Compare commits

...

6 Commits

Author SHA1 Message Date
rootiest 233d75434c Merge pull request 'feat(completions): unify cd/z completions across CWD, CDPATH, and zoxide' (#13) from cd-completions into main
Reviewed-on: #13
2026-05-12 03:58:41 +00:00
rootiest 520217d4a9 fix(zoxide): suppress missing-zoxide startup message
Silent degradation is cleaner; the shell already handles the
missing binary gracefully without any output.
2026-05-11 23:57:46 -04:00
rootiest 4e255f4502 chore(license): add copyright/SPDX headers to zoxide files
- Add copyright + SPDX header to functions/zoxide.fish and
  conf.d/zoxide.fish (modified from original, owned by Rootiest)
- Add sourced-from attribution to completions/zoxide.fish
  (unmodified from icezyclon/zoxide.fish, MIT)
2026-05-11 23:47:27 -04:00
rootiest 6d91f49521 fix(completions): add cdi function as alias for zi
cdi was documented and expected to work as an interactive zoxide
directory picker but was never defined as a function, causing it
to silently fail. Wraps zi so completions are inherited correctly.
2026-05-11 23:37:21 -04:00
rootiest 2e3230974c feat(completions): unify cd/z completions across CWD, CDPATH, and zoxide
Previous to this commit, tab completion and auto-suggestions for cd/z
were inconsistent — only one or two of: CWD, CDPATH, and zoxide frecency
results would work at a time, with different sourced matches shown in
tab completion, shown in auto-suggest, and execution after pressing
<Enter>.

- Add _zoxide_z_complete in functions/zoxide.fish that merges all three
  sources into a single completion list (CWD via __fish_complete_cd,
  CDPATH via __fish_complete_directories, zoxide via query -l capped at
25)
- Wire the new completer to both z and cd via complete directives in
  conf.d/zoxide.fish, replacing the previous incomplete approach
- Add completions/zoxide.fish for full tab completion of the zoxide CLI
  itself (add, query, remove, import, init subcommands)
- Update README to document the unified completion behavior and fix
  structural issues in Personalization/Attribution/Dependencies sections
2026-05-11 23:28:59 -04:00
rootiest f93f9844dc build(ignore): add case-insensitive patterns for local testing and temporary files
Consolidates and expands the .gitignore to ignore various temporary and
testing directories. This allows for local experimentation with new
ideas
and the preservation of disabled functions without the risk of
accidentally committing them to the repository.
2026-05-11 23:22:18 -04:00
6 changed files with 177 additions and 102 deletions
+7
View File
@@ -36,3 +36,10 @@ OLD/
# Auto-managed by fish; contains machine-local state and universal vars # Auto-managed by fish; contains machine-local state and universal vars
fish_variables fish_variables
.claude .claude
# Personal testing/temporary files
[Tt][Mm][Pp]/
[Tt][Ee][Mm][Pp]/
[Tt][Ee][Mm][Pp][Oo][Rr][Aa][Rr][Yy]/
[Tt][Ee][Ss][Tt][Ii][Nn][Gg]/
[Dd][Ee][Bb][Uu][Gg]/
+15 -5
View File
@@ -15,7 +15,7 @@ A feature-rich Fish shell configuration for CachyOS (Arch Linux), built around a
- [Dependencies](#dependencies) - [Dependencies](#dependencies)
- [Installation](#installation) - [Installation](#installation)
- [Personalization](#personalization) - [Personalization](#personalization)
- [Full Requirements](#full-requirements) - [Attribution](#attribution)
- [License](#license) - [License](#license)
--- ---
@@ -107,7 +107,14 @@ See [FZF Bindings](#fzf-bindings) under Key Bindings for the default FZF shortcu
### Zoxide ### Zoxide
Smart `cd` replacement. `cd` (or `z`) `<keyword>` jumps to the best frecency match; `cdi` (or `zi`) opens an interactive selector. Smart `cd` replacement powered by frecency scoring. `cd`, `z`, and `cdi`/`zi` are all mapped to zoxide-backed navigation functions.
| Command | Description |
|---|---|
| `cd <path>` / `z <path>` | Jump to a matching directory by frecency; falls back to exact path |
| `cdi` / `zi` | Open an interactive fzf selector across all frecency-ranked directories |
Tab completions for `cd` and `z` blend standard directory entries (CWD and `CDPATH`) with zoxide frecency results, so familiar paths and frequently-visited destinations appear together in a single list. Full tab completions for the `zoxide` CLI itself (subcommands: `add`, `query`, `remove`, `import`, `init`) are provided via `completions/zoxide.fish`.
### DirEnv ### DirEnv
@@ -493,6 +500,10 @@ Named context shortcuts (e.g. `dcr`, `dck`) live in `~/.config/.user-dots/fish/l
| [Kitty](https://sw.kovidgoyal.net/kitty/) / [WezTerm](https://wezfurlong.org/wezterm/) | Terminal emulator | | [Kitty](https://sw.kovidgoyal.net/kitty/) / [WezTerm](https://wezfurlong.org/wezterm/) | Terminal emulator |
| [WakaTime](https://wakatime.com/) | Activity tracking | | [WakaTime](https://wakatime.com/) | Activity tracking |
### Full Requirements
For a complete, categorized list of all non-standard tools required or used by this configuration, see [requirements.md](requirements.md).
--- ---
## Installation ## Installation
@@ -512,7 +523,6 @@ Then open a new Fish shell — Fisher and all plugins will be installed automati
A [chezmoi](https://www.chezmoi.io/) dotfile manager is also configured — secrets are sourced from `~/.config/.user-dots/fish/secrets.fish` and excluded from version control. A [chezmoi](https://www.chezmoi.io/) dotfile manager is also configured — secrets are sourced from `~/.config/.user-dots/fish/secrets.fish` and excluded from version control.
--- ---
## Personalization ## Personalization
Sensitive credentials and machine-specific paths are kept out of version control via a secondary private directory at `~/.config/.user-dots/fish/`. Two files are sourced automatically by `config.fish` if they exist: Sensitive credentials and machine-specific paths are kept out of version control via a secondary private directory at `~/.config/.user-dots/fish/`. Two files are sourced automatically by `config.fish` if they exist:
@@ -585,9 +595,9 @@ end
--- ---
## Full Requirements ## Attribution
For a complete, categorized list of all non-standard tools required or used by this configuration, see [requirements.md](requirements.md). The core of the [Zoxide integration](#zoxide) in this repository was originally adapted from the [icezyclon/zoxide.fish](https://github.com/icezyclon/zoxide.fish) plugin (MIT Licensed) and has since been heavily customized for performance and Fish 4.x compatibility.
--- ---
+43
View File
@@ -0,0 +1,43 @@
# Sourced from icezyclon/zoxide.fish (MIT)
set -l commands add help import init query remove
# disable normal all-files completion
complete -c zoxide -f
# onyl show base options if none was used already
complete -c zoxide -n __fish_use_subcommand -a add -d "Add a new directory or increment its rank"
complete -c zoxide -n __fish_use_subcommand -a help -d "Prints this message or the help of the given subcommand(s)"
complete -c zoxide -n __fish_use_subcommand -a import -d "Import from z database"
complete -c zoxide -n __fish_use_subcommand -a init -d "Generates shell configuration"
complete -c zoxide -n __fish_use_subcommand -a query -d "Search for a directory"
complete -c zoxide -n __fish_use_subcommand -a remove -d "Remove a directory"
# zoxide add
complete -c zoxide -n "_zoxide_equals_first_token add" -n "__fish_is_nth_token 2" -a "(__fish_complete_directories)"
# zoxide help
complete -c zoxide -n "_zoxide_equals_first_token help" -n "__fish_is_nth_token 2" -a "$commands"
# zoxide import
complete -c zoxide -r -F -n "_zoxide_equals_first_token import" -n "__fish_is_nth_token 2"
complete -c zoxide -r -n "_zoxide_equals_first_token import" -l merge -d "Merge entries into existing database"
# zoxide init
set -l initshells bash fish posix powershell zsh
complete -c zoxide -n "_zoxide_equals_first_token init" -n "__fish_is_nth_token 2" -a "$initshells"
complete -c zoxide -n "_zoxide_equals_first_token init" -l cmd -d "Renames the 'z' command and corresponding aliases [default: z]"
complete -c zoxide -n "_zoxide_equals_first_token init" -l hook -a "none prompt pwd" -d "Chooses event on which an entry is added to the database [default: pwd]"
complete -c zoxide -n "_zoxide_equals_first_token init" -l no-aliases -d "Prevents zoxide from defining any commands other than 'z'"
# zoxide query
complete -c zoxide -r -n "_zoxide_equals_first_token query" -s i -l interactive -d "Opens an interactive selection menu using fzf"
complete -c zoxide -r -n "_zoxide_equals_first_token query" -s l -l list -d "List all matching directories"
complete -c zoxide -r -n "_zoxide_equals_first_token query" -s s -l score -d "Display score along with result"
# zoxide remove
complete -c zoxide -n "_zoxide_equals_first_token remove" -n "__fish_is_nth_token 2" -a "(zoxide query -l)"
# Always possible
complete -c zoxide -x -s h -l help -d "Prints help information"
complete -c zoxide -x -s V -l version -d "Prints version information"
+61 -99
View File
@@ -1,106 +1,68 @@
# ============================================================================= # Copyright (C) 2026 Rootiest
# # SPDX-License-Identifier: AGPL-3.0-or-later
# # Adapted from icezyclon/zoxide.fish (MIT)
# Utility functions for zoxide. # Heavily customized for Fish 4.x compatibility and performance
#
if not type -q zoxide if status is-interactive
return
end
# pwd based on the value of _ZO_RESOLVE_SYMLINKS. if type -q zoxide
function __zoxide_pwd
builtin pwd -L
end
# A copy of fish's internal cd function. This makes it possible to use # -------------
# `alias cd=z` without causing an infinite loop. # 'zoxide init fish' is very different for different versions of zoxide
if ! builtin functions --query __zoxide_cd_internal # to guarantee the same behavior we define these functions ourself,
string replace --regex -- '^function cd\s' 'function __zoxide_cd_internal ' <$__fish_data_dir/functions/cd.fish | source # especially because the apt package is so old
end # most of these functions were taken from https://github.com/ajeetdsouza/zoxide
# from version 0.8.1
# cd + custom logic based on the value of _ZO_ECHO. if ! builtin functions -q _zoxide_cd
function __zoxide_cd if builtin functions -q cd
if set -q __zoxide_loop builtin functions -c cd _zoxide_cd
builtin echo "zoxide: infinite loop detected"
builtin echo "Avoid aliasing `cd` to `z` directly, use `zoxide init --cmd=cd fish` instead"
return 1
end
__zoxide_loop=1 __zoxide_cd_internal $argv
end
# =============================================================================
#
# Hook configuration for zoxide.
#
# Initialize hook to add new entries to the database.
function __zoxide_hook --on-variable PWD
test -z "$fish_private_mode"
and command zoxide add -- (__zoxide_pwd)
end
# =============================================================================
#
# When using zoxide with --no-cmd, alias these internal functions as desired.
#
# Jump to a directory using only keywords.
function __zoxide_z
set -l argc (builtin count $argv)
if test $argc -eq 0
__zoxide_cd $HOME
else if test "$argv" = -
__zoxide_cd -
else if test $argc -eq 1 -a -d $argv[1]
__zoxide_cd $argv[1]
else if test $argc -eq 2 -a $argv[1] = --
__zoxide_cd -- $argv[2]
else else
set -l result (command zoxide query --exclude (__zoxide_pwd) -- $argv) alias _zoxide_cd='builtin cd'
and __zoxide_cd $result end
end
function _zoxide_hook --on-variable PWD
test -z "$fish_private_mode"
and command zoxide add -- (builtin pwd -L)
end
function z
set argc (count $argv)
if test $argc -eq 0
_zoxide_cd $HOME
else if test "$argv" = -
_zoxide_cd -
else if test -d $argv[-1]
_zoxide_cd $argv[-1]
else
set -l result (command zoxide query $argv)
and _zoxide_cd $result
end
end
function zi
set -l result (command zoxide query -i -- $argv)
and _zoxide_cd $result
end
# -------------
alias cd=z
# use custom completion
complete -c z -f # disable files by default
complete -c z -x -a '(_zoxide_z_complete)'
end
end
function _zoxide_uninstall --on-event zoxide_uninstall
if alias | grep "alias cd z" >/dev/null
functions -e cd
end
if builtin functions -q _zoxide_cd && not functions -q cd
# restore old cd
builtin functions -c _zoxide_cd cd
end end
end end
# Completions.
function __zoxide_z_complete
set -l tokens (builtin commandline --current-process --tokenize)
set -l curr_tokens (builtin commandline --cut-at-cursor --current-process --tokenize)
if test (builtin count $tokens) -le 2 -a (builtin count $curr_tokens) -eq 1
# If there are < 2 arguments, use `cd` completions.
complete --do-complete "'' "(builtin commandline --cut-at-cursor --current-token) | string match --regex -- '.*/$'
else if test (builtin count $tokens) -eq (builtin count $curr_tokens)
# If the last argument is empty, use interactive selection.
set -l query $tokens[2..-1]
set -l result (command zoxide query --exclude (__zoxide_pwd) --interactive -- $query)
and __zoxide_cd $result
and builtin commandline --function cancel-commandline repaint
end
end
complete --command __zoxide_z --no-files --arguments '(__zoxide_z_complete)'
# Jump to a directory using interactive search.
function __zoxide_zi
set -l result (command zoxide query --interactive -- $argv)
and __zoxide_cd $result
end
# =============================================================================
#
# Commands for zoxide. Disable these using --no-cmd.
#
abbr --erase z &>/dev/null
alias z=__zoxide_z
abbr --erase zi &>/dev/null
alias zi=__zoxide_zi
abbr --erase cdi &>/dev/null
alias cdi=__zoxide_zi
# =============================================================================
# Initialize zoxide:
zoxide init --cmd=cd fish | source
+6
View File
@@ -0,0 +1,6 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
function cdi --wraps zi --description 'Interactively jump to a directory using zoxide (alias for zi)'
zi $argv
end
+47
View File
@@ -0,0 +1,47 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# Adapted from icezyclon/zoxide.fish (MIT)
# Heavily customized for Fish 4.x compatibility and performance
function _zoxide_z_complete -d "Complete directory first or zoxide queries otherwise" --argument-names comp desc
# comp is the currently completing token
if not set -q comp[1]
set comp (commandline -ct)
end
# cmd are all tokens including the current one except the command
set -l cmd (commandline -opc) $comp
set -e cmd[1]
# 1. Get standard completions (CWD, CDPATH, etc.)
# We call the underlying functions directly to avoid recursion.
if test (count $cmd) -le 1
# CDPATH results
__fish_complete_cd
# Local directory results (CWD)
__fish_complete_directories "$comp" ""
end
# 2. Get zoxide results
# Cap results to 25 to avoid overwhelming the completion engine
set -l zresults (zoxide query -l $cmd | head -n 25)
for res in $zresults
set -l bname (basename $res)
# If the basename matches the prefix, show it as a short name.
if string match -qi "$comp*" -- $bname
printf "%s/\tzoxide: %s\n" $bname $res
end
# Also provide the absolute path. Fish will filter it if it doesn't match.
printf "%s/\tzoxide\n" $res
end
end
function _zoxide_equals_first_token -a check -d "Test if first non-switch token equals given one"
set -l tokens (commandline -co)
set -e tokens[1]
set -l tokens (string replace -r --filter '^([^-].*)' '$1' -- $tokens)
if set -q tokens[1]
test $tokens[1] = $check
else
return 1
end
end