基于多个路径的自定义zsh完成

dan*_*i_l 1 zsh

我想为接受目录作为参数的命令编写自定义完成.我认为最简单的解释一下如何使用一个例子.

假设我有一个在某处定义的目录列表:

d=(~/somedir/foo ~/somedir/foo/bar ~/other/dir/baz)
Run Code Online (Sandbox Code Playgroud)

对命令的有效调用是

mycmd foo
mycmd bar
mycmd baz
mycmd baz/and/some/subdir
Run Code Online (Sandbox Code Playgroud)

完成应该能够做到

mycmd f<TAB>              => mycmd foo
mycmd baz/and/some/s<TAB> => mycmd baz/and/some/subdir
Run Code Online (Sandbox Code Playgroud)

不知怎的,我在zshcompsys的复杂性上有点迷失,所以我不确定如何最好地处理这个问题.

sim*_*ont 6

1.预定义目录作为参数.

如果你事先知道参数是什么mycmd,你可以使用一个非常简单的完成函数,里面的值是硬编码的:

 #compdef _mycmd
 _arguments "1: :(foo bar baz baz/and/some/subdir)"
Run Code Online (Sandbox Code Playgroud)

这给出了以下内容:

zsh% mycmd<TAB>
bar                    baz                    baz/some/other/subdir  foo    
zsh% mycmd baz<TAB>
baz                    baz/some/other/subdir
zsh% mycmd baz/<TAB>
zsh% mycmd baz/some/other/subdir 
Run Code Online (Sandbox Code Playgroud)

2.完成目录中的所有子目录

假设任何子目录foo是有效路径mycmd:

~/foo/bar         # Valid path
~/foo/subdir/baz  # Valid path
~/baz/bar         # Invalid path
Run Code Online (Sandbox Code Playgroud)

你可以告诉compctl完成任何目录foo作为参数mycmd:

# In your ~/.zshrc
compctl -/ -W ~/foo mycmd
Run Code Online (Sandbox Code Playgroud)

我不知道这对于mycmd您编写的任何其他完成函数有多好(例如,如果mycmd还采用非文件名参数).它像这样完成:

zsh% mycmd<TAB>
bar/  baz/  caz/
zsh% mycmd baz/s<TAB>
zsh% mycmd baz/subdir/
Run Code Online (Sandbox Code Playgroud)

注意:我的路径/命令有点长.我在下面的贴片中剪了一些(替换为...).

3.使用预定义的数组.

如果我们有一个数组d=(foo bar baz),其中每个元素都是有效的完成mycmd,我们可以使用-k:

? compctl -k "(foo bar baz)" mycmd
? mycmd
bar  baz  foo
Run Code Online (Sandbox Code Playgroud)

4.数组的子目录.

使用以下目录结构:

~/.../somedir
~/.../somedir/bar
~/.../somedir/foo
~/.../somedir/foo/invalid
~/.../otherdir
~/.../otherdir/subdir
~/.../otherdir/subdir/baz
Run Code Online (Sandbox Code Playgroud)

所述-W的选择compctl还带有一个数组作为参数,从而允许这样的:

? compctl -/ -W "(/.../otherdir /.../somedir)" mycmd
? mycmd <TAB>
bar/     foo/     subdir/
Run Code Online (Sandbox Code Playgroud)

我很确定这现在符合您的要求.
注意:-W选项适用于-/(阅读手册页zshcompctl) - -W不适用于它自己.

5.具有部分子目录的数组

我们假设有效的参数是:

mycmd foo  # Valid
mycmd baz  # Valid
mycmd baz/and/some/subdir # Valid - subdirectory of `baz`
mycmd foo/subdir # Invalid!! 
Run Code Online (Sandbox Code Playgroud)

在这里我们也不会要的子目录foo,只有baz.我们可以通过混合实现这一目标-k-/ -W:

? compctl -/ -W "(/.../otherdir)" -k "(/.../somedir/foo)" mycmd
? mycmd <TAB>
/Users/simont/sandbox/completion/somedir/foo  subdir/ 
? mycmd foo/<TAB> # No further completion - we can't complete foo/invalid. 
? mycmd subdir/<TAB>
? mycmd subdir/baz/
Run Code Online (Sandbox Code Playgroud)

然而,这留下了完整的路径foo(-W与之不同,它将其删除).要解决此问题,请不要将其放入数组中-k:

compctl -/ -W "(/.../otherdir)" -k "(foo)" mycmd
Run Code Online (Sandbox Code Playgroud)