Zsh:如何强制文件在一组字符后处处完成?
我正试图找出如何使文件完成在命令行中一组字符之后的任何Zsh:如何强制文件在一组字符后处处完成?,zsh,zshrc,zsh-completion,Zsh,Zshrc,Zsh Completion,我正试图找出如何使文件完成在命令行中一组字符之后的任何word位置上工作。如shell中所列,这些字符将是[=+-\'\'”()](空格为制表符和空格)。Zsh将执行此操作,但仅在反勾字符“`”或$”()之后执行此操作。mksh不在字符[+-]之后执行此操作 根据命令行上的单词位置,我指的是您键入的每一组字符,它们由空格和一些其他字符分隔。例如 打印Hello World 在位置1-3处有三个单词。在位置1处,当您第一次输入内容时,补全非常完美。文件补全可以在我提到的所有字符之后工作。在第一个单
word
位置上工作。如shell中所列,这些字符将是[=+-\'\'”()]
(空格为制表符和空格)。Zsh将执行此操作,但仅在反勾字符“`”或$”(
)之后执行此操作。mksh不在字符[+-]
之后执行此操作
根据命令行上的单词位置,我指的是您键入的每一组字符,它们由空格和一些其他字符分隔。例如
打印Hello World
在位置1-3处有三个单词
。在位置1处,当您第一次输入内容时,补全非常完美。文件补全可以在我提到的所有字符之后工作。在第一个单词
之后,补全系统变得更加有限,因为它很智能。这对命令很有用,但限制了您可以做的事情文件完成并不是特别有帮助
以下是一些文件完成对我不起作用但我认为应该起作用的例子:
:${a:=/…}
echo“${a:-/…}”
make LDFLAGS+='-nostlib/../crt1.o/../crti.o…'
env a=/…b=/…
我已经看过重新绑定“^I”
(选项卡)Zsh附带了一些不同的完成小部件,并更改了我的zstyle':completion:'
行。到目前为止,还没有任何东西能改变这个默认的Zsh行为。我想我需要创建一个完成函数,我可以将它添加到我的zstyle':completion:'completer…
行的末尾,作为最后的补偿伊顿
在completion函数中,一种方法是将当前的单词
切掉,完成它,然后如果可能的话,将其重新插入行中。它也可能更像\u precommand
,将第二个单词
移动到第一个单词
,以便正常的命令执行莱顿工作
我可以修改\u precommand
,以便您可以在任何word
位置完成命令。这是新文件,我将其命名为\u commando
,并将其目录添加到我的fpath:
#compdef -
# precommands is made local in _main_complete
precommands+=($words[1,$(( CURRENT -1 ))])
shift words
CURRENT=1
_normal
为了使用它,我将它添加到了我的:completion:'completer…
行的末尾,因此它适用于$path
中的每个程序。基本上,您键入的任何word
都被认为是第一个word
,因此命令完成在命令行的每个word
位置都有效
我正试图找到一种方法来完成同样的文件完成工作,但一开始看起来有点复杂。我真的不知道该怎么做,所以我想在这方面获得一些帮助。我仔细查看了Zsh的一些内置函数,发现了一些具有特殊完成行为的函数。它们属于
typeset
组,它在默认的fpath
中有一个功能\u typeset
。我只需要提取几行就可以完成我想做的事情。这些是我提取的行:
...
elif [[ "$PREFIX" = *\=* ]]; then
compstate[parameter]="${PREFIX%%\=*}"
compset -P 1 '*='
_value
...
这几行允许在命令中的每个斜杠后完成排版,如下所示:
typeset file1=/... file2=~/... file3=/...
_reallyforcefilecompletion() {
local prefix_char
for prefix_char in ' ' $'\t' '=' '+' '-' "'" '"' ')' ':'; do
if [[ "$PREFIX" = *${prefix_char}* ]]; then
if [[ "$PREFIX" = *[\'\"]* ]]; then
compset -q -P "*${prefix_char}"
else
compset -P "*${prefix_char}"
fi
_value
break
fi
done
}
zstyle ':completion:*' completer _complete _reallyforcefilecompletion
我由此推断创建了以下函数。您可以将其修改为放入fpath
。我只是在我的zshrc中这样定义它:
typeset file1=/... file2=~/... file3=/...
_reallyforcefilecompletion() {
local prefix_char
for prefix_char in ' ' $'\t' '=' '+' '-' "'" '"' ')' ':'; do
if [[ "$PREFIX" = *${prefix_char}* ]]; then
if [[ "$PREFIX" = *[\'\"]* ]]; then
compset -q -P "*${prefix_char}"
else
compset -P "*${prefix_char}"
fi
_value
break
fi
done
}
zstyle ':completion:*' completer _complete _reallyforcefilecompletion
您可以通过将其添加到zstyle
行来使用它,如下所示:
typeset file1=/... file2=~/... file3=/...
_reallyforcefilecompletion() {
local prefix_char
for prefix_char in ' ' $'\t' '=' '+' '-' "'" '"' ')' ':'; do
if [[ "$PREFIX" = *${prefix_char}* ]]; then
if [[ "$PREFIX" = *[\'\"]* ]]; then
compset -q -P "*${prefix_char}"
else
compset -P "*${prefix_char}"
fi
_value
break
fi
done
}
zstyle ':completion:*' completer _complete _reallyforcefilecompletion
这样,它只能作为最后的手段使用,以便更智能的补全可以在它之前尝试。以下是对该函数的一些解释,从涉及的几个变量和命令开始:
prefix\u char
:这将设置为我们要在后面完成的每个前缀字符。例如,env a=123
具有前缀字符=
前缀
:最初,这将设置为当前单词的一部分,从单词的开头到光标的位置;可以更改为为所有匹配项提供一个公共前缀
IPREFIX
(未在代码中显示):compset
将字符串匹配项从PREFIX
移动到IPREFIX
,以便完成PREFIX
的其余部分
compset
:此命令简化了特殊参数的修改,而其返回状态允许对其执行测试
\u value
:对这一点不太确定。文档说明它在完成过程中起到某种作用
函数:在第二行,我们声明prefix\u char
local
以避免变量污染。在第三行,我们开始for
循环,选择每个prefix\u char
之后要完成的。在下一个if
块中,我们检查变量prefix
是否以前缀字符
我们希望在之后完成,如果前缀
包含任何引号。由于前缀
包含引号,我们使用compset-q
基本上允许忽略引号,以便我们可以在其中完成。compset-P
去除前缀
,并将其移动到IPREFIX
,基本上是这样它会被忽略,完成也会起作用
下一个elif
语句用于以PREFIX_char结尾但不包含引号的PREFIX
语句,因此我们只使用compset-p
。我添加了return 0
来打破循环。更正确的方法是在case
语句中创建此函数,但我们没有使用compset
return除了\u value
,你看不到任何关于文件完成的信息。在大多数情况下,我们只是告诉系统忽略单词的一部分
基本上这就是函数所做的