From f09006846b91daf862f3288246ce69095a8c12dc Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 21:47:20 -0400 Subject: [PATCH 01/21] fix(fzf): drop focus/resize bind entirely on older fzf builds Older fzf (pre-0.62) does not support the focus and resize events in bind actions, causing a startup error when --fish or the bundled integration is sourced. Split the FZF_DEFAULT_OPTS preview block into an if/else: newer fzf gets the dynamic bg-transform bind with wrap-word; older fzf gets a static preview window with plain wrap and no event bind. --- integrations/fzf.fish | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) 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 From 9b342114aa7bf51ae7813babd6f9c4f0f7726793 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 21:51:22 -0400 Subject: [PATCH 02/21] feat(deps): add fish-deps unified dependency management command Introduces `fish-deps` with four subcommands: - status: colored installed/missing report per tier (required/integrations/recommended) - install: interactively install each missing dep, prompts method when multiple exist - update: update all installed deps using their preferred method - sync: install missing then update installed Install method priority: cargo (Rust tools get latest crate) > system PM (paru/pacman/apt/brew/pkg/dnf/yum) > git clone (fzf via fzf-update) > curl installer (starship, fisher) > pipx (wakatime). Splits into focused helper files: - _fish_deps_catalog.fish: parallel-array dep catalog with tiers, cargo crates, PM names, special install keys - _fish_deps_pm.fish: PM detection and install/upgrade helpers - _fish_deps_status.fish: tier-grouped colored status display - _fish_deps_install.fish: per-dep interactive install with method selection - _fish_deps_update.fish: per-dep update using known install method check_fish_deps becomes a thin wrapper delegating to `fish-deps status`. README updated with Dependency Management section. --- README.md | 15 ++++ functions/_fish_deps_catalog.fish | 52 ++++++++++++ functions/_fish_deps_install.fish | 135 ++++++++++++++++++++++++++++++ functions/_fish_deps_pm.fish | 65 ++++++++++++++ functions/_fish_deps_status.fish | 35 ++++++++ functions/_fish_deps_update.fish | 84 +++++++++++++++++++ functions/check_fish_deps.fish | 47 +---------- functions/fish-deps.fish | 41 +++++++++ 8 files changed, 429 insertions(+), 45 deletions(-) create mode 100644 functions/_fish_deps_catalog.fish create mode 100644 functions/_fish_deps_install.fish create mode 100644 functions/_fish_deps_pm.fish create mode 100644 functions/_fish_deps_status.fish create mode 100644 functions/_fish_deps_update.fish create mode 100644 functions/fish-deps.fish diff --git a/README.md b/README.md index a7cca06..32eac7f 100644 --- a/README.md +++ b/README.md @@ -241,6 +241,21 @@ 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: **cargo** (for 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. + ### Docker | Function | Description | diff --git a/functions/_fish_deps_catalog.fish b/functions/_fish_deps_catalog.fish new file mode 100644 index 0000000..ca644f8 --- /dev/null +++ b/functions/_fish_deps_catalog.fish @@ -0,0 +1,52 @@ +# 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_* variables. +# +# 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: fisher-bootstrap | fzf-update | +# paru-build | pipx | curl-installer | "" (none) +function _fish_deps_catalog + set -g _fdc_bins \ + 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 \ + 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 "" "" trash-cli "" "" + + set -g _fdc_pm \ + fish "" starship fzf zoxide direnv paru \ + wakatime tailscale \ + eza lsd bat btop dust duf prettyping most ripgrep lazygit lazydocker trash kitty wezterm + + set -g _fdc_special \ + "" fisher-bootstrap curl-installer fzf-update "" "" paru-build \ + pipx "" \ + "" "" "" "" "" "" "" "" "" "" "" "" "" "" +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_install.fish b/functions/_fish_deps_install.fish new file mode 100644 index 0000000..96843c8 --- /dev/null +++ b/functions/_fish_deps_install.fish @@ -0,0 +1,135 @@ +# 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 + if not type -q $bin + 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 — only if cargo is present and the tool has a crate + if test -n "$cargo_crate" -a (type -q cargo) + set -a methods cargo + set -a method_labels "cargo ($cargo_crate)" + end + + # System PM — only if a PM is detected and the tool is in repos + if test -n "$pm_pkg" -a -n "$pm" + set -a methods pm + set -a method_labels "$pm ($pm_pkg)" + end + + # Special methods + 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 useful on Arch; skip if pacman not present + if type -q pacman + set -a methods special-paru + set -a method_labels "build from AUR (paru)" + 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 this dep? + set_color cyan; echo -n "Install $bin? "; set_color normal + read -l -P "[Y/n] " _reply + if test "$_reply" = n -o "$_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 + echo " $m) $lbl" + set m (math $m + 1) + end + read -l -P " Choose [1-"(count $methods)"] (default 1): " _choice + if test -n "$_choice" -a "$_choice" -ge 1 -a "$_choice" -le (count $methods) 2>/dev/null + set chosen_method $methods[$_choice] + end + end + + # Execute chosen method + switch $chosen_method + case cargo + cargo install $cargo_crate + case pm + _fish_deps_pm_install $pm_pkg + 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 + # Currently used for starship + if test "$bin" = starship + curl -sS https://starship.rs/install.sh | sh + end + 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-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 installed."; set_color normal + else + set_color red; echo " $bin install 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.fish b/functions/_fish_deps_pm.fish new file mode 100644 index 0000000..d7314ee --- /dev/null +++ b/functions/_fish_deps_pm.fish @@ -0,0 +1,65 @@ +# 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 pacman apt brew pkg dnf yum + if type -q $pm + echo $pm + return + end + end + echo "" +end + +# 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 + paru -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 + +# 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 + paru -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..8997122 --- /dev/null +++ b/functions/_fish_deps_status.fish @@ -0,0 +1,35 @@ +# 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 + if type -q $bin + set_color green; echo -n " "; set_color normal + echo -n "$bin " + set_color brblack; echo "(Found at "(type -p $bin)")"; 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 + 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..e40bcaf --- /dev/null +++ b/functions/_fish_deps_update.fish @@ -0,0 +1,84 @@ +# 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 -o 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] + + # 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 + + # 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 + + # 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 -- --yes + set updated_any 1 + end + set i (math $i + 1) + continue + end + + # Cargo: prefer for Rust tools + if test -n "$cargo_crate" -a (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" -a -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 From b82766ad522944a5601224ef0d8c76f10bc296ee Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 21:52:56 -0400 Subject: [PATCH 03/21] feat(deps): add yay as supported AUR helper alongside paru yay uses the same -S --noconfirm interface as paru. Detection priority is paru > yay > pacman so paru is preferred when both are present. When installing paru itself via paru-build special, yay -S paru is offered as a method when yay is available, in addition to the makepkg-from-source fallback. --- functions/_fish_deps_install.fish | 8 +++++++- functions/_fish_deps_pm.fish | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index 96843c8..c549c90 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -45,9 +45,13 @@ function _fish_deps_install set -a method_labels "curl installer" case paru-build # Only useful on Arch; skip if pacman not 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 (paru)" + set -a method_labels "build from AUR (makepkg)" end case pipx if type -q pipx @@ -106,6 +110,8 @@ function _fish_deps_install 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 diff --git a/functions/_fish_deps_pm.fish b/functions/_fish_deps_pm.fish index d7314ee..9208758 100644 --- a/functions/_fish_deps_pm.fish +++ b/functions/_fish_deps_pm.fish @@ -3,7 +3,7 @@ # Detect the first available system package manager. function _fish_deps_detect_pm - for pm in paru pacman apt brew pkg dnf yum + for pm in paru yay pacman apt brew pkg dnf yum if type -q $pm echo $pm return @@ -23,6 +23,8 @@ function _fish_deps_pm_install --argument-names pkg switch $pm case paru paru -S --noconfirm $pkg + case yay + yay -S --noconfirm $pkg case pacman sudo pacman -S --noconfirm $pkg case apt @@ -49,6 +51,8 @@ function _fish_deps_pm_upgrade --argument-names pkg switch $pm case paru paru -S --noconfirm $pkg + case yay + yay -S --noconfirm $pkg case pacman sudo pacman -S --noconfirm $pkg case apt From 1a6f1f3f2c4daf0545da15c2cfe8b230f3a8d9bf Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 21:56:50 -0400 Subject: [PATCH 04/21] feat(deps): add status symbols to fish-deps status output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Installed deps show a green ✓. Missing required/integration deps show a red ✗. Missing recommended deps show a yellow ⚠ since they are optional, distinguishing severity at a glance. --- functions/_fish_deps_status.fish | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/functions/_fish_deps_status.fish b/functions/_fish_deps_status.fish index 8997122..1ca1a99 100644 --- a/functions/_fish_deps_status.fish +++ b/functions/_fish_deps_status.fish @@ -5,13 +5,17 @@ function _fish_deps_status _fish_deps_catalog - function __fds_print_dep --argument-names bin + function __fds_print_dep --argument-names bin tier if type -q $bin - set_color green; echo -n " "; set_color normal + 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 + set_color red; echo -n " ✗ "; set_color normal echo -n "$bin " set_color brblack; echo "(Not installed)"; set_color normal end @@ -24,7 +28,7 @@ function _fish_deps_status set -l i 1 for bin in $_fdc_bins if test "$_fdc_tiers[$i]" = $tier - __fds_print_dep $bin + __fds_print_dep $bin $tier end set i (math $i + 1) end From a86f797627ae229f93e6b58d5dbffa4d1e2c07c4 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 21:59:56 -0400 Subject: [PATCH 05/21] fix(deps): demote paru from required to recommended paru is an AUR helper only available on Arch-based distros and is not required for the config to function. Moved to recommended tier alongside yay. README updated accordingly. --- README.md | 2 +- functions/_fish_deps_catalog.fish | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 32eac7f..c36fa42 100644 --- a/README.md +++ b/README.md @@ -499,12 +499,12 @@ Named context shortcuts (e.g. `dcr`, `dck`) live in `~/.config/.user-dots/fish/l | [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 | ### Recommended | Tool | Replaces | |---|---| +| [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 index ca644f8..aab7ecc 100644 --- a/functions/_fish_deps_catalog.fish +++ b/functions/_fish_deps_catalog.fish @@ -18,7 +18,7 @@ function _fish_deps_catalog 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 req req req req req rec \ int int \ rec rec rec rec rec rec rec rec rec rec rec rec rec rec From a3d99eec3f289d689dabda39a2a553d68b8d780f Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 22:01:00 -0400 Subject: [PATCH 06/21] fix(aur): fall back to yay when paru is unavailable upgrade, pkg, search, and parur now detect paru first, then yay, and print a clear error if neither is installed. Removes the hard dependency on paru specifically across all AUR-wrapper functions. --- functions/parur.fish | 15 +++++++++++---- functions/pkg.fish | 17 +++++++++++------ functions/search.fish | 17 +++++++++++------ functions/upgrade.fish | 16 +++++++++++----- 4 files changed, 44 insertions(+), 21 deletions(-) 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 From 0e7e82408551c67791c783d2e17730bc5e452e38 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 22:05:56 -0400 Subject: [PATCH 07/21] fix(deps): fix autoloading and Fish 4.x test compatibility Split _fish_deps_pm.fish into one file per function so Fish can autoload each by name (_fish_deps_detect_pm, _fish_deps_pm_install, _fish_deps_pm_upgrade). A single file with multiple functions only autoloads under the filename, leaving the others unreachable. Replace all `test -a`/`test -o` binary operators with `; and`/`; or` chains throughout _fish_deps_install and _fish_deps_update. Fish 4.x removed support for -a/-o in test, causing the "unexpected argument" errors seen on Debian. Also consolidate paru/yay cases in pm_install and pm_upgrade since both helpers use identical flags. --- functions/_fish_deps_detect_pm.fish | 13 ++++++ functions/_fish_deps_install.fish | 10 ++-- functions/_fish_deps_pm.fish | 69 ---------------------------- functions/_fish_deps_pm_install.fish | 28 +++++++++++ functions/_fish_deps_pm_upgrade.fish | 28 +++++++++++ functions/_fish_deps_update.fish | 6 +-- 6 files changed, 76 insertions(+), 78 deletions(-) create mode 100644 functions/_fish_deps_detect_pm.fish delete mode 100644 functions/_fish_deps_pm.fish create mode 100644 functions/_fish_deps_pm_install.fish create mode 100644 functions/_fish_deps_pm_upgrade.fish 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 index c549c90..b46679b 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -21,13 +21,13 @@ function _fish_deps_install set -l method_labels # Cargo — only if cargo is present and the tool has a crate - if test -n "$cargo_crate" -a (type -q cargo) + if test -n "$cargo_crate"; and type -q cargo set -a methods cargo set -a method_labels "cargo ($cargo_crate)" end # System PM — only if a PM is detected and the tool is in repos - if test -n "$pm_pkg" -a -n "$pm" + if test -n "$pm_pkg"; and test -n "$pm" set -a methods pm set -a method_labels "$pm ($pm_pkg)" end @@ -44,7 +44,6 @@ function _fish_deps_install set -a methods special-curl set -a method_labels "curl installer" case paru-build - # Only useful on Arch; skip if pacman not present if type -q yay set -a methods special-yay-paru set -a method_labels "yay -S paru" @@ -74,7 +73,7 @@ function _fish_deps_install # Prompt: install this dep? set_color cyan; echo -n "Install $bin? "; set_color normal read -l -P "[Y/n] " _reply - if test "$_reply" = n -o "$_reply" = N + if test "$_reply" = n; or test "$_reply" = N set i (math $i + 1) continue end @@ -89,7 +88,7 @@ function _fish_deps_install set m (math $m + 1) end read -l -P " Choose [1-"(count $methods)"] (default 1): " _choice - if test -n "$_choice" -a "$_choice" -ge 1 -a "$_choice" -le (count $methods) 2>/dev/null + if test -n "$_choice"; and test "$_choice" -ge 1; and test "$_choice" -le (count $methods) set chosen_method $methods[$_choice] end end @@ -106,7 +105,6 @@ function _fish_deps_install curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source fisher update case special-curl - # Currently used for starship if test "$bin" = starship curl -sS https://starship.rs/install.sh | sh end diff --git a/functions/_fish_deps_pm.fish b/functions/_fish_deps_pm.fish deleted file mode 100644 index 9208758..0000000 --- a/functions/_fish_deps_pm.fish +++ /dev/null @@ -1,69 +0,0 @@ -# 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 - -# 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 - paru -S --noconfirm $pkg - case yay - yay -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 - -# 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 - paru -S --noconfirm $pkg - case yay - yay -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_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_update.fish b/functions/_fish_deps_update.fish index e40bcaf..189143b 100644 --- a/functions/_fish_deps_update.fish +++ b/functions/_fish_deps_update.fish @@ -19,7 +19,7 @@ function _fish_deps_update set -l i 1 for bin in $_fdc_bins # Skip fisher itself (handled above) and tools that aren't installed - if test "$bin" = fisher -o not (type -q $bin) + if test "$bin" = fisher; or not type -q $bin set i (math $i + 1) continue end @@ -60,7 +60,7 @@ function _fish_deps_update end # Cargo: prefer for Rust tools - if test -n "$cargo_crate" -a (type -q cargo) + if test -n "$cargo_crate"; and type -q cargo echo "Updating $bin..." cargo install --force $cargo_crate set updated_any 1 @@ -69,7 +69,7 @@ function _fish_deps_update end # System PM fallback - if test -n "$pm_pkg" -a -n "$pm" + if test -n "$pm_pkg"; and test -n "$pm" echo "Updating $bin..." _fish_deps_pm_upgrade $pm_pkg set updated_any 1 From a7c6b9097dc9786b52cb039c229b5727dbf827a9 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 22:07:50 -0400 Subject: [PATCH 08/21] fix(deps): consolidate install prompt into read -P to prevent display race --- functions/_fish_deps_install.fish | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index b46679b..307ad9b 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -71,8 +71,7 @@ function _fish_deps_install end # Prompt: install this dep? - set_color cyan; echo -n "Install $bin? "; set_color normal - read -l -P "[Y/n] " _reply + read -l -P (set_color cyan)"Install $bin?"(set_color normal)" [Y/n] " _reply if test "$_reply" = n; or test "$_reply" = N set i (math $i + 1) continue From a70e88c3446fee5ea6b13025fcc21dd2028a02df Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 22:13:13 -0400 Subject: [PATCH 09/21] fix(deps): remove paru install, enforce cargo preference for Rust tools Catalog: clear paru's pm and special install entries so it appears in status but fish-deps install skips it (it's a package manager, not a managed dep). Install: cargo is now always attempted first for Rust tools. When cargo is absent but a crate exists, a note is printed suggesting rustup. When only one method is available the chosen method is shown so the user can see whether cargo or the system PM is being used. Method prompt now shows the default label inline for clarity. Removed dead paru-build switch case from the install executor. --- functions/_fish_deps_catalog.fish | 6 ++--- functions/_fish_deps_install.fish | 41 ++++++++++++------------------- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/functions/_fish_deps_catalog.fish b/functions/_fish_deps_catalog.fish index aab7ecc..7b639b6 100644 --- a/functions/_fish_deps_catalog.fish +++ b/functions/_fish_deps_catalog.fish @@ -10,7 +10,7 @@ # _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: fisher-bootstrap | fzf-update | -# paru-build | pipx | curl-installer | "" (none) +# pipx | curl-installer | "" (none) function _fish_deps_catalog set -g _fdc_bins \ fish fisher starship fzf zoxide direnv paru \ @@ -28,12 +28,12 @@ function _fish_deps_catalog eza lsd bat "" du-dust "" "" "" ripgrep "" "" trash-cli "" "" set -g _fdc_pm \ - fish "" starship fzf zoxide direnv paru \ + 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 \ - "" fisher-bootstrap curl-installer fzf-update "" "" paru-build \ + "" fisher-bootstrap curl-installer fzf-update "" "" "" \ pipx "" \ "" "" "" "" "" "" "" "" "" "" "" "" "" "" end diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index 307ad9b..c34b903 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -20,13 +20,19 @@ function _fish_deps_install set -l methods set -l method_labels - # Cargo — only if cargo is present and the tool has a crate - if test -n "$cargo_crate"; and type -q cargo - set -a methods cargo - set -a method_labels "cargo ($cargo_crate)" + # Cargo first — 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 rustup for the latest $bin" + set_color normal + end end - # System PM — only if a PM is detected and the tool is in repos + # System PM — after cargo so cargo is always the default when available if test -n "$pm_pkg"; and test -n "$pm" set -a methods pm set -a method_labels "$pm ($pm_pkg)" @@ -43,15 +49,6 @@ function _fish_deps_install case curl-installer set -a methods special-curl set -a method_labels "curl installer" - case paru-build - 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 @@ -83,13 +80,16 @@ function _fish_deps_install echo " Available methods:" set -l m 1 for lbl in $method_labels - echo " $m) $lbl" + 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): " _choice + read -l -P " Choose [1-"(count $methods)"] (default 1 = $method_labels[1]): " _choice if test -n "$_choice"; and test "$_choice" -ge 1; and test "$_choice" -le (count $methods) set chosen_method $methods[$_choice] end + else + set_color brblack; echo " Installing via $method_labels[1]"; set_color normal end # Execute chosen method @@ -107,15 +107,6 @@ function _fish_deps_install 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-pipx pipx install $bin case special-pip From abbbf20b40669abbd741c6b9ec9c7508d1411d61 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 22:14:45 -0400 Subject: [PATCH 10/21] fix(deps): restore paru install gated on pacman presence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Arch-based systems (pacman present), paru-build offers yay or makepkg as install methods. On non-Arch systems neither pacman nor yay exist, so no methods are built and the dep is silently skipped — no prompt shown to the user. --- functions/_fish_deps_catalog.fish | 2 +- functions/_fish_deps_install.fish | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/functions/_fish_deps_catalog.fish b/functions/_fish_deps_catalog.fish index 7b639b6..457373f 100644 --- a/functions/_fish_deps_catalog.fish +++ b/functions/_fish_deps_catalog.fish @@ -33,7 +33,7 @@ function _fish_deps_catalog eza lsd bat btop dust duf prettyping most ripgrep lazygit lazydocker trash kitty wezterm set -g _fdc_special \ - "" fisher-bootstrap curl-installer fzf-update "" "" "" \ + "" fisher-bootstrap curl-installer fzf-update "" "" paru-build \ pipx "" \ "" "" "" "" "" "" "" "" "" "" "" "" "" "" end diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index c34b903..a3bfe2e 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -49,6 +49,16 @@ function _fish_deps_install 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 @@ -107,6 +117,15 @@ function _fish_deps_install 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-pipx pipx install $bin case special-pip From df7c921bc66f329f0e4fda70a54daccb44438729 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 22:18:57 -0400 Subject: [PATCH 11/21] feat(deps): add cargo as a managed dependency with rustup installer cargo is now the second entry in the catalog (after fish) so it is installed before any Rust tool that depends on it. Install preference: rustup installer (curl | sh) first, system PM as fallback. Update runs rustup update when rustup is available. The rustup-installer special is evaluated before the system PM in the method list so it is always option 1 / the default for cargo. --- functions/_fish_deps_catalog.fish | 18 ++++++++++-------- functions/_fish_deps_install.fish | 16 ++++++++++++---- functions/_fish_deps_update.fish | 11 +++++++++++ 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/functions/_fish_deps_catalog.fish b/functions/_fish_deps_catalog.fish index 457373f..5667f11 100644 --- a/functions/_fish_deps_catalog.fish +++ b/functions/_fish_deps_catalog.fish @@ -2,38 +2,40 @@ # SPDX-License-Identifier: AGPL-3.0-or-later # Populates parallel arrays describing every managed dependency. -# Callers must invoke this function before accessing _fdc_* variables. +# 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: fisher-bootstrap | fzf-update | -# pipx | curl-installer | "" (none) +# _fdc_special — special install key: rustup-installer | fisher-bootstrap | +# fzf-update | paru-build | pipx | curl-installer | "" (none) +# +# cargo is listed second so it is installed before Rust tools that depend on it. function _fish_deps_catalog set -g _fdc_bins \ - fish fisher starship fzf zoxide direnv paru \ + fish cargo 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 rec \ + 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 "" "" \ + "" "" "" starship "" zoxide "" "" \ "" "" \ eza lsd bat "" du-dust "" "" "" ripgrep "" "" trash-cli "" "" set -g _fdc_pm \ - fish "" starship fzf zoxide direnv "" \ + fish cargo "" starship fzf zoxide direnv "" \ wakatime tailscale \ eza lsd bat btop dust duf prettyping most ripgrep lazygit lazydocker trash kitty wezterm set -g _fdc_special \ - "" fisher-bootstrap curl-installer fzf-update "" "" paru-build \ + "" rustup-installer fisher-bootstrap curl-installer fzf-update "" "" paru-build \ pipx "" \ "" "" "" "" "" "" "" "" "" "" "" "" "" "" end diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index a3bfe2e..c3e07c7 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -20,25 +20,31 @@ function _fish_deps_install set -l methods set -l method_labels - # Cargo first — preferred for Rust tools; gets the latest crate version + # 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 rustup for the latest $bin" + echo " note: cargo not found — install cargo first for the latest $bin" set_color normal end end - # System PM — after cargo so cargo is always the default when available + # rustup installer — listed before system PM so it is the default for cargo itself + if test "$special" = rustup-installer + set -a methods special-rustup + set -a method_labels "rustup installer (curl | sh)" + end + + # System PM — after cargo/rustup so those are always the default when available if test -n "$pm_pkg"; and test -n "$pm" set -a methods pm set -a method_labels "$pm ($pm_pkg)" end - # Special methods + # Remaining special methods switch $special case fzf-update set -a methods special-fzf @@ -108,6 +114,8 @@ function _fish_deps_install cargo install $cargo_crate case pm _fish_deps_pm_install $pm_pkg + case special-rustup + curl https://sh.rustup.rs -sSf | sh case special-fzf fzf-update case special-fisher diff --git a/functions/_fish_deps_update.fish b/functions/_fish_deps_update.fish index 189143b..35d2b14 100644 --- a/functions/_fish_deps_update.fish +++ b/functions/_fish_deps_update.fish @@ -28,6 +28,17 @@ function _fish_deps_update 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..." From 6fd1e3221e14df6e8579ed62ed12b2ca2750e771 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 22:20:16 -0400 Subject: [PATCH 12/21] docs(readme): require Fish >= 4.0 and add Rust/cargo to dependencies --- README.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index c36fa42..b9053a7 100644 --- a/README.md +++ b/README.md @@ -491,19 +491,23 @@ 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 | +| Tool | Version | Purpose | +|---|---|---| +| [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. ### 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) | From 9e7539d8635a3933aa13fd62d6bad2b214285bb0 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 22:23:10 -0400 Subject: [PATCH 13/21] feat(deps): support upgrading fish itself via cargo install fish Fish 4.x is a Rust rewrite published to crates.io as 'fish'. Added the crate to the catalog so fish-deps update will run cargo install --force fish to upgrade it. A yellow restart reminder is printed after the upgrade since the new binary won't take effect until the shell restarts. README warning updated to mention cargo install fish as the upgrade path for users stuck on Fish 3.x. --- README.md | 5 +++++ functions/_fish_deps_catalog.fish | 2 +- functions/_fish_deps_update.fish | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b9053a7..acee522 100644 --- a/README.md +++ b/README.md @@ -502,6 +502,11 @@ Named context shortcuts (e.g. `dcr`, `dck`) live in `~/.config/.user-dots/fish/l > [!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. +> If you are on an older Fish, you can upgrade via cargo (Fish 4.x is a Rust rewrite published to crates.io): +> ``` +> cargo install fish +> ``` +> Or run `fish-deps update` once cargo is available — it will upgrade Fish via cargo automatically. ### Recommended diff --git a/functions/_fish_deps_catalog.fish b/functions/_fish_deps_catalog.fish index 5667f11..58105c8 100644 --- a/functions/_fish_deps_catalog.fish +++ b/functions/_fish_deps_catalog.fish @@ -25,7 +25,7 @@ function _fish_deps_catalog rec rec rec rec rec rec rec rec rec rec rec rec rec rec set -g _fdc_cargo \ - "" "" "" starship "" zoxide "" "" \ + fish "" "" starship "" zoxide "" "" \ "" "" \ eza lsd bat "" du-dust "" "" "" ripgrep "" "" trash-cli "" "" diff --git a/functions/_fish_deps_update.fish b/functions/_fish_deps_update.fish index 35d2b14..eff4cdd 100644 --- a/functions/_fish_deps_update.fish +++ b/functions/_fish_deps_update.fish @@ -75,6 +75,11 @@ function _fish_deps_update echo "Updating $bin..." cargo install --force $cargo_crate set updated_any 1 + if test "$bin" = fish + set_color yellow + echo " Fish updated — restart your shell to use the new version." + set_color normal + end set i (math $i + 1) continue end From 8d9e7ae43f1dbdd0d7ef8ba11a3637b26a22a492 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 22:29:50 -0400 Subject: [PATCH 14/21] fix(deps): validate method choice is numeric before comparing --- functions/_fish_deps_install.fish | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index c3e07c7..f32fa0a 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -101,7 +101,7 @@ function _fish_deps_install set m (math $m + 1) end read -l -P " Choose [1-"(count $methods)"] (default 1 = $method_labels[1]): " _choice - if test -n "$_choice"; and test "$_choice" -ge 1; and test "$_choice" -le (count $methods) + if string match -qr '^\d+$' "$_choice"; and test "$_choice" -ge 1; and test "$_choice" -le (count $methods) set chosen_method $methods[$_choice] end else From 891744208952634b791aa1a532ea9e2c2558f684 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 22:40:35 -0400 Subject: [PATCH 15/21] fix(deps): update PATH immediately after rustup install After the rustup installer runs, add the cargo bin dir to PATH in the current session so subsequent installs in the same fish-deps run can find cargo without a shell restart. Checks CARGO_HOME/bin first (set in config.fish), then falls back to the rustup default ~/.cargo/bin. Warns the user if cargo still isn't detectable after the path update. --- functions/_fish_deps_install.fish | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index f32fa0a..d50bae6 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -116,6 +116,19 @@ function _fish_deps_install _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-fzf fzf-update case special-fisher From 782ef833c283e00dfd69b0e426ebe667387a58c0 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 22:48:33 -0400 Subject: [PATCH 16/21] fix(deps): correct trash cargo crate name to trashy --- functions/_fish_deps_catalog.fish | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/_fish_deps_catalog.fish b/functions/_fish_deps_catalog.fish index 58105c8..79c27a0 100644 --- a/functions/_fish_deps_catalog.fish +++ b/functions/_fish_deps_catalog.fish @@ -27,7 +27,7 @@ function _fish_deps_catalog set -g _fdc_cargo \ fish "" "" starship "" zoxide "" "" \ "" "" \ - eza lsd bat "" du-dust "" "" "" ripgrep "" "" trash-cli "" "" + eza lsd bat "" du-dust "" "" "" ripgrep "" "" trashy "" "" set -g _fdc_pm \ fish cargo "" starship fzf zoxide direnv "" \ From 7d4e33bc7e3291a1f3d0ec8a8f0a7a3aadf91e34 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 23:04:35 -0400 Subject: [PATCH 17/21] feat(deps): add curl installer for lazydocker and binary download for wakatime lazydocker: prefer the official install_update_linux.sh curl script over system PM. The same script handles updates, so fish-deps update re-runs it. wakatime: replace pipx with a direct binary download from github releases. Detects architecture (amd64/arm64/arm) via uname -m, downloads the zip, extracts the binary to ~/.config/wakatime/wakatime, chmods it, and symlinks it to ~/.local/bin/wakatime. fish-deps update re-downloads and replaces the binary in place. Both new specials are added to the preferred-method block so they appear before the system PM and are the default when prompted. --- functions/_fish_deps_catalog.fish | 4 +-- functions/_fish_deps_install.fish | 46 +++++++++++++++++++++++++++---- functions/_fish_deps_update.fish | 34 +++++++++++++++++++++++ 3 files changed, 76 insertions(+), 8 deletions(-) diff --git a/functions/_fish_deps_catalog.fish b/functions/_fish_deps_catalog.fish index 79c27a0..02c2e0a 100644 --- a/functions/_fish_deps_catalog.fish +++ b/functions/_fish_deps_catalog.fish @@ -36,8 +36,8 @@ function _fish_deps_catalog set -g _fdc_special \ "" rustup-installer fisher-bootstrap curl-installer fzf-update "" "" paru-build \ - pipx "" \ - "" "" "" "" "" "" "" "" "" "" "" "" "" "" + wakatime-binary "" \ + "" "" "" "" "" "" "" "" "" "" curl-lazydocker "" "" "" end # Returns the index (1-based) of $argv[1] in the catalog, or "" if not found. diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index d50bae6..f56f902 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -32,19 +32,26 @@ function _fish_deps_install end end - # rustup installer — listed before system PM so it is the default for cargo itself - if test "$special" = rustup-installer - set -a methods special-rustup - set -a method_labels "rustup installer (curl | sh)" + # Preferred special methods — listed before system PM so they are the default + switch $special + 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/rustup so those are always the default when available + # 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 - # Remaining special methods + # Supplemental special methods (fallbacks, Arch-only, etc.) switch $special case fzf-update set -a methods special-fzf @@ -129,6 +136,33 @@ function _fish_deps_install 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 diff --git a/functions/_fish_deps_update.fish b/functions/_fish_deps_update.fish index eff4cdd..1bce7ac 100644 --- a/functions/_fish_deps_update.fish +++ b/functions/_fish_deps_update.fish @@ -48,6 +48,40 @@ function _fish_deps_update 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 From fee2d99bea739ff66127a947b86f8cf7b55b9055 Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 23:17:51 -0400 Subject: [PATCH 18/21] feat(fish-deps): warn on fish < 4.0 in status; prompt upgrade in install MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fish-deps status now shows ⚠ with the current version when fish < 4.0. fish-deps install prompts to upgrade fish when the installed version is below 4.0, using the same install methods (cargo/PM) and printing a restart reminder on success. --- functions/_fish_deps_install.fish | 28 +++++++++++++++++++++++----- functions/_fish_deps_status.fish | 11 +++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index f56f902..6a92fb4 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -11,7 +11,20 @@ function _fish_deps_install 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] @@ -90,8 +103,8 @@ function _fish_deps_install continue end - # Prompt: install this dep? - read -l -P (set_color cyan)"Install $bin?"(set_color normal)" [Y/n] " _reply + # 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 @@ -112,7 +125,7 @@ function _fish_deps_install set chosen_method $methods[$_choice] end else - set_color brblack; echo " Installing via $method_labels[1]"; set_color normal + set_color brblack; echo " "(string lower $upgrade_label)"ing via $method_labels[1]"; set_color normal end # Execute chosen method @@ -189,9 +202,14 @@ function _fish_deps_install if test $status -eq 0 set installed_any 1 - set_color green; echo " $bin installed."; set_color normal + 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 install failed."; set_color normal + set_color red; echo " $bin "(string lower $upgrade_label)" failed."; set_color normal end end set i (math $i + 1) diff --git a/functions/_fish_deps_status.fish b/functions/_fish_deps_status.fish index 1ca1a99..e9e66b0 100644 --- a/functions/_fish_deps_status.fish +++ b/functions/_fish_deps_status.fish @@ -7,6 +7,17 @@ function _fish_deps_status 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 From 7936a0966e0183efc99c04071841b2551c6fdbae Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 23:29:55 -0400 Subject: [PATCH 19/21] feat(fish-deps): build fish from source via git + cargo when upgrading Adds a git-cargo-fish install method that clones fish-shell, checks out the latest tag, and runs `uv run --no-managed-python cargo install --path .`. This is offered first in `fish-deps install` (requires cargo + uv) and used automatically by `fish-deps update`, falling back to the system PM when cargo or uv are absent. Removes the stale `cargo install fish` README note (that crate is a library, not the shell binary). --- README.md | 11 ++++---- functions/_fish_deps_catalog.fish | 7 ++--- functions/_fish_deps_install.fish | 27 +++++++++++++++++++ functions/_fish_deps_update.fish | 44 +++++++++++++++++++++++++++---- 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index acee522..f08b1f4 100644 --- a/README.md +++ b/README.md @@ -254,7 +254,10 @@ rm -f file.txt # Falls through to standard rm -f | `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: **cargo** (for 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. +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/)**. If either is missing, `fish-deps install`/`update` will fall back to the system package manager instead. ### Docker @@ -502,11 +505,7 @@ Named context shortcuts (e.g. `dcr`, `dck`) live in `~/.config/.user-dots/fish/l > [!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. -> If you are on an older Fish, you can upgrade via cargo (Fish 4.x is a Rust rewrite published to crates.io): -> ``` -> cargo install fish -> ``` -> Or run `fish-deps update` once cargo is available — it will upgrade Fish via cargo automatically. +> If you are on an older Fish, run `fish-deps install` or `fish-deps update` — it will build and install the latest Fish from source using git + cargo (requires cargo and uv). ### Recommended diff --git a/functions/_fish_deps_catalog.fish b/functions/_fish_deps_catalog.fish index 02c2e0a..85db830 100644 --- a/functions/_fish_deps_catalog.fish +++ b/functions/_fish_deps_catalog.fish @@ -10,7 +10,8 @@ # _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 | "" (none) +# fzf-update | paru-build | pipx | curl-installer | +# git-cargo-fish | "" (none) # # cargo is listed second so it is installed before Rust tools that depend on it. function _fish_deps_catalog @@ -25,7 +26,7 @@ function _fish_deps_catalog rec rec rec rec rec rec rec rec rec rec rec rec rec rec set -g _fdc_cargo \ - fish "" "" starship "" zoxide "" "" \ + "" "" "" starship "" zoxide "" "" \ "" "" \ eza lsd bat "" du-dust "" "" "" ripgrep "" "" trashy "" "" @@ -35,7 +36,7 @@ function _fish_deps_catalog eza lsd bat btop dust duf prettyping most ripgrep lazygit lazydocker trash kitty wezterm set -g _fdc_special \ - "" rustup-installer fisher-bootstrap curl-installer fzf-update "" "" paru-build \ + git-cargo-fish rustup-installer fisher-bootstrap curl-installer fzf-update "" "" paru-build \ wakatime-binary "" \ "" "" "" "" "" "" "" "" "" "" curl-lazydocker "" "" "" end diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index 6a92fb4..ae46e00 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -47,6 +47,18 @@ function _fish_deps_install # Preferred special methods — listed before system PM so they are the default switch $special + 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)" @@ -194,6 +206,21 @@ function _fish_deps_install and makepkg -si --noconfirm and popd rm -rf $_build_dir + 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" for-each-ref refs/tags/ --format '%(refname:short)' --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 diff --git a/functions/_fish_deps_update.fish b/functions/_fish_deps_update.fish index 1bce7ac..1837f1a 100644 --- a/functions/_fish_deps_update.fish +++ b/functions/_fish_deps_update.fish @@ -93,6 +93,45 @@ function _fish_deps_update 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" for-each-ref refs/tags/ --format '%(refname:short)' --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 @@ -109,11 +148,6 @@ function _fish_deps_update echo "Updating $bin..." cargo install --force $cargo_crate set updated_any 1 - if test "$bin" = fish - set_color yellow - echo " Fish updated — restart your shell to use the new version." - set_color normal - end set i (math $i + 1) continue end From a351e62a171c477c0d58f01183a5ad479a655f0f Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 23:34:49 -0400 Subject: [PATCH 20/21] feat(fish-deps): add uv as managed dep; install before cargo and fish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit uv is now listed first in the catalog (before cargo and fish) so it is installed automatically before the fish source build is attempted. Install uses the official curl script; update uses `uv self update`. Catalog order is now: uv → cargo → fish → … ensuring prerequisites are in place before any dependent install method runs. README updated: uv and cargo added to the Required table, warning callout and dependency management note reflect the automatic install flow. --- README.md | 6 ++++-- functions/_fish_deps_catalog.fish | 14 +++++++------- functions/_fish_deps_install.fish | 17 +++++++++++++++++ functions/_fish_deps_update.fish | 9 +++++++++ 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index f08b1f4..bad8ea0 100644 --- a/README.md +++ b/README.md @@ -257,7 +257,7 @@ rm -f file.txt # Falls through to standard rm -f 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/)**. If either is missing, `fish-deps install`/`update` will fall back to the system package manager instead. +> 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 @@ -496,6 +496,8 @@ Named context shortcuts (e.g. `dcr`, `dck`) live in `~/.config/.user-dots/fish/l | 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 | @@ -505,7 +507,7 @@ Named context shortcuts (e.g. `dcr`, `dck`) live in `~/.config/.user-dots/fish/l > [!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. -> If you are on an older Fish, run `fish-deps install` or `fish-deps update` — it will build and install the latest Fish from source using git + cargo (requires cargo and uv). +> 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 diff --git a/functions/_fish_deps_catalog.fish b/functions/_fish_deps_catalog.fish index 85db830..3f4cea0 100644 --- a/functions/_fish_deps_catalog.fish +++ b/functions/_fish_deps_catalog.fish @@ -11,32 +11,32 @@ # _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 | "" (none) +# git-cargo-fish | curl-uv | "" (none) # -# cargo is listed second so it is installed before Rust tools that depend on it. +# uv and cargo are listed first so both are available before fish and other Rust tools. function _fish_deps_catalog set -g _fdc_bins \ - fish cargo fisher starship fzf zoxide direnv paru \ + 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 rec \ + 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 "" "" \ + "" "" "" "" starship "" zoxide "" "" \ "" "" \ eza lsd bat "" du-dust "" "" "" ripgrep "" "" trashy "" "" set -g _fdc_pm \ - fish cargo "" starship fzf zoxide direnv "" \ + 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 \ - git-cargo-fish rustup-installer fisher-bootstrap curl-installer fzf-update "" "" paru-build \ + curl-uv rustup-installer git-cargo-fish fisher-bootstrap curl-installer fzf-update "" "" paru-build \ wakatime-binary "" \ "" "" "" "" "" "" "" "" "" "" curl-lazydocker "" "" "" end diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index ae46e00..618e74c 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -47,6 +47,9 @@ function _fish_deps_install # 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 @@ -206,6 +209,20 @@ function _fish_deps_install 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 diff --git a/functions/_fish_deps_update.fish b/functions/_fish_deps_update.fish index 1837f1a..ad8e39b 100644 --- a/functions/_fish_deps_update.fish +++ b/functions/_fish_deps_update.fish @@ -93,6 +93,15 @@ function _fish_deps_update 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 From a7510cc8ea6c62f5303e39eab0818f859cddc11a Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 23:46:34 -0400 Subject: [PATCH 21/21] fix(fish-deps): filter fish-* tags only; fix starship sh -s flag git tag --list 'fish-*' replaces for-each-ref so old pre-Rust tags like pre_whitespace_fix (which have no Cargo.toml) are never selected. starship update: sh -s -- --yes correctly passes --yes to the piped install script instead of treating it as a filename for sh to open. --- functions/_fish_deps_install.fish | 2 +- functions/_fish_deps_update.fish | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index 618e74c..03db4e3 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -228,7 +228,7 @@ function _fish_deps_install set -l _build_ok 0 git clone https://github.com/fish-shell/fish-shell "$_tmpdir" and begin - set -l _tag (git -C "$_tmpdir" for-each-ref refs/tags/ --format '%(refname:short)' --sort=version:refname | tail -1) + 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 diff --git a/functions/_fish_deps_update.fish b/functions/_fish_deps_update.fish index ad8e39b..1ae31f7 100644 --- a/functions/_fish_deps_update.fish +++ b/functions/_fish_deps_update.fish @@ -110,7 +110,7 @@ function _fish_deps_update set -l _build_ok 0 git clone https://github.com/fish-shell/fish-shell "$_tmpdir" and begin - set -l _tag (git -C "$_tmpdir" for-each-ref refs/tags/ --format '%(refname:short)' --sort=version:refname | tail -1) + 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 @@ -145,7 +145,7 @@ function _fish_deps_update if test "$special" = curl-installer if test "$bin" = starship echo "Updating $bin..." - curl -sS https://starship.rs/install.sh | sh -- --yes + curl -sS https://starship.rs/install.sh | sh -s -- --yes set updated_any 1 end set i (math $i + 1)