将上一个命令中的参数添加到 zsh 补全中

将上一个命令中的参数添加到 zsh 补全中

在 zsh(以及 bash)中,您可以使用一些历史词扩展来表示先前命令的参数。

此示例显示通过扩展从历史记录中的上一个命令获取第二个参数!:#

% echo foo bar baz
foo bar baz
% echo !:2
echo bar
bar

我经常忘记某个特定参数到底是什么 # 参数,并且!:#当我记住它是什么参数时,输入并不总是那么快。我知道要meta-.替换最后一个参数,但有时它不是我想要的最后一个参数。

我想添加上一个命令中的参数作为建议,以完成我在 zsh 中键入的任何命令。

我能够弄清楚如何创建一个 shell 函数,该函数可以从最后一个命令创建一个参数数组 (0..N) 并将其绑定到特定命令。

_last_command_args() {
    last_command=$history[$[HISTCMD-1]]
    last_command_array=("${(s/ /)last_command}") 
    _sep_parts last_command_array
}

# trying to get last_command_args to be suggested for any command, this just works for foo
compdef _last_command_args foo

这就是完成 foo 的样子,我点击了 tab 键<TAB>

% echo bar baz qux
bar baz qux
% foo <TAB>
bar   baz   echo  qux 

这对于完成命令“foo”非常有用,但我希望这些成为我所做的任何 zsh 扩展的选项。我认为这与 zstyle 完成者的东西有关,但经过几个小时的黑客攻击后,我意识到我已经超出了我的能力范围。

如何从上一个命令中获取参数作为 zsh 中任何命令的建议补全?

我已经满了zshrc 编译安装文件如果有帮助的话,请在 bitbucket 上分享。其中很多内容是从各种来源抄袭的,其中一些是我自己编写的。

更新:

@Julien Nicoulaud 的回答让我很接近,我将其标记为已接受,因为它让我到达了我需要到达的地方。

根据我的特定配置,使用建议的:

zstyle ':completion:*' completer _last_command_args _complete

对我来说不太有效,因为它导致制表符完成仅显示最后一个命令的参数列表(尽管它实际上也完成了文件名,只是不显示它们)。更改顺序即可_complete _last_command_args实现相反的效果。它会显示正常的文件名,但不显示last_command_args

我猜这与完成器的工作方式有关。我认为它只显示第一个成功返回的方法的输出,但我在解析 zsh 源以完全理解发生了什么时遇到困难。我能够调整我的方法以包含对的调用,_complete以便它显示最后一个参数命令以及常规自动完成内容。不太分开,但对我来说已经足够好了。

这是我使用的完整函数以及我拥有的其他 zstyle 东西:

# adds the arguments from the last commadn to the autocomplete list
# I wasn't able to get this to work standalone and still print out both regular
# completion plus the last args, but this works well enough.
_complete_plus_last_command_args() {
    last_command=$history[$[HISTCMD-1]]
    last_command_array=("${(s/ /)last_command}") 
    _sep_parts last_command_array
    _complete 
}


_force_rehash() {
  (( CURRENT == 1 )) && rehash
  return 1  # Because we didn't really complete anything
}

zstyle ':completion:::::' completer _force_rehash _complete_plus_last_command_args _approximate 

我拥有的其他 zstyle 行,对于此功能来说不是必需的,但可能会影响为什么这对我有用:

zstyle -e ':completion:*:approximate:*' max-errors 'reply=( $(( ($#PREFIX + $#SUFFIX) / 3 )) )'
zstyle ':completion:*:descriptions' format "- %d -"
zstyle ':completion:*:corrections' format "- %d - (errors %e})"
zstyle ':completion:*:default' list-prompt '%S%M matches%s'
zstyle ':completion:*' group-name ''
zstyle ':completion:*:manuals' separate-sections true
zstyle ':completion:*' menu select
zstyle ':completion:*' verbose yes

file1.txt现在,如果我位于包含and的目录中file2.txt,并且我的最后一个命令是echo foo bar baz,我会得到这个自动完成功能,这正是我想要的:

% ls
bar   baz   echo  foo 
- files -
file1.txt   file2.txt 

答案1

您可以将完成者添加到默认使用的完成者列表中:

zstyle ':completion:*' completer _last_command_args _complete

相关内容