将命令视为其他命令以完成目的

将命令视为其他命令以完成目的

我的 zshrc 包含以下函数来创建目录然后进入它:

function mcd () {
    mkdir -p "$*" && cd "$*"
}

该函数本身工作正常,但完成后我得到了奇怪的行为。如果我开始输入 例如mcd ~/然后按Tab,则会显示消息

_mtools_drives:3: command not found: mtoolstest

被插入到插入点,什么也没完成。我想要的是命令的完成就像mkdir这样:zsh 应该为我提供现有目录的名称。

我如何告诉 zsh 为了完成目的,它应该视为mcd相同mkdir

答案1

以下代码片段会导致mcd完成,如下所示mkdir

compdefas () {
  if (($+_comps[$1])); then
    compdef $_comps[$1] ${^@[2,-1]}=$1
  fi
}
compdefas mkdir mcd

它的工作方式是查找 的当前完成设置mkdir。函数的完成代码(通常是完成函数的名称)存储在关联数组中_comps。因此compdef $_comps[mkdir] mcd声明应该以与现在完成的mcd方式相同的方式完成。mkdir

上面的函数添加了一些细节:

  • 的测试(($+_comps[$1]))确保如果$1没有指定的完成方法,则不会为其他参数设置完成方法。
  • ${@[2,-1]}是从第二个参数开始的函数参数列表,因此您可以指定多个命令名称来定义补全。其实是${^@[a,-1]}这样的为每个数组元素复制数组扩展周围的文本
  • =$1设置要使用的服务名称。这仅对于少数命令重要,这些命令的完成函数处理多个密切相关的命令。例如,完成函数_gzip可以处理gzipandgunzip以及pigzand unpigz;使用while的默认行为compdef _gzip foo使用for 完成时的行为。foo_gzipcompdef _gzip foo=pigzfoo_gzippigz

转向您的具体情况,默认完成不仅mkdir提供目录,还提供您的函数不支持的选项。因此,您实际上最好定义mcd为仅完成现有目录。 Zsh 附带了一个辅助函数(一个未记录的包装器)_files)。

compdef _directories mcd

您得到这些看起来奇怪的完成的原因mcd是它是曾经相当广泛的命令套件中的一个命令的名称工具箱

答案2

compdef使用以下形式:

compdef [ -ane ] function name

所以一种想法是通过以下命令将nameof指向mcd该函数:_mkdir

compdef _mkdir mcd

然而,这有点不正确,因为mkdir完成了可能不应该给出的各种标志cd。更直接的方法是在目录上完成:

compdef _directories mcd

相关内容