zsh: Dynamically ignore files for autocomplete
This is a small article about a pattern I’ve made to automatically ignore filenames for autocompletion.
In the zshell you can use CORRECT_IGNORE_FILE to ignore files for spelling
corrections (or autocorrect for commands). While handy, it is somewhat limited
as it is global and perhaps somewhat limited. Now, I wanted to ignore it only
for git and not other commands. But I haven’t found a way to only target git
without having to make a wrapper around git (which I don’t want to do).
So I wrote an autoloaded function that does this for me. The idea is rather
simple. In your .zshrc you set a zstyle that tells which file should be
ignored based on files (or directories) that exist in the current directory.
Based on this you build the CORRECT_IGNORE_FILE environment variable or you
just unset it. This function is then hooked into the chpwd action. I went
with three default options, check dir, file, or just exist: d, f, or e. File
wins, then directory, then exists.
# in your .zshrc
zstyle ':waterkip:correct-ignore:d' app '.git app'
add-zsh-hook chpwd set-correct-ignore
The actual autoloaded function is seen here:
# set-correct-ignore
local word dirs check_type all_exist
local ignore_words=()
for check_type in f d e; do
local -A rules
zstyle -g patterns ':waterkip:correct-ignore:'$check_type
for word in $patterns
do
zstyle -a ':waterkip:correct-ignore:'$check_type $word dirs
all_exist=1
for dir in ${=dirs}; do
case $check_type in
e) [[ -e $dir ]] || { all_exist=0; break };;
d) [[ -d $dir ]] || { all_exist=0; break };;
f) [[ -f $dir ]] || { all_exist=0; break };;
esac
done
(( all_exist )) && ignore_words+=($word)
done
done
if (( ${#ignore_words} )); then
export CORRECT_IGNORE_FILE="${(j:|:)ignore_words}"
else
unset CORRECT_IGNORE_FILE
fi
Now you can enter, in this case a Laravel project and git ap won’t trigger a
correction from zsh: zsh: correct 'ap' to 'app' [nyae]?. Sweet! Totally :)