问题描述
我想为接受目录作为参数的命令编写自定义完成.我认为用一个例子来解释它应该如何工作是最容易的.
I want to write a custom completion for a command that accepts a directory as an argument. I think it's easiest to explain how it is supposed to work with an example.
假设我在某处定义了一个目录列表:
Let's assume I have a list of directories defined somewhere:
d=(~/somedir/foo ~/somedir/foo/bar ~/other/dir/baz)
对命令的有效调用是
mycmd foo
mycmd bar
mycmd baz
mycmd baz/and/some/subdir
完成后应该可以做
mycmd f<TAB> => mycmd foo
mycmd baz/and/some/s<TAB> => mycmd baz/and/some/subdir
不知何故,我对 zshcompsys 的复杂性有点迷茫,所以我不确定如何最好地实现这一点.
Somehow I'm a bit lost in the complexity of zshcompsys, so I'm not really sure how to approach this best.
推荐答案
1.预定义的目录作为参数.
如果你事先知道 mycmd
的参数可以是什么,你可以使用一个非常简单的完成函数,里面的值是硬编码的:
1. Pre-defined directories as arguments.
If you know in advance what the arguments of mycmd
can be, you can just use a very simple completion function with the values hard-coded inside:
#compdef _mycmd
_arguments "1: :(foo bar baz baz/and/some/subdir)"
这给出了以下内容:
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
2.完成一个目录内的所有子目录
假设 foo
的任何子目录都是 mycmd
的有效路径:
2. Completion to all subdirectories within a directory
Assuming that any subdirectory of foo
is a valid path for mycmd
:
~/foo/bar # Valid path
~/foo/subdir/baz # Valid path
~/baz/bar # Invalid path
你可以告诉 compctl
完成 foo
内的任何目录作为 mycmd
的参数:
you can tell compctl
to complete any directory within foo
as an argument to mycmd
:
# In your ~/.zshrc
compctl -/ -W ~/foo mycmd
我不知道这与您编写的 mycmd
的任何其他完成函数的效果如何(例如,如果 mycmd
也采用非文件名参数).它是这样完成的:
I do not know how well this will play with any other completion function for mycmd
that you have written (for example, if mycmd
also takes non-filename arguments). It completes like this:
zsh% mycmd<TAB>
bar/ baz/ caz/
zsh% mycmd baz/s<TAB>
zsh% mycmd baz/subdir/
注意:我的路径/命令有点长.我在下面的粘贴中剪掉了一些(替换为 ...
).
3.使用预定义的数组.
如果我们有一个数组 d=(foo bar baz)
,其中每个元素都是 mycmd
的有效补全,我们可以使用 -k:
Note: my paths / commands got a bit long. I've snipped some in the below pastes (replaced with ...
).
...
).3. Using pre-defined arrays.
If we have an array
d=(foo bar baz)
, where each element is a valid completion for mycmd
, we can use -k
:
→ compctl -k "(foo bar baz)" mycmd
→ mycmd
bar baz foo
4.数组的子目录.
使用以下目录结构:
4. Subdirectories of arrays.
Using the following directory structure:
~/.../somedir
~/.../somedir/bar
~/.../somedir/foo
~/.../somedir/foo/invalid
~/.../otherdir
~/.../otherdir/subdir
~/.../otherdir/subdir/baz
compctl
的 -W
选项也接受一个数组作为参数,允许这样做:
The
-W
option of compctl
also takes an array as an argument, allowing this:
→ compctl -/ -W "(/.../otherdir /.../somedir)" mycmd
→ mycmd <TAB>
bar/ foo/ subdir/
我很确定这现在与您想要的相匹配.
注意: -W
选项与 -/
一起使用(阅读 zshcompctl
的手册页)- -W
不能单独工作.
I'm fairly sure this now matches to what you want.
Note: The -W
option works with the -/
(read the man page for zshcompctl
) - -W
doesn't work on it's own.
让我们假设有效的参数是:
Let's assume that valid arguments are:
mycmd foo # Valid
mycmd baz # Valid
mycmd baz/and/some/subdir # Valid - subdirectory of `baz`
mycmd foo/subdir # Invalid!!
我们不想要
foo
的子目录,只想要baz
的子目录.我们可以通过混合 -k
和 -/-W
来实现:
where we do not want subdirectories of
foo
, only of baz
. We can achieve this by mixing -k
and -/ -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/
然而,这会留下
foo
的完整路径(与 -W
不同,它删除了它).要解决此问题,请不要将其放入 -k
的数组中:
This, however, leaves the full path to
foo
(unlike -W
, which removes it). To fix this, don't put it into the array for -k
:
compctl -/ -W "(/.../otherdir)" -k "(foo)" mycmd
这篇关于基于多个路径的自定义 zsh 完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!