我的 zshrc 包含以下函数来创建目录然后进入它:
function mcd () {
mkdir -p "$*" && cd "$*"
}
Run Code Online (Sandbox Code Playgroud)
该函数本身工作正常,但完成后我得到了奇怪的行为。如果我开始输入 例如mcd ~/
然后按Tab,则会显示消息
_mtools_drives:3: command not found: mtoolstest
Run Code Online (Sandbox Code Playgroud)
被插入到插入点,什么也没完成。我想要的是命令的完成就像这样mkdir
:zsh 应该为我提供现有目录的名称。
我如何告诉 zsh 为了完成目的,它应该视为mcd
相同mkdir
?
以下代码片段会导致mcd
完成,如下所示mkdir
:
compdefas () {
if (($+_comps[$1])); then
compdef $_comps[$1] ${^@[2,-1]}=$1
fi
}
compdefas mkdir mcd
Run Code Online (Sandbox Code Playgroud)
它的工作方式是查找 的当前完成设置mkdir
。函数的完成代码(通常是完成函数的名称)存储在关联数组中_comps
。因此compdef $_comps[mkdir] mcd
声明应该以与现在完成的mcd
方式相同的方式完成。mkdir
上面的函数添加了一些细节:
(($+_comps[$1]))
确保如果$1
没有指定的完成方法,则不会为其他参数设置完成方法。${@[2,-1]}
是从第二个参数开始的函数参数列表,因此您可以指定多个命令名称来定义补全。实际上${^@[a,-1]}
,数组扩展周围的文本会为每个数组元素复制。=$1
设置要使用的服务名称。这仅对于少数命令重要,这些命令的完成函数处理多个密切相关的命令。例如,完成函数_gzip
可以处理gzip
andgunzip
以及pigz
and unpigz
;compdef _gzip foo
使用whilefoo
的默认行为使用for 完成时的行为。_gzip
compdef _gzip foo=pigz
foo
_gzip
pigz
转向您的具体情况,默认完成mkdir
不仅提供目录,还提供您的函数不支持的选项。因此,您实际上最好定义mcd
为仅完成现有目录。Zsh 附带了一个辅助函数(一个未记录的包装器_files
)。
compdef _directories mcd
Run Code Online (Sandbox Code Playgroud)
您得到这些看起来奇怪的补全的原因是,它是曾经相当广泛的命令mtoolsmcd
套件中的命令名称。
compdef
使用以下形式:
compdef [ -ane ] function name
Run Code Online (Sandbox Code Playgroud)
所以一种想法是通过以下命令将name
of指向mcd
该函数:_mkdir
compdef _mkdir mcd
Run Code Online (Sandbox Code Playgroud)
然而,这有点不正确,因为mkdir
完成了可能不应该给出的各种标志cd
。更直接的方法是在目录上完成:
compdef _directories mcd
Run Code Online (Sandbox Code Playgroud)