从文件中让zsh自动完成参数

10

zsh很棒,但它的补全系统非常多样化。而且文档缺乏良好的示例。是否有一个特定应用程序的完成模板。完成将从一个由换行符分隔的文件中获取匹配数据?

我尝试修改我之前写的一个需要“实时”获取匹配数据的旧示例:

~ % cat .zsh/completers/_jazzup 
#compdef jazz_up
_arguments "2: :(`mpc lsplaylists|sed -e 's# #\\\\ #g'`)"

我可以使用cat my_file代替mpc来完成这个简单的任务,但是有没有更优雅的方式呢?并且那里的自动补全是位置特定的:你能提供一个例子,在程序名称被识别后,zsh 会尝试在任何时候都进行补全吗?

匹配数据中可能包含空格等字符,补全应该对空格进行转义。例如:

Foo bar
Barbaric
Get it (42)

现在,如果该完成(completion)被配置为一个命令Say,那么我们应该从zsh中获得这种行为:

$ Say Fo<TAB>
$ Say Foo\ bar
$ Say Ge<TAB>
$ Say Get\ it\ \(42\)
2个回答

22

使用 _describe 更好地解决简单的自动完成需求,它将一个包含完成选项和其描述的数组配对(可以使用多个数组/描述对,请查看手册)。

(_arguments功能强大但太复杂。)

[...]

首先创建一个文件。

echo "foo\nbar\nbaz\nwith spac e s\noh:noes\noh\:yes" >! ~/simple-complete

然后在您的$fpath中的某个位置创建一个名为_simple的文件:

#compdef simple

# you may wish to modify the expansion options here
# PS: 'f' is the flag making one entry per line
cmds=( ${(uf)"$(< ~/simple-complete)"} ) 

# main advantage here is that it is easy to understand, see alternative below
_describe 'a description of the completion options' cmds

# this is the equivalent _arguments command... too complex for what it does
## _arguments '*:foo:(${cmds})'

then

function simple() { echo $* }
autoload _simple # do not forget BEFORE the next cmd! 
compdef _simple simple # binds the completion function to a command

simple [TAB]

它可以工作。只需确保完成文件 _simple 放置在您的 fpath 中的某个位置。

请注意,选项列表中的冒号:应用于将选项与其(各自的)描述(oh:noes)分隔开。因此,这不能与_describe一起使用,除非您对其进行引用(oh\:yes)。被注释掉的_arguments示例将不使用冒号:作为分隔符。


太棒了。如果您能稍微详细介绍一下引用和细节,我会授予一些奖励金,但这是我正在寻找的完美示例。 - mike3996
2
非常感谢。这是我找到的迄今为止最简洁的zsh自动补全教程。它应该得到比它现在所获得的更多的赞。 - Lyndsy Simon
我在哪里可以获取有关 uf 标志的信息? - Timo
如果您忘记自动加载,它将无法工作。在自动加载后,它可以正常工作。请参见此处 - Timo
文档中说您可以像“_simple”那样自己编写compdefs,但是我没有找到如何做到。文档很差.. - Timo
如果有人想在没有file的情况下查看_describecmds=('--stat:Zeige Dateinamen' '-p: Zeige Inhalte' '--graph:Zeige foo') _describe 'Git Log P.' cmds - Timo

2

在不进一步更改.zshrc的情况下(我已经有autoload -Uz compinit compinit),我将以下内容添加为/usr/local/share/zsh/site-functions/_drush

#compdef drush
_arguments "1: :($(/usr/local/bin/aliases-drush.php))"

/usr/local/bin/aliases-drush.php 只打印字符串列表时,每个字符串都可以作为命令drush的第一个参数。 您可以使用($(< filename))filename完成补全。

我基于https://unix.stackexchange.com/a/458850/9452 进行了编写 - 在一天结束时,这是多么简单啊。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接