zsh 模糊模式匹配删除键入的字符

zsh 模糊模式匹配删除键入的字符

我在 zshrc 中使用以下内容:

zstyle ':completion:*' matcher-list 'm:{[:lower:]}={[:upper:]} r:|?=**'

(这要归功于马龙

但我发现一些奇怪的行为。例如采取以下测试用例:


% tree zsh-test 
zsh-test
├── a-xx
├── b-xx
└── somefile

然后打字ls zsh-test/xx和点击Tab我可能期望看到的a-xx并列b-xx为可能性。相反,没有列出任何内容xx我输入的部分是已删除

我认为正在发生的事情是xx生成两个选项,然后 zsh 正在寻找一个公共前缀,但没有找到一个,因此将我的文本替换为任何内容。这不是很有帮助。我有RTM但这并没有帮助我实现找到直观的模糊匹配器模式的目标。

有没有办法让它显示与模式匹配的候选者,而不删除我的模式?

这种行为的奇怪之处在于,我什至无法习惯它,因为如果我在目录内zsh-test并输入内容,ls xx Tab那么它会按预期工作 - 显示两个候选人!

答案1

发生这种情况是因为 Zshzsh-test/在第一种情况下将其视为明确的前缀,而在第二种情况下,没有明确的前缀。 (是的,有一个明确的后缀,但不幸的是,Zsh 对此没有做任何事情。)默认情况下,如果 Zsh 看到明确的前缀,那么第一次按Tab将简单地插入该前缀,可能会删除您已经存在的字符键入。

您可以通过在 shell 中输入以下内容来测试这一点:

autoload -Uz compinit && compinit
zstyle ':completion:*' matcher-list 'm:{[:lower:]}={[:upper:]} r:|?=**'
bindkey '^I' complete-word
zle -C complete-word complete-word complete-word

complete-word() {
  _main_complete;
  compadd -x "unambiguous prefix: '${compstate[unambiguous]}'";
  compstate[list]='list force';
}

然后,再次尝试您的两个案例。对于第一种情况,您将看到unambiguous prefix: 'zsh-test/'.对于第二种情况,你会看到unambiguous prefix: ''

不幸的是,没有办法配置Zsh 以获得您想要的行为。但是,如果您愿意更深入地研究兔子洞,那么可以通过将以下脚本添加到您的.zshrc文件中来实现您想要的行为:

zmodload -i zsh/complist
autoload -Uz compinit && compinit
zstyle ':completion:*' matcher-list 'm:{[:lower:]}={[:upper:]} r:|?=**'
bindkey '^I' complete-word
zle -C complete-word menu-select complete-word

complete-word() {
  _main_complete;
  compstate[list]='list';
  local word=$PREFIX$SUFFIX
  (( compstate[unambiguous_cursor] <= ${#word} )) && compstate[insert]='menu';
}
  • compstate[list]='list'确保当有多个匹配可用时自动列出完成情况。
  • 最后一行检查默认行为是否会删除光标所在的当前单词的任何部分,如果是,则插入列表中的第一项。
  • 然后,(由menu-select提供zsh/complistzle -C complete-word menu-select complete-word可让您使用您的选择Tabarrow keys从列表中选择不同的项目。

以这种方式调整 Zsh 的完成系统可能很快就会变得相当复杂,而且其中的许多部分都没有详细记录。我强烈建议您查看我的zsh-autocomplete插入,它定制了 Zsh 完成系统,以开箱即用地完成大多数人期望它做的事情。

答案2

完成菜单后,您确实会得到两个zsh-test/a-xxzsh-test/b-xx。我无法告诉你为什么 xx 被删除。但从你所说的看来你试图获得模糊匹配,并且可能有更简单的方法。

'r:|?=**'相当具有侵略性。就模糊性而言,它允许在每个输入的字符之间存在额外的字符,但不处理转置字符之类的事情。 Just'b:=*'将允许子字符串和_approximate完成器以某种更受控制的方式处理近似值,更喜欢需要较少校正的匹配。

相关内容