How to disable zsh tab completion for NFS dirs?
Solution 1:
To disable the completion completely if you are in those directories, you can use this code:
function restricted-expand-or-complete() {
if [[ ! $PWD = /mnt/* ]]; then
zle expand-or-complete
else
echo -en "\007"
fi
}
zle -N restricted-expand-or-complete
bindkey "^I" restricted-expand-or-complete
This defines a function which checks if your working directory starts with /mnt/
. If not, the default completion function is called via zle expand-or-complete
otherwise a beep is produced.
The function is declared as a widget (zle -N
) and bound to TAB (bindkey
).
However, this is only a start, because when you do somethine like that
/foo/bar$ cp hello.c /mnt/[TAB]
you are lost again. So you also had to exclude the /mnt/
tree from completion system. According to the doc that should do the trick:
zstyle ':completion:*:*files' ignored-patterns '/mnt/*'
zstyle ':completion:*:*directories' ignored-patterns '/mnt/*'
But I'm not sure if that'll prevent any stat function call to /mnt/
or only removes the matches afterwards. Please try and if there's still a noticable delay, extend the if clause in the restricted-expand-or-complete
function to
if [[ ! $PWD = /mnt/* && ! ${${(z)LBUFFER}[-1]} = */mnt/* ]]
[EDIT]
I reworked this hack to be more flexible, but it still has issues and I'm still positive directly modifying the completion functions (perhaps _path_files
) would be much cleaner. However...
This works (a summary in examples):
-
ls <TAB>
is blocked inside a slow dir (/mnt
) -
ls /mnt/<TAB>
is blocked -
ls /home/user/symlink_to_mnt/<TAB>
is blocked -
cd /; ls mnt/<TAB>
is blocked -
tar --exclude-from=/mnt/<TAB>
is blocked (an also the other variants, symlink, relative path)
This doesn't work:
- in-path completion still completes
/m/s/p
to/mnt/some/path
- completion of command options is blocked, if the option does not start with
-
, e.g.apt-get inst<TAB>
won't work inside /mnt - in
/
strange behavior occurs under Cygwin, with Linux everything is fine
And here's the code:
function restricted-expand-or-complete() {
# split into shell words also at "=", if IFS is unset use the default (blank, \t, \n, \0)
local IFS="${IFS:- \n\t\0}="
# this word is completed
local complt
# if the cursor is following a blank, you are completing in CWD
# the condition would be much nicer, if it's based on IFS
if [[ $LBUFFER[-1] = " " || $LBUFFER[-1] = "=" ]]; then
complt="$PWD"
else
# otherwise take the last word of LBUFFER
complt=${${=LBUFFER}[-1]}
fi
# determine the physical path, if $complt is not an option (i.e. beginning with "-")
[[ $complt[1] = "-" ]] || complt=${complt:A}/
# activate completion only if the file is on a local filesystem, otherwise produce a beep
if [[ ! $complt = /mnt/* && ! $complt = /another/nfs-mount/* ]]; then
zle expand-or-complete
else
echo -en "\007"
fi
}
zle -N restricted-expand-or-complete
bindkey "^I" restricted-expand-or-complete