diff --git a/README.md b/README.md index a7cca06..bad8ea0 100644 --- a/README.md +++ b/README.md @@ -241,6 +241,24 @@ rm -f file.txt # Falls through to standard rm -f | `upgrade` | Full system upgrade: `paru -Syu --noconfirm` | | `cleanup` | Log and remove orphaned packages | +### Dependency Management + +`fish-deps` is a unified command for checking, installing, and updating all tools this config depends on. + +| Command | Description | +|---|---| +| `fish-deps` / `fish-deps status` | Show installed/missing status for all deps, grouped by tier | +| `fish-deps install` | Interactively install each missing dep (prompts per-dep, prompts method when multiple exist) | +| `fish-deps update` | Update all installed deps using their preferred install method | +| `fish-deps sync` | Install missing deps then update installed ones | +| `fzf-update` | Install or upgrade fzf from git HEAD into `~/.fzf` (guarantees the latest build) | +| `check_fish_deps` | Legacy alias — delegates to `fish-deps status` | + +Install method priority: **git+cargo source build** (fish) → **cargo** (other Rust tools, gets latest crate) → **system PM** (paru/apt/brew/etc.) → **git clone** (fzf) → **curl installer** (starship, fisher) → **pipx** (Python tools). When multiple methods are available for a tool, you are prompted to choose. + +> [!NOTE] +> Upgrading Fish from source requires **cargo** and **[uv](https://docs.astral.sh/uv/)**. Both are managed dependencies — `fish-deps install` will offer to install them before attempting the Fish build. If both are unavailable, `fish-deps update` falls back to the system package manager. + ### Docker | Function | Description | @@ -476,20 +494,27 @@ Named context shortcuts (e.g. `dcr`, `dck`) live in `~/.config/.user-dots/fish/l ### Required -| Tool | Purpose | -|---|---| -| [Fish](https://fishshell.com/) | Shell | -| [Fisher](https://github.com/jorgebucaran/fisher) | Plugin manager | -| [Starship](https://starship.rs/) | Prompt | -| [fzf](https://github.com/junegunn/fzf) | Fuzzy finder | -| [zoxide](https://github.com/ajeetdsouza/zoxide) | Smart directory jumper | -| [direnv](https://direnv.net/) | Per-directory env loading | -| [paru](https://github.com/Morganamilo/paru) | AUR helper | +| Tool | Version | Purpose | +|---|---|---| +| [uv](https://docs.astral.sh/uv/) | any | Python runner (needed to build Fish from source) | +| [Rust / cargo](https://www.rust-lang.org/tools/install) | any | Installs Rust-based tools; required to build Fish | +| [Fish](https://fishshell.com/) | **≥ 4.0** | Shell | +| [Fisher](https://github.com/jorgebucaran/fisher) | any | Plugin manager | +| [Starship](https://starship.rs/) | any | Prompt | +| [fzf](https://github.com/junegunn/fzf) | any | Fuzzy finder | +| [zoxide](https://github.com/ajeetdsouza/zoxide) | any | Smart directory jumper | +| [direnv](https://direnv.net/) | any | Per-directory env loading | + +> [!WARNING] +> Fish **4.0 or newer is required.** This config uses `test` syntax and other constructs that are incompatible with Fish 3.x. Older versions will produce errors on startup. +> Run `fish-deps install` or `fish-deps update` to upgrade — it will install `uv` and `cargo` automatically if missing, then build the latest Fish from source. ### Recommended | Tool | Replaces | |---|---| +| [Rust / cargo](https://www.rust-lang.org/tools/install) | Build tool for Rust-based CLI replacements below | +| [paru](https://github.com/Morganamilo/paru) / [yay](https://github.com/Jguer/yay) | AUR helper (Arch only) | | [eza](https://github.com/eza-community/eza) | `ls` (preferred) | | [lsd](https://github.com/lsd-rs/lsd) | `ls` (fallback) | | [bat](https://github.com/sharkdp/bat) | `cat` | diff --git a/functions/_fish_deps_catalog.fish b/functions/_fish_deps_catalog.fish new file mode 100644 index 0000000..3f4cea0 --- /dev/null +++ b/functions/_fish_deps_catalog.fish @@ -0,0 +1,55 @@ +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later + +# Populates parallel arrays describing every managed dependency. +# Callers must invoke this function before accessing _fdc_* arrays. +# +# Array layout (same index across all sets): +# _fdc_bins — binary name (what `type -q` checks) +# _fdc_tiers — req | int | rec +# _fdc_cargo — cargo crate name, or "" if not on crates.io +# _fdc_pm — system PM package name, or "" if not in repos +# _fdc_special — special install key: rustup-installer | fisher-bootstrap | +# fzf-update | paru-build | pipx | curl-installer | +# git-cargo-fish | curl-uv | "" (none) +# +# uv and cargo are listed first so both are available before fish and other Rust tools. +function _fish_deps_catalog + set -g _fdc_bins \ + uv cargo fish fisher starship fzf zoxide direnv paru \ + wakatime tailscale \ + eza lsd bat btop dust duf prettyping most rg lazygit lazydocker trash kitty wezterm + + set -g _fdc_tiers \ + req req req req req req req req rec \ + int int \ + rec rec rec rec rec rec rec rec rec rec rec rec rec rec + + set -g _fdc_cargo \ + "" "" "" "" starship "" zoxide "" "" \ + "" "" \ + eza lsd bat "" du-dust "" "" "" ripgrep "" "" trashy "" "" + + set -g _fdc_pm \ + uv cargo fish "" starship fzf zoxide direnv "" \ + wakatime tailscale \ + eza lsd bat btop dust duf prettyping most ripgrep lazygit lazydocker trash kitty wezterm + + set -g _fdc_special \ + curl-uv rustup-installer git-cargo-fish fisher-bootstrap curl-installer fzf-update "" "" paru-build \ + wakatime-binary "" \ + "" "" "" "" "" "" "" "" "" "" curl-lazydocker "" "" "" +end + +# Returns the index (1-based) of $argv[1] in the catalog, or "" if not found. +function _fish_deps_catalog_idx --argument-names bin + _fish_deps_catalog + set -l i 1 + for b in $_fdc_bins + if test "$b" = "$bin" + echo $i + return + end + set i (math $i + 1) + end +end diff --git a/functions/_fish_deps_detect_pm.fish b/functions/_fish_deps_detect_pm.fish new file mode 100644 index 0000000..a118140 --- /dev/null +++ b/functions/_fish_deps_detect_pm.fish @@ -0,0 +1,13 @@ +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later + +# Detect the first available system package manager. +function _fish_deps_detect_pm + for pm in paru yay pacman apt brew pkg dnf yum + if type -q $pm + echo $pm + return + end + end + echo "" +end diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish new file mode 100644 index 0000000..03db4e3 --- /dev/null +++ b/functions/_fish_deps_install.fish @@ -0,0 +1,265 @@ +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later + +# Interactively install missing deps. +# For each missing dep: prompts yes/no, then prompts install method when multiple exist. +function _fish_deps_install + _fish_deps_catalog + + set -l pm (_fish_deps_detect_pm) + set -l installed_any 0 + + set -l i 1 + for bin in $_fdc_bins + # Determine if this dep needs attention: missing, or fish < 4.0 + set -l needs_install 0 + set -l upgrade_label Install + if not type -q $bin + set needs_install 1 + else if test "$bin" = fish + set -l _major (fish --version 2>&1 | string match -r 'version (\d+)')[2] + if test -n "$_major"; and test "$_major" -lt 4 + set needs_install 1 + set upgrade_label "Upgrade" + end + end + + if test $needs_install -eq 1 + set -l cargo_crate $_fdc_cargo[$i] + set -l pm_pkg $_fdc_pm[$i] + set -l special $_fdc_special[$i] + + # Build list of available install methods + set -l methods + set -l method_labels + + # Cargo — preferred for Rust tools; gets the latest crate version + if test -n "$cargo_crate" + if type -q cargo + set -a methods cargo + set -a method_labels "cargo ($cargo_crate)" + else + set_color brblack + echo " note: cargo not found — install cargo first for the latest $bin" + set_color normal + end + end + + # Preferred special methods — listed before system PM so they are the default + switch $special + case curl-uv + set -a methods special-uv + set -a method_labels "curl installer (official script)" + case git-cargo-fish + if type -q cargo; and type -q uv + set -a methods special-git-cargo-fish + set -a method_labels "build from source (git + cargo)" + else + set_color brblack + set -l _need + type -q cargo; or set -a _need cargo + type -q uv; or set -a _need uv + echo " note: "(string join " and " $_need)" not found — install them first to build fish from source" + set_color normal + end + case rustup-installer + set -a methods special-rustup + set -a method_labels "rustup installer (curl | sh)" + case curl-lazydocker + set -a methods special-lazydocker + set -a method_labels "curl installer (official script)" + case wakatime-binary + set -a methods special-wakatime + set -a method_labels "binary download (github releases)" + end + + # System PM — after cargo and preferred specials + if test -n "$pm_pkg"; and test -n "$pm" + set -a methods pm + set -a method_labels "$pm ($pm_pkg)" + end + + # Supplemental special methods (fallbacks, Arch-only, etc.) + switch $special + case fzf-update + set -a methods special-fzf + set -a method_labels "git clone (~/.fzf)" + case fisher-bootstrap + set -a methods special-fisher + set -a method_labels "curl bootstrap (fisher)" + case curl-installer + set -a methods special-curl + set -a method_labels "curl installer" + case paru-build + # Only offered on Arch-based systems where pacman is present + if type -q yay + set -a methods special-yay-paru + set -a method_labels "yay -S paru" + end + if type -q pacman + set -a methods special-paru + set -a method_labels "build from AUR (makepkg)" + end + case pipx + if type -q pipx + set -a methods special-pipx + set -a method_labels "pipx ($bin)" + else if type -q pip + set -a methods special-pip + set -a method_labels "pip install --user ($bin)" + end + end + + if test (count $methods) -eq 0 + set_color yellow + echo " $bin: no install method available on this system — skipping" + set_color normal + set i (math $i + 1) + continue + end + + # Prompt: install/upgrade this dep? + read -l -P (set_color cyan)"$upgrade_label $bin?"(set_color normal)" [Y/n] " _reply + if test "$_reply" = n; or test "$_reply" = N + set i (math $i + 1) + continue + end + + # Choose install method + set -l chosen_method $methods[1] + if test (count $methods) -gt 1 + echo " Available methods:" + set -l m 1 + for lbl in $method_labels + set_color brblack; echo -n " $m) "; set_color normal + echo $lbl + set m (math $m + 1) + end + read -l -P " Choose [1-"(count $methods)"] (default 1 = $method_labels[1]): " _choice + if string match -qr '^\d+$' "$_choice"; and test "$_choice" -ge 1; and test "$_choice" -le (count $methods) + set chosen_method $methods[$_choice] + end + else + set_color brblack; echo " "(string lower $upgrade_label)"ing via $method_labels[1]"; set_color normal + end + + # Execute chosen method + switch $chosen_method + case cargo + cargo install $cargo_crate + case pm + _fish_deps_pm_install $pm_pkg + case special-rustup + curl https://sh.rustup.rs -sSf | sh + # Add cargo to PATH for the rest of this session without restarting. + # Try CARGO_HOME first (set in config.fish), then the rustup default. + for _d in "$CARGO_HOME/bin" "$HOME/.cargo/bin" + if test -d "$_d" + fish_add_path "$_d" + break + end + end + if not type -q cargo + set_color yellow + echo " cargo not yet in PATH — restart your shell if subsequent installs fail." + set_color normal + end + case special-lazydocker + curl https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | bash + case special-wakatime + set -l _arch (uname -m) + switch $_arch + case x86_64 + set _arch amd64 + case aarch64 arm64 + set _arch arm64 + case armv7l + set _arch arm + case '*' + set _arch amd64 + end + set -l _zip "wakatime-cli-linux-$_arch.zip" + set -l _bin_src "wakatime-cli-linux-$_arch" + set -l _wt_dir "$HOME/.config/wakatime" + set -l _wt_bin "$_wt_dir/wakatime" + set -l _tmpdir (mktemp -d) + curl -L "https://github.com/wakatime/wakatime-cli/releases/latest/download/$_zip" \ + -o "$_tmpdir/$_zip" + and unzip -o "$_tmpdir/$_zip" -d "$_tmpdir" + and mkdir -p "$_wt_dir" "$HOME/.local/bin" + and cp "$_tmpdir/$_bin_src" "$_wt_bin" + and chmod +x "$_wt_bin" + and ln -sf "$_wt_bin" "$HOME/.local/bin/wakatime" + rm -rf "$_tmpdir" + case special-fzf + fzf-update + case special-fisher + curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source + fisher update + case special-curl + if test "$bin" = starship + curl -sS https://starship.rs/install.sh | sh + end + case special-yay-paru + yay -S --noconfirm paru + case special-paru + set -l _build_dir (mktemp -d) + git clone https://aur.archlinux.org/paru.git $_build_dir + and pushd $_build_dir + and makepkg -si --noconfirm + and popd + rm -rf $_build_dir + case special-uv + curl -LsSf https://astral.sh/uv/install.sh | sh + # Add uv to PATH for the rest of this session + for _d in "$HOME/.local/bin" "$HOME/.cargo/bin" + if test -d "$_d" + fish_add_path "$_d" + break + end + end + if not type -q uv + set_color yellow + echo " uv not yet in PATH — restart your shell if subsequent installs fail." + set_color normal + end + case special-git-cargo-fish + set -l _tmpdir (mktemp -d) + set -l _build_ok 0 + git clone https://github.com/fish-shell/fish-shell "$_tmpdir" + and begin + set -l _tag (git -C "$_tmpdir" tag --list 'fish-*' --sort=version:refname | tail -1) + test -n "$_tag"; and git -C "$_tmpdir" checkout "$_tag" + true + end + and pushd "$_tmpdir" + and uv run --no-managed-python cargo install --path . + and set _build_ok 1 + popd 2>/dev/null + rm -rf "$_tmpdir" + test $_build_ok -eq 1 + case special-pipx + pipx install $bin + case special-pip + pip install --user $bin + end + + if test $status -eq 0 + set installed_any 1 + set_color green; echo " $bin "(string lower $upgrade_label)"ed."; set_color normal + if test "$bin" = fish + set_color yellow + echo " Fish upgraded — restart your shell to use the new version." + set_color normal + end + else + set_color red; echo " $bin "(string lower $upgrade_label)" failed."; set_color normal + end + end + set i (math $i + 1) + end + + if test $installed_any -eq 0 + echo "Nothing to install." + end +end diff --git a/functions/_fish_deps_pm_install.fish b/functions/_fish_deps_pm_install.fish new file mode 100644 index 0000000..7279a07 --- /dev/null +++ b/functions/_fish_deps_pm_install.fish @@ -0,0 +1,28 @@ +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later + +# Install a package via the system PM. +# Usage: _fish_deps_pm_install +function _fish_deps_pm_install --argument-names pkg + set -l pm (_fish_deps_detect_pm) + if test -z "$pm" + echo "No supported package manager found." >&2 + return 1 + end + switch $pm + case paru yay + $pm -S --noconfirm $pkg + case pacman + sudo pacman -S --noconfirm $pkg + case apt + sudo apt install -y $pkg + case brew + brew install $pkg + case pkg + sudo pkg install -y $pkg + case dnf + sudo dnf install -y $pkg + case yum + sudo yum install -y $pkg + end +end diff --git a/functions/_fish_deps_pm_upgrade.fish b/functions/_fish_deps_pm_upgrade.fish new file mode 100644 index 0000000..0d4efe2 --- /dev/null +++ b/functions/_fish_deps_pm_upgrade.fish @@ -0,0 +1,28 @@ +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later + +# Upgrade an already-installed package via the system PM. +# Usage: _fish_deps_pm_upgrade +function _fish_deps_pm_upgrade --argument-names pkg + set -l pm (_fish_deps_detect_pm) + if test -z "$pm" + echo "No supported package manager found." >&2 + return 1 + end + switch $pm + case paru yay + $pm -S --noconfirm $pkg + case pacman + sudo pacman -S --noconfirm $pkg + case apt + sudo apt install --only-upgrade -y $pkg + case brew + brew upgrade $pkg + case pkg + sudo pkg upgrade -y $pkg + case dnf + sudo dnf upgrade -y $pkg + case yum + sudo yum update -y $pkg + end +end diff --git a/functions/_fish_deps_status.fish b/functions/_fish_deps_status.fish new file mode 100644 index 0000000..e9e66b0 --- /dev/null +++ b/functions/_fish_deps_status.fish @@ -0,0 +1,50 @@ +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later + +# Print colored installed/missing status for all deps, grouped by tier. +function _fish_deps_status + _fish_deps_catalog + + function __fds_print_dep --argument-names bin tier + if type -q $bin + # Special version check: fish < 4.0 is functionally incompatible + if test "$bin" = fish + set -l _major (fish --version 2>&1 | string match -r 'version (\d+)')[2] + if test -n "$_major"; and test "$_major" -lt 4 + set -l _ver (fish --version 2>&1 | string replace 'fish, ' '') + set_color yellow; echo -n " ⚠ "; set_color normal + echo -n "$bin " + set_color brblack; echo "($_ver — upgrade to 4.0+ required)"; set_color normal + return + end + end + set_color green; echo -n " ✓ "; set_color normal + echo -n "$bin " + set_color brblack; echo "(Found at "(type -p $bin)")"; set_color normal + else if test "$tier" = rec + set_color yellow; echo -n " ⚠ "; set_color normal + echo -n "$bin " + set_color brblack; echo "(Not installed)"; set_color normal + else + set_color red; echo -n " ✗ "; set_color normal + echo -n "$bin " + set_color brblack; echo "(Not installed)"; set_color normal + end + end + + for tier_label in "Required Dependencies:req" "Integrations:int" "Recommended Dependencies:rec" + set -l label (string split : $tier_label)[1] + set -l tier (string split : $tier_label)[2] + set_color cyan; echo $label; set_color normal + set -l i 1 + for bin in $_fdc_bins + if test "$_fdc_tiers[$i]" = $tier + __fds_print_dep $bin $tier + end + set i (math $i + 1) + end + echo "" + end + + functions -e __fds_print_dep +end diff --git a/functions/_fish_deps_update.fish b/functions/_fish_deps_update.fish new file mode 100644 index 0000000..1ae31f7 --- /dev/null +++ b/functions/_fish_deps_update.fish @@ -0,0 +1,177 @@ +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later + +# Update all installed deps using their known install method. +# Priority: cargo > system PM > special (fzf-update, fisher, pipx). +function _fish_deps_update + _fish_deps_catalog + + set -l pm (_fish_deps_detect_pm) + set -l updated_any 0 + + # Fisher plugins — always update if fisher is present + if type -q fisher + echo "Updating fisher plugins..." + fisher update + set updated_any 1 + end + + set -l i 1 + for bin in $_fdc_bins + # Skip fisher itself (handled above) and tools that aren't installed + if test "$bin" = fisher; or not type -q $bin + set i (math $i + 1) + continue + end + + set -l cargo_crate $_fdc_cargo[$i] + set -l pm_pkg $_fdc_pm[$i] + set -l special $_fdc_special[$i] + + # cargo: update via rustup + if test "$special" = rustup-installer + if type -q rustup + echo "Updating $bin..." + rustup update + set updated_any 1 + end + set i (math $i + 1) + continue + end + + # fzf: always use fzf-update (git-based) + if test "$special" = fzf-update + echo "Updating $bin..." + fzf-update + set updated_any 1 + set i (math $i + 1) + continue + end + + # lazydocker: re-run the official install/update script + if test "$special" = curl-lazydocker + echo "Updating $bin..." + curl https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | bash + set updated_any 1 + set i (math $i + 1) + continue + end + + # wakatime: re-download the binary from github releases + if test "$special" = wakatime-binary + echo "Updating $bin..." + set -l _arch (uname -m) + switch $_arch + case x86_64; set _arch amd64 + case aarch64 arm64; set _arch arm64 + case armv7l; set _arch arm + case '*'; set _arch amd64 + end + set -l _zip "wakatime-cli-linux-$_arch.zip" + set -l _bin_src "wakatime-cli-linux-$_arch" + set -l _wt_bin "$HOME/.config/wakatime/wakatime" + set -l _tmpdir (mktemp -d) + curl -L "https://github.com/wakatime/wakatime-cli/releases/latest/download/$_zip" \ + -o "$_tmpdir/$_zip" + and unzip -o "$_tmpdir/$_zip" -d "$_tmpdir" + and cp "$_tmpdir/$_bin_src" "$_wt_bin" + and chmod +x "$_wt_bin" + rm -rf "$_tmpdir" + and set updated_any 1 + set i (math $i + 1) + continue + end + + # pipx tools + if test "$special" = pipx + if type -q pipx + echo "Updating $bin..." + pipx upgrade $bin + set updated_any 1 + end + set i (math $i + 1) + continue + end + + # uv: use built-in self-updater + if test "$special" = curl-uv + echo "Updating $bin..." + uv self update + set updated_any 1 + set i (math $i + 1) + continue + end + + # fish: prefer build from source via git + cargo; fall back to PM + if test "$special" = git-cargo-fish + if type -q cargo; and type -q uv + echo "Updating $bin..." + set -l _tmpdir (mktemp -d) + set -l _build_ok 0 + git clone https://github.com/fish-shell/fish-shell "$_tmpdir" + and begin + set -l _tag (git -C "$_tmpdir" tag --list 'fish-*' --sort=version:refname | tail -1) + test -n "$_tag"; and git -C "$_tmpdir" checkout "$_tag" + true + end + and pushd "$_tmpdir" + and uv run --no-managed-python cargo install --path . + and set _build_ok 1 + popd 2>/dev/null + rm -rf "$_tmpdir" + if test $_build_ok -eq 1 + set updated_any 1 + set_color yellow + echo " Fish updated — restart your shell to use the new version." + set_color normal + end + else if test -n "$pm_pkg"; and test -n "$pm" + echo "Updating $bin (cargo/uv unavailable, using system PM)..." + _fish_deps_pm_upgrade $pm_pkg + set updated_any 1 + set_color yellow + echo " Fish updated — restart your shell to use the new version." + set_color normal + else + set_color yellow + echo " fish: cannot update — install cargo and uv to build from source" + set_color normal + end + set i (math $i + 1) + continue + end + + # curl-installer tools (starship etc.): re-run install script, which upgrades in place + if test "$special" = curl-installer + if test "$bin" = starship + echo "Updating $bin..." + curl -sS https://starship.rs/install.sh | sh -s -- --yes + set updated_any 1 + end + set i (math $i + 1) + continue + end + + # Cargo: prefer for Rust tools + if test -n "$cargo_crate"; and type -q cargo + echo "Updating $bin..." + cargo install --force $cargo_crate + set updated_any 1 + set i (math $i + 1) + continue + end + + # System PM fallback + if test -n "$pm_pkg"; and test -n "$pm" + echo "Updating $bin..." + _fish_deps_pm_upgrade $pm_pkg + set updated_any 1 + end + + set i (math $i + 1) + end + + if test $updated_any -eq 0 + echo "Nothing to update." + end +end diff --git a/functions/check_fish_deps.fish b/functions/check_fish_deps.fish index 4ca9b4b..04470c5 100644 --- a/functions/check_fish_deps.fish +++ b/functions/check_fish_deps.fish @@ -1,50 +1,7 @@ # Copyright (C) 2026 Rootiest # SPDX-License-Identifier: AGPL-3.0-or-later -# Check all fish-related dependencies +# Thin wrapper kept for backwards compatibility. function check_fish_deps --description 'Check all fish-related dependencies' - set -l required fish fisher starship fzf zoxide direnv paru - set -l integrations wakatime tailscale - set -l recommended eza lsd bat btop dust duf prettyping most rg lazygit lazydocker trash kitty wezterm - - function __print_dep - set -l dep $argv[1] - if type -q $dep - set_color green - echo -n "  " - set_color normal - echo -n "$dep " - set_color brblack - echo "(Found at "(type -p $dep)")" - set_color normal - else - set_color red - echo -n "  " - set_color normal - echo -n "$dep " - set_color brblack - echo "(Not installed)" - set_color normal - end - end - - set_color cyan; echo "Required Dependencies:"; set_color normal - for dep in $required - __print_dep $dep - end - echo "" - - set_color cyan; echo "Integrations:"; set_color normal - for dep in $integrations - __print_dep $dep - end - echo "" - - set_color cyan; echo "Recommended Dependencies:"; set_color normal - for dep in $recommended - __print_dep $dep - end - echo "" - - functions -e __print_dep + fish-deps status end diff --git a/functions/fish-deps.fish b/functions/fish-deps.fish new file mode 100644 index 0000000..47099e5 --- /dev/null +++ b/functions/fish-deps.fish @@ -0,0 +1,41 @@ +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later + +function fish-deps --description 'Manage fish shell dependencies' + set -l subcmd $argv[1] + + switch $subcmd + case status '' + _fish_deps_status + case install + _fish_deps_install + case update + _fish_deps_update + case sync + echo "=== Installing missing deps ===" + _fish_deps_install + echo "" + echo "=== Updating installed deps ===" + _fish_deps_update + case '*' + set_color red + echo "Unknown subcommand: $subcmd" + set_color normal + echo "" + __fish_deps_help + return 1 + end +end + +function __fish_deps_help + set_color cyan; echo "fish-deps — manage fish shell dependencies"; set_color normal + echo "" + echo "Usage:" + echo " fish-deps [status] Check installed/missing deps (default)" + echo " fish-deps install Install missing deps interactively" + echo " fish-deps update Update all installed deps" + echo " fish-deps sync Install missing, then update all" + echo "" + echo "Install method priority: cargo > system PM > git/curl/pipx" + echo "When multiple methods are available, you will be prompted to choose." +end diff --git a/functions/parur.fish b/functions/parur.fish index dddf658..3d0a249 100644 --- a/functions/parur.fish +++ b/functions/parur.fish @@ -3,16 +3,23 @@ # Interactively search and remove an installed package using fzf function parur --description 'Interactively search and remove an installed package using fzf' - # 1. Use command substitution to get the package list from fzf + set -l aur "" + if type -q paru + set aur paru + else if type -q yay + set aur yay + else + echo "No AUR helper found (install paru or yay)" >&2 + return 1 + end + set -l pkg_list ( pacman -Qqs \ | fzf --preview 'pacman -Qi {}' --multi ) - # 2. Check if a package was selected. if test (count $pkg_list) -gt 0 - # 3. Pass the selected packages directly to paru -R - paru -R $pkg_list + $aur -R $pkg_list else echo "No packages selected for removal." end diff --git a/functions/pkg.fish b/functions/pkg.fish index 2732deb..6b9dd57 100644 --- a/functions/pkg.fish +++ b/functions/pkg.fish @@ -1,10 +1,15 @@ # Copyright (C) 2026 Rootiest # SPDX-License-Identifier: AGPL-3.0-or-later -# Function for installing packages with paru. -# This runs `paru` with the `-S` flag to install one or more packages. -# The `$argv` variable passes all arguments given to the `pkg` function -# directly to the `paru` command. -function pkg --wraps='paru' --description 'directly to the `paru` command.' - paru -S $argv +function pkg --description 'Install packages via paru or yay' + set -l aur "" + if type -q paru + set aur paru + else if type -q yay + set aur yay + else + echo "No AUR helper found (install paru or yay)" >&2 + return 1 + end + $aur -S $argv end diff --git a/functions/search.fish b/functions/search.fish index 823fb97..35f28d7 100644 --- a/functions/search.fish +++ b/functions/search.fish @@ -1,10 +1,15 @@ # Copyright (C) 2026 Rootiest # SPDX-License-Identifier: AGPL-3.0-or-later -# Function for searching for packages to install with paru. -# This runs `paru` with the search flags. -# The `$argv` variable passes all arguments given to the `search` function -# directly to the `paru` command. -function search --wraps='paru' --description 'directly to the `paru` command.' - paru $argv +function search --description 'Search/install packages interactively via paru or yay' + set -l aur "" + if type -q paru + set aur paru + else if type -q yay + set aur yay + else + echo "No AUR helper found (install paru or yay)" >&2 + return 1 + end + $aur $argv end diff --git a/functions/upgrade.fish b/functions/upgrade.fish index 59c1ff9..7fd00cf 100644 --- a/functions/upgrade.fish +++ b/functions/upgrade.fish @@ -1,9 +1,15 @@ # Copyright (C) 2026 Rootiest # SPDX-License-Identifier: AGPL-3.0-or-later -# Function for upgrading the system with paru. -# This runs `paru` with the `-Syu` flags to sync, refresh, and upgrade all -# packages, and adds `--no-confirm` to bypass the confirmation prompt. -function upgrade --wraps='paru' --description 'packages, and adds `--no-confirm` to bypass the confirmation prompt.' - paru -Syu --noconfirm +function upgrade --description 'Full system upgrade via paru or yay' + set -l aur "" + if type -q paru + set aur paru + else if type -q yay + set aur yay + else + echo "No AUR helper found (install paru or yay)" >&2 + return 1 + end + $aur -Syu --noconfirm end diff --git a/integrations/fzf.fish b/integrations/fzf.fish index b3ee476..8bd410a 100644 --- a/integrations/fzf.fish +++ b/integrations/fzf.fish @@ -221,13 +221,18 @@ function fzf_key_bindings end # Prepend the options to allow user customizations - # wrap-word requires the same newer fzf as bg-transform; fall back to plain wrap - set -l _fzf_wrap_opt wrap - test "$_fzf_transform_action" = bg-transform; and set _fzf_wrap_opt wrap-word - set -p -- FZF_DEFAULT_OPTS \ - '--bind="focus,resize:'$_fzf_transform_action':if test \\"$FZF_COLUMNS\\" -gt 100 -a \\\\( \\"$FZF_SELECT_COUNT\\" -gt 0 -o \\\\( -z \\"$FZF_WRAP\\" -a (string length -- {}) -gt (math $FZF_COLUMNS - 4) \\\\) -o (string collect -- {2..} | fish_indent | count) -gt 1 \\\\); echo show-preview; else echo hide-preview; end"' \ - '--preview="string collect -- (test \\"$FZF_SELECT_COUNT\\" -gt 0; and string collect -- {+2..}) \\"\\n# \\"'$date_cmd' {2..} | fish_indent --ansi"' \ - '--preview-window="right,50%,'$_fzf_wrap_opt',follow,info,hidden"' + if test "$_fzf_transform_action" = bg-transform + # Newer fzf: dynamic show/hide preview based on terminal width + set -p -- FZF_DEFAULT_OPTS \ + '--bind="focus,resize:bg-transform:if test \\"$FZF_COLUMNS\\" -gt 100 -a \\\\( \\"$FZF_SELECT_COUNT\\" -gt 0 -o \\\\( -z \\"$FZF_WRAP\\" -a (string length -- {}) -gt (math $FZF_COLUMNS - 4) \\\\) -o (string collect -- {2..} | fish_indent | count) -gt 1 \\\\); echo show-preview; else echo hide-preview; end"' \ + '--preview="string collect -- (test \\"$FZF_SELECT_COUNT\\" -gt 0; and string collect -- {+2..}) \\"\\n# \\"'$date_cmd' {2..} | fish_indent --ansi"' \ + '--preview-window="right,50%,wrap-word,follow,info,hidden"' + else + # Older fzf: static preview; focus/resize events not reliably supported + set -p -- FZF_DEFAULT_OPTS \ + '--preview="string collect -- (test \\"$FZF_SELECT_COUNT\\" -gt 0; and string collect -- {+2..}) \\"\\n# \\"'$date_cmd' {2..} | fish_indent --ansi"' \ + '--preview-window="right,50%,wrap,follow,info"' + end end set -lx FZF_DEFAULT_OPTS_FILE