4

Я использую zsh и завершение его вкладки. Когда я случайно нажимаю вкладку в (медленном) каталоге NFS, zsh занимает слишком много времени. Еще хуже, если NFS не работает, и я нажимаю /mnt/[tab] , вся моя оболочка блокируется.

Как отключить завершение zsh tab в этих папках?

1 ответ1

2

Чтобы полностью отключить завершение, если вы находитесь в этих каталогах, вы можете использовать этот код:

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .