我的 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
可以处理gzip
andgunzip
以及pigz
andunpigz
;使用while的默认行为compdef _gzip foo
使用for 完成时的行为。foo
_gzip
compdef _gzip foo=pigz
foo
_gzip
pigz
转向您的具体情况,默认完成不仅mkdir
提供目录,还提供您的函数不支持的选项。因此,您实际上最好定义mcd
为仅完成现有目录。 Zsh 附带了一个辅助函数(一个未记录的包装器)_files
)。
compdef _directories mcd
您得到这些看起来奇怪的完成的原因mcd
是它是曾经相当广泛的命令套件中的一个命令的名称工具箱。
答案2
compdef
使用以下形式:
compdef [ -ane ] function name
所以一种想法是通过以下命令将name
of指向mcd
该函数:_mkdir
compdef _mkdir mcd
然而,这有点不正确,因为mkdir
完成了可能不应该给出的各种标志cd
。更直接的方法是在目录上完成:
compdef _directories mcd