如何禁用 NFS 目录的 zsh 制表符补全?

如何禁用 NFS 目录的 zsh 制表符补全?

我使用zsh及其 Tab 补全功能。当我在(慢速)NFS 目录中意外按下 Tab 键时,zsh会花费太长时间。更糟糕的是,如果 NFS 已关闭,而我按下/mnt/[tab],我的整个 shell 都会被锁定。

如何禁用zsh这些目录中的制表符补全?

答案1

如果您在这些目录中,要完全禁用完成功能,您可以使用以下代码:

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/树从完成系统中排除。根据文档,这应该可以解决问题:

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/* ]]

[编辑]

我重新设计了这个 hack,让它更加灵活,但它仍然存在问题,我仍然确信直接修改完成函数(也许_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

相关内容