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.
This commit is contained in:
2026-05-18 21:51:22 -04:00
parent f09006846b
commit 9b342114aa
8 changed files with 429 additions and 45 deletions
+15
View File
@@ -241,6 +241,21 @@ rm -f file.txt # Falls through to standard rm -f
| `upgrade` | Full system upgrade: `paru -Syu --noconfirm` | | `upgrade` | Full system upgrade: `paru -Syu --noconfirm` |
| `cleanup` | Log and remove orphaned packages | | `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 ### Docker
| Function | Description | | Function | Description |
+52
View File
@@ -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
+135
View File
@@ -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
+65
View File
@@ -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 <pkg>
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 <pkg>
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
+35
View File
@@ -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
+84
View File
@@ -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
+2 -45
View File
@@ -1,50 +1,7 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # 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' function check_fish_deps --description 'Check all fish-related dependencies'
set -l required fish fisher starship fzf zoxide direnv paru fish-deps status
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
end end
+41
View File
@@ -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