#!/usr/bin/env bash # # Build and install the furst toolset. Safe to re-run: it never overwrites a # config you have edited, and every system-changing step can be skipped. # # ./install.sh --help set -euo pipefail PREFIX="${HOME}/.local/bin" CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/furst" CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/furst" UNIT_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user" DESKTOP="${XDG_DATA_HOME:-$HOME/.local/share}/applications/furst.desktop" BINARIES=(furst furst-read furst-serve furst-proxy) HANDLERS=(mpv yt-dlp zathura nsxiv surf firefox) MODE=install DO_BUILD=1 DO_LISTS=1 DO_SERVICE=1 DO_BROWSER=ask PURGE=0 if [ -t 1 ]; then B=$'\033[1m'; DIM=$'\033[2m'; GREEN=$'\033[32m'; YELLOW=$'\033[33m'; RED=$'\033[31m'; R=$'\033[0m' else B=; DIM=; GREEN=; YELLOW=; RED=; R= fi step() { printf '\n%s==>%s %s%s%s\n' "$GREEN" "$R" "$B" "$1" "$R"; } info() { printf ' %s\n' "$1"; } skip() { printf ' %s%s%s\n' "$DIM" "$1" "$R"; } warn() { printf ' %s!%s %s\n' "$YELLOW" "$R" "$1"; } die() { printf '\n%serror:%s %s\n' "$RED" "$R" "$1" >&2; exit 1; } usage() { cat <<'EOF' install.sh — build and install the furst toolset USAGE ./install.sh [OPTIONS] OPTIONS --prefix where to install binaries (default ~/.local/bin) --no-build install from an existing target/release build --no-lists skip downloading the proxy blocklists --no-service skip the systemd user service for the proxy --no-default-browser do not register furst as the default browser -y, --yes answer every prompt with yes --uninstall remove binaries, service and desktop entry --purge with --uninstall, also remove configs and caches -h, --help this The install never overwrites an existing config file, so re-running it after editing your rules is safe. EOF } while [ $# -gt 0 ]; do case "$1" in --prefix) PREFIX="${2:?--prefix needs a directory}"; shift 2 ;; --no-build) DO_BUILD=0; shift ;; --no-lists) DO_LISTS=0; shift ;; --no-service) DO_SERVICE=0; shift ;; --no-default-browser) DO_BROWSER=no; shift ;; -y|--yes) DO_BROWSER=yes; shift ;; --uninstall) MODE=uninstall; shift ;; --purge) PURGE=1; shift ;; -h|--help) usage; exit 0 ;; *) die "unknown option $1 (--help for usage)" ;; esac done # ---------------------------------------------------------------- uninstall --- if [ "$MODE" = uninstall ]; then step "Removing the service" if command -v systemctl >/dev/null 2>&1; then systemctl --user disable --now furst-proxy.service 2>/dev/null || true rm -f "$UNIT_DIR/furst-proxy.service" "$UNIT_DIR/furst-serve.service" systemctl --user daemon-reload 2>/dev/null || true info "stopped and removed" else skip "no systemctl" fi step "Removing binaries" for b in "${BINARIES[@]}"; do if [ -e "$PREFIX/$b" ]; then rm -f "$PREFIX/$b"; info "removed $PREFIX/$b"; fi done step "Removing the desktop entry" rm -f "$DESKTOP" info "removed $DESKTOP" warn "your default browser is now unset — pick one in your desktop settings," warn "or run: xdg-settings set default-web-browser firefox.desktop" if [ "$PURGE" = 1 ]; then step "Purging configs and caches" rm -rf "$CONFIG_DIR" "$CACHE_DIR" "${XDG_CACHE_HOME:-$HOME/.cache}/furst-read" info "removed $CONFIG_DIR and caches" else step "Kept" info "$CONFIG_DIR and caches — remove with --uninstall --purge" fi printf '\n%sUninstalled.%s\n\n' "$B" "$R" exit 0 fi # ------------------------------------------------------------------- build --- cd "$(dirname "$0")" if [ "$DO_BUILD" = 1 ]; then step "Building" command -v cargo >/dev/null 2>&1 || die "cargo not found — install rust first" info "$(cargo --version)" # --workspace matters: the root package is only furst, so a bare build would # silently skip the other three. cargo build --release --workspace info "built 4 binaries" else step "Skipping build" fi for b in "${BINARIES[@]}"; do [ -x "target/release/$b" ] || die "target/release/$b missing — run without --no-build" done # ----------------------------------------------------------------- install --- step "Installing to $PREFIX" mkdir -p "$PREFIX" for b in "${BINARIES[@]}"; do install -m755 "target/release/$b" "$PREFIX/$b" info "$b $(du -h "$PREFIX/$b" | cut -f1)" done case ":$PATH:" in *":$PREFIX:"*) ;; *) warn "$PREFIX is not on your \$PATH — add this to ~/.zshrc:" warn " export PATH=\"$PREFIX:\$PATH\"" ;; esac export PATH="$PREFIX:$PATH" # ----------------------------------------------------------------- configs --- step "Writing starter configs" mkdir -p "$CONFIG_DIR" init_config() { local file="$1" cmd="$2" if [ -e "$CONFIG_DIR/$file" ]; then skip "$file already exists, left alone" else "$PREFIX/$cmd" --init >/dev/null && info "$file" fi } init_config rules.toml furst init_config home.toml furst-serve init_config proxy.toml furst-proxy # ---------------------------------------------------------------- handlers --- step "Checking handlers" missing=() for h in "${HANDLERS[@]}"; do command -v "$h" >/dev/null 2>&1 || missing+=("$h") done if [ ${#missing[@]} -eq 0 ]; then info "all present" else warn "not installed: ${missing[*]}" warn "rules naming them fall through to the next handler; install with:" warn " sudo pacman -S mpv yt-dlp zathura zathura-pdf-mupdf nsxiv surf" fi # --------------------------------------------------------------- blocklists --- if [ "$DO_LISTS" = 1 ]; then step "Fetching blocklists" if "$PREFIX/furst-proxy" --update 2>&1 | sed 's/^/ /'; then :; else warn "could not fetch — the proxy will run with only its built-in rules" fi else step "Skipping blocklists" skip "run 'furst-proxy --update' later" fi # ------------------------------------------------------------------ service --- if [ "$DO_SERVICE" = 1 ] && command -v systemctl >/dev/null 2>&1; then step "Installing the proxy service" mkdir -p "$UNIT_DIR" cat > "$UNIT_DIR/furst-proxy.service" < "$UNIT_DIR/furst-serve.service" </dev/null || true if systemctl --user enable --now furst-proxy.service 2>/dev/null; then info "furst-proxy.service enabled and started" else warn "could not start the service — run it yourself with: furst-proxy &" fi skip "furst-serve.service written but not enabled (the reader autostarts)" else step "Skipping the service" skip "start the proxy yourself: furst-proxy &" fi # ---------------------------------------------------------- default browser --- step "Default browser" if [ "$DO_BROWSER" = ask ]; then if [ -t 0 ]; then printf ' Register furst as your default browser? [y/N] ' read -r reply case "$reply" in [yY]*) DO_BROWSER=yes ;; *) DO_BROWSER=no ;; esac else DO_BROWSER=no fi fi if [ "$DO_BROWSER" = yes ]; then "$PREFIX/furst" --install 2>&1 | sed 's/^/ /' else skip "not changed — run 'furst --install' when you want it" fi # -------------------------------------------------------------------- done --- cat < Network Settings > Manual, 127.0.0.1 port 8228, and tick "Also use this proxy for HTTPS". Reader home http://127.0.0.1:7714/ Proxy status http://furst.proxy/ Read ${B}GUIDE.md${R} next. The command to remember is: furst --explain EOF