Чтобы полностью отключить завершение, если вы находитесь в этих каталогах, вы можете использовать этот код:
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
Это определяет функцию, которая проверяет, начинается ли ваш рабочий каталог с /mnt/
. Если нет, функция завершения по умолчанию вызывается через zle expand-or-complete
иначе выдается звуковой сигнал.
Функция объявлена как виджет (zle -N
) и привязана к TAB (bindkey
).
Тем не менее, это только начало, потому что, когда вы делаете что-то подобное
/foo/bar$ cp hello.c /mnt/[TAB]
Вы снова потерялись. Таким образом, вы также должны были исключить /mnt/
tree из системы завершения. Согласно документу, который должен сделать свое дело:
zstyle ':completion:*:*files' ignored-patterns '/mnt/*'
zstyle ':completion:*:*directories' ignored-patterns '/mnt/*'
Но я не уверен, что это предотвратит любой вызов функции stat для /mnt/
или только удалит совпадения после этого. Пожалуйста, попробуйте, и если все еще заметная задержка, расширьте предложение if в функции restricted-expand-or-complete
до
if [[ ! $PWD = /mnt/* && ! ${${(z)LBUFFER}[-1]} = */mnt/* ]]
[РЕДАКТИРОВАТЬ]
Я переработал этот хак, чтобы сделать его более гибким, но у него все еще есть проблемы, и я по-прежнему уверен, что непосредственное изменение функций завершения (возможно, _path_files
) будет намного чище. Тем не мение...
Это работает (резюме в примерах):
ls <TAB>
заблокирован внутри медленного каталога (/mnt
)
ls /mnt/<TAB>
заблокирован
ls /home/user/symlink_to_mnt/<TAB>
заблокирован
cd /; ls mnt/<TAB>
заблокирован
tar --exclude-from=/mnt/<TAB>
заблокирован (а также другие варианты, символическая ссылка, относительный путь)
Это не работает:
- завершение в пути все еще завершается
/m/s/p
в /mnt/some/path
- завершение параметров команды блокируется, если параметр не начинается с
-
, например, apt-get inst<TAB>
не будет работать внутри /mnt
- в
/
странное поведение происходит под Cygwin, с Linux все нормально
И вот код:
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