# Fish shell configuration - batteries included # A comprehensive, quality-of-life focused fish setup with useful plugins { inputs, lib, config, pkgs, ... }: { programs.fish = { enable = true; # ═══════════════════════════════════════════════════════════════════════════ # SHELL ALIASES # ═══════════════════════════════════════════════════════════════════════════ shellAliases = { # Navigation ".." = "cd .."; "..." = "cd ../.."; "...." = "cd ../../.."; "....." = "cd ../../../.."; # Listings (eza integration handled by programs.eza) ll = "ls -la"; la = "ls -a"; lt = "ls --tree"; # Git shortcuts gs = "git status"; gd = "git diff"; gds = "git diff --staged"; ga = "git add"; gc = "git commit"; gp = "git push"; gl = "git pull"; glog = "git log --oneline --graph --decorate"; gco = "git checkout"; gb = "git branch"; # Nix shortcuts nix-gc = "nix-collect-garbage -d"; nix-search = "nix search nixpkgs"; nrs = "sudo nixos-rebuild switch --flake ."; drs = "darwin-rebuild switch --flake ."; hms = "home-manager switch --flake ."; # Safety nets rm = "rm -i"; cp = "cp -i"; mv = "mv -i"; # Modern replacements (when available) cat = "bat --paging=never"; grep = "rg"; find = "fd"; # Misc c = "clear"; q = "exit"; h = "history"; j = "jobs -l"; path = "echo $PATH | tr ':' '\\n'"; week = "date +%V"; myip = "curl -s https://ipinfo.io/ip"; }; # ═══════════════════════════════════════════════════════════════════════════ # SHELL ABBREVIATIONS (expand as you type, more powerful than aliases) # ═══════════════════════════════════════════════════════════════════════════ shellAbbrs = { # Git abbreviations (expand to full commands) gst = "git status"; gaa = "git add --all"; gcm = "git commit -m"; gca = "git commit --amend"; gcan = "git commit --amend --no-edit"; gpf = "git push --force-with-lease"; grb = "git rebase"; grbi = "git rebase -i"; gsta = "git stash"; gstp = "git stash pop"; # Docker dps = "docker ps"; dpa = "docker ps -a"; di = "docker images"; dcu = "docker-compose up"; dcd = "docker-compose down"; # Kubernetes k = "kubectl"; kg = "kubectl get"; kd = "kubectl describe"; kl = "kubectl logs"; kx = "kubectl exec -it"; }; # ═══════════════════════════════════════════════════════════════════════════ # CUSTOM FUNCTIONS # ═══════════════════════════════════════════════════════════════════════════ functions = { # Create directory and cd into it mkcd = "mkdir -p $argv[1]; and cd $argv[1]"; # Quick extract - handles multiple archive formats extract = '' if test -f $argv[1] switch $argv[1] case '*.tar.bz2' tar xjf $argv[1] case '*.tar.gz' tar xzf $argv[1] case '*.tar.xz' tar xJf $argv[1] case '*.bz2' bunzip2 $argv[1] case '*.rar' unrar x $argv[1] case '*.gz' gunzip $argv[1] case '*.tar' tar xf $argv[1] case '*.tbz2' tar xjf $argv[1] case '*.tgz' tar xzf $argv[1] case '*.zip' unzip $argv[1] case '*.Z' uncompress $argv[1] case '*.7z' 7z x $argv[1] case '*' echo "'$argv[1]' cannot be extracted via extract()" end else echo "'$argv[1]' is not a valid file" end ''; # Git clone and cd gcl = '' git clone $argv[1] cd (basename $argv[1] .git) ''; # Quick backup file bak = "cp $argv[1] $argv[1].bak.(date +%Y%m%d_%H%M%S)"; # Find process by name psg = "ps aux | grep -v grep | grep -i $argv[1]"; # Quick HTTP server serve = '' set port (test -n "$argv[1]"; and echo $argv[1]; or echo 8000) echo "Serving on http://localhost:$port" python3 -m http.server $port ''; # Weather weather = '' set location (test -n "$argv[1]"; and echo $argv[1]; or echo "") curl -s "wttr.in/$location?format=3" ''; # Quick nix shell nsh = "nix-shell -p $argv"; # Reload fish config reload = "source ~/.config/fish/config.fish; echo 'Fish config reloaded!'"; # Show path entries one per line pathlist = "echo $PATH | tr ':' '\\n' | nl"; # Create a quick note note = '' set note_dir "$HOME/notes" mkdir -p $note_dir set note_file "$note_dir/(date +%Y-%m-%d).md" if test -n "$argv" echo "- (date +%H:%M) $argv" >> $note_file echo "Note added to $note_file" else $EDITOR $note_file end ''; # Show disk usage for current directory, sorted duf = "du -sh * 2>/dev/null | sort -h"; }; # ═══════════════════════════════════════════════════════════════════════════ # PLUGINS - Curated selection for productivity # ═══════════════════════════════════════════════════════════════════════════ plugins = with pkgs.fishPlugins; [ # ── Directory Navigation ────────────────────────────────────────────────── # z: Jump to frequently used directories (like autojump/zoxide but pure fish) { name = "z"; src = z.src; } # ── Fuzzy Finding ───────────────────────────────────────────────────────── # fzf-fish: Superior fzf integration - Ctrl+R history, Ctrl+Alt+F files, Ctrl+V vars { name = "fuck.fzf.fish"; src = pkgs.fetchFromGitHub { owner = "PatrickF1"; repo = "fzf.fish"; rev = "v10.3"; hash = "sha256-T8KYLA/r/gOKvAivKRoeqIwE2pINlxFQtZJHpOy9GMM="; }; } { name = "tide"; src = tide.src; } # forgit: Interactive git with fzf (ga, glo, gi, gd, grh, gcf, gss, gclean) { name = "forgit"; src = forgit.src; } # ── Quality of Life ─────────────────────────────────────────────────────── # autopair: Auto-insert matching brackets, quotes, etc. { name = "autopair"; src = autopair.src; } # done: Notifications when long-running commands complete { name = "done"; src = done.src; } # sponge: Remove failed commands and typos from history automatically { name = "sponge"; src = sponge.src; } # puffer: Text expansions (!! for last command, !$ for last argument) { name = "puffer"; src = puffer.src; } # colored-man-pages: Colorize man pages for better readability { name = "colored-man-pages"; src = colored-man-pages.src; } # ── Git Enhancement ─────────────────────────────────────────────────────── # plugin-git: Git aliases and status helpers (similar to oh-my-zsh git) { name = "plugin-git"; src = plugin-git.src; } # ── Shell Compatibility ─────────────────────────────────────────────────── # bass: Run bash scripts and capture environment changes { name = "bass"; src = bass.src; } # foreign-env: Source files from other shells (bash, zsh env files) { name = "foreign-env"; src = foreign-env.src; } # ── Utility ─────────────────────────────────────────────────────────────── # grc: Colorize output of common commands (ping, traceroute, make, etc.) { name = "grc"; src = grc.src; } ]; # ═══════════════════════════════════════════════════════════════════════════ # INTERACTIVE SHELL INITIALIZATION # ═══════════════════════════════════════════════════════════════════════════ interactiveShellInit = '' echo "🐟 "(set_color cyan)(whoami)(set_color normal)" @ "(set_color yellow)(hostname -s)(set_color normal)" in "(set_color green)(prompt_pwd)(set_color normal) ''; # ═══════════════════════════════════════════════════════════════════════════ # SHELL INIT (runs for all shells, including non-interactive) # ═══════════════════════════════════════════════════════════════════════════ shellInit = '' # Ensure locale is set properly for UTF-8 if test -z "$LANG" set -gx LANG en_US.UTF-8 end if test -z "$LC_ALL" set -gx LC_ALL en_US.UTF-8 end ''; # ═══════════════════════════════════════════════════════════════════════════ # LOGIN SHELL INIT # ═══════════════════════════════════════════════════════════════════════════ loginShellInit = '' # Add any login-specific initialization here # This runs only for login shells ''; }; # ═════════════════════════════════════════════════════════════════════════════ # ADDITIONAL PACKAGES needed for fish plugins and functions # ═════════════════════════════════════════════════════════════════════════════ home.packages = with pkgs; [ grc # Generic colorizer (for grc plugin) libnotify # For done plugin notifications (Linux) ] ++ lib.optionals pkgs.stdenv.isDarwin [ terminal-notifier # For done plugin notifications (macOS) ]; }