使用命令输出生成zsh的自动完成命令

5
嗨,我正在尝试让zsh运行一个git命令,并使用输出生成自动补全选项。
我正在尝试运行的命令是:
git log -n 2 --pretty=format:"'%h %an'"

以下是我使用的代码:

local lines words

lines=(${(f)$(git log -n 2 --pretty=format:"'%h %an'")})
words=${(f)$(_call_program foobar git log -n 2 --pretty=format:"%h")}

echo "Length of lines is " ${#lines[@]} " value is " ${lines}
echo "Length of words is " ${#words[@]} " value is " ${words}

compadd -d lines -a -- words

这根本不起作用...它认为words是一个单独的元素,行根本没有正确地打印出来。

然而,当我手动设置一个字符串数组时,所有东西都能正常工作。

local lines words

lines=('one two' 'three')
words=('one two' 'three')

echo "Length of lines is " ${#lines[@]} " value is " ${lines}
echo "Length of words is " ${#words[@]} " value is " ${words}

compadd -d lines -a -- words

compadd中,那真的是一个字面上的words而不是"$words[@]"吗? - geekosaur
@geekosaur 是的,没错。-a选项让compadd查找指定的数组。而"$words[@]"是bash代码,尽管它可能在zsh中工作,因为zsh开发人员关注与bash的兼容性,但明智的zsh开发人员会只写$words而不是那个(它通常可以正常工作,无论数组值中有什么符号)。 - ZyX
3个回答

4
为了将单词强制转换为数组,您应该使用以下任一方法:
words=( ${(f)...} )

或者

set -A words ${(f)...}

如果你只使用words=${(f)...},你将始终得到一个值。顺便说一下,在编写lines定义时,为什么要在${(f)...}周围加括号,但没有对words进行这样的操作?

另外,还有一件事需要注意:${(f)$(...)}应该被替换成${(f)"$(...)"}。这里有一些黑魔法:我不知道为什么第一个会发出单个标量值,而第二个会发出标量值数组,只是被stackoverflow上的某个人指出了这个事实。


1

感谢你的帮助,ZyX,这是最终的脚本,供有需要的人参考。

local lines words

lines=(${(f)"$(git log -n 15 --pretty=format:"'%h - %an - %s'")"} )
words=(${(f)"$(git log -n 15 --pretty=format:"%h")"})

compadd -l -d lines -a -- words

0

我遇到了一个更加复杂的情况。我试图在许多文件中使用grep查找一个字符串,然后编辑结果文件列表。使用**和*通配符并不能让上述解决方案对我起作用。我通过分成两个步骤来解决了这个问题:

> tmp=$(grep -l someString **/*.clj)
> fileList=( ${(f)tmp} )

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