不要在选项卡完成时扩展通配符

BMo*_*ler 6 zsh wildcards tab-completion

我想知道如何配置zsh扩展文件名中的通配符。例如,我有一个包含数百个文件的目录,名称如下:

a.foo-bar a.foo b.foo-bar b.foo c.foo-bar c.foo
Run Code Online (Sandbox Code Playgroud)

我希望能够通配符执行选项卡完成匹配,所以

cat *.foo-< tab > => cat *.foo-bar
Run Code Online (Sandbox Code Playgroud)

这是我得到的:

$ cat *.foo-
=> cat a.foo-bar
   文件
   a.foo-bar b.foo-bar c.foo-bar

mpy*_*mpy 7

一种选择是,你替换默认键绑定TAB

bindkey "^I" expand-or-complete
Run Code Online (Sandbox Code Playgroud)

bindkey "^I" complete-word
Run Code Online (Sandbox Code Playgroud)

这不会将 a 扩展*到所有匹配的文件,但不会触及星号。这样您就可以摆脱无休止的列表,但它仍然无法完成通配符表达式。

要解决这个问题要棘手得多。您必须编写自己的完成小部件(请参阅 参考资料man zshcompwid)。

  1. 让我们从定义开始:

    zle -C complete-glob menu-complete compglob
    
    Run Code Online (Sandbox Code Playgroud)

    这引入了新的小部件complete-glob,它的行为类似于menu-complete并使用shell 函数 compglob来生成匹配项。

    [注意:如果您不想要菜单完成,请使用更基本的选项complete-wordlist-choices ]

  2. 将此新小部件绑定到一个方便的快捷方式,例如CTRL+K

    bindkey "^K" complete-glob
    
    Run Code Online (Sandbox Code Playgroud)

    不要将此绑定到TAB,因为当前形式的小部件仅完成文件!

  3. 定义shell函数compglob如下,它做实际工作:

    compglob () {
        setopt localoptions globsubst
        compset -P '*'
        files=(${IPREFIX}*) 
        display=(${files/${IPREFIX}/${(q)IPREFIX}}) 
        glob=(${files/${IPREFIX}/}) 
        compadd -d display -- $glob
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 示范:

    $ touch a.foo-bar a.foo b.foo-bar b.foo c.foo-bar c.foo
    $ cat *.f<CTRL+K>
    $ cat *.foo
    \*.foo      \*.foo-bar
    
    Run Code Online (Sandbox Code Playgroud)

    我看到的唯一缺陷是\显示列表中的星星前面。但这只是一个光学缺陷,因为完成是正确的:*.foo*.foo-bar


hym*_*mie 0

我认为这是不可能的。您不仅要求 shell 找出您希望哪些文件最终成为“根据通配符扩展有效”,而且还希望 shell 找出将扩展的“最佳”通配符表达式这边走。我希望第二部分是 NP 完全的。