├── Readme.md └── init.fish /Readme.md: -------------------------------------------------------------------------------- 1 | # fish-completion-sync 2 | 3 | A fish plugin to help dynamically load fish completions from `$XDG_DATA_DIRS`. 4 | 5 | ## Installation 6 | 7 | ### home-manager 8 | 9 | ```nix 10 | { 11 | programs.fish = { 12 | # ... 13 | plugins = [ 14 | #... 15 | { 16 | name = "fish-completion-sync"; 17 | src = pkgs.fetchFromGitHub { 18 | owner = "pfgray"; 19 | repo = "fish-completion-sync"; 20 | rev = "ba70b6457228af520751eab48430b1b995e3e0e2"; 21 | sha256 = "sha256-JdOLsZZ1VFRv7zA2i/QEZ1eovOym/Wccn0SJyhiP9hI="; 22 | }; 23 | } 24 | ]; 25 | }; 26 | } 27 | ``` 28 | 29 | ### fisher 30 | ``` 31 | fisher install pfgray/fish-completion-sync 32 | ``` 33 | 34 | ## Why 35 | 36 | Fish only considers `$XDG_DATA_DIRS` on shell startup, and thus will not dynamically load completions if `$XDG_DATA_DIRS` changes sometime after the shell starts. This leads to problems when using tools like [direnv](https://github.com/direnv/direnv), which try to add completions on a per-folder basis. 37 | 38 | This plugin tries to alleviate this issue. 39 | 40 | tl;dr; it's the bit of glue between: 41 | https://github.com/fish-shell/fish-shell/issues/8261 42 | and: 43 | https://github.com/direnv/direnv/issues/443 44 | 45 | ## How it works 46 | 47 | Fish _will_ search `$fish_complete_path` dynamically, so the idea is to implement a function which listens for changes to `$XDG_DATA_DIRS`, and attempts to keep that in sync with `$fish_complete_path`. 48 | 49 | ``` 50 | function fish_completion_sync --on-variable XDG_DATA_DIRS 51 | 52 | # If there are paths in $FISH_COMPLETION_ADDITIONS, 53 | # but not in $XDG_DATA_DIRS 54 | # remove them from $fish_complete_path 55 | # remove them from $FISH_COMPLETION_ADDITIONS 56 | 57 | # if there are paths in $XDG_DATA_DIRS 58 | # but not in $FISH_COMPLETION_ADDITIONS 59 | # add them to $fish_complete_path 60 | # add them to $FISH_COMPLETION_ADDITIONS 61 | 62 | echo "got new data dirs: $XDG_DATA_DIRS" 63 | end 64 | ``` 65 | 66 | ### Caveats 67 | 68 | This has been working well for me, but it's stopped working a few times, and I haven't been able to pinpoint why. If you experience this, you can set the environment variable `FISH_COMPLETION_DEBUG` to help debug: 69 | 70 | ```fish 71 | set -x FISH_COMPLETION_DEBUG 1 72 | ``` 73 | 74 | Submit an issue if the problem persists. 75 | -------------------------------------------------------------------------------- /init.fish: -------------------------------------------------------------------------------- 1 | 2 | # Filters an item from an array 3 | # Usage: 4 | # > fish_completion_filter_from_array bar foo bar baz 5 | # > foo baz 6 | function fish_completion_sync_filter 7 | set -l item $argv[1] 8 | set -e argv[1] 9 | set -l array $argv 10 | for array_item in $array 11 | if [ $array_item != $item ] 12 | echo $array_item 13 | end 14 | end 15 | end 16 | 17 | function fish_completion_sync_add_comp 18 | set -l array $argv 19 | for array_item in $array 20 | echo "$array_item/fish/vendor_completions.d" 21 | end 22 | end 23 | 24 | set -g FISH_COMPLETION_ADDITIONS 25 | 26 | function fish_completion_sync --on-variable XDG_DATA_DIRS 27 | set -l FISH_COMPLETION_DATA_DIRS (fish_completion_sync_add_comp (fish_completion_sync_filter "" (string split ":" $XDG_DATA_DIRS))) 28 | # If there are paths in $FISH_COMPLETION_ADDITIONS, 29 | # but not in $XDG_DATA_DIRS 30 | # remove them from $fish_complete_path 31 | # remove them from $FISH_COMPLETION_ADDITIONS 32 | for addition in $FISH_COMPLETION_ADDITIONS 33 | # test if addition is in xdg_data_dirs 34 | if not contains $addition $FISH_COMPLETION_DATA_DIRS 35 | if set -q FISH_COMPLETION_DEBUG 36 | echo "removing: $data_dir" 37 | end 38 | set fish_complete_path (fish_completion_sync_filter $addition $fish_complete_path) 39 | set FISH_COMPLETION_ADDITIONS (fish_completion_sync_filter $addition $FISH_COMPLETION_ADDITIONS) 40 | end 41 | end 42 | 43 | # if there are paths in $XDG_DATA_DIRS 44 | # but not in $FISH_COMPLETION_ADDITIONS 45 | # add them to $fish_complete_path 46 | # add them to $FISH_COMPLETION_ADDITIONS 47 | for data_dir in $FISH_COMPLETION_DATA_DIRS 48 | if not contains $data_dir $FISH_COMPLETION_ADDITIONS 49 | if set -q FISH_COMPLETION_DEBUG 50 | echo "adding: $data_dir" 51 | end 52 | set -a fish_complete_path $data_dir 53 | set -a FISH_COMPLETION_ADDITIONS $data_dir 54 | end 55 | end 56 | end --------------------------------------------------------------------------------