如何根据历史记录为bind -x指定命令参数?

如何根据历史记录为bind -x指定命令参数?

假设我有一个名为 synopsis 的命令,它将命令的名称作为参数并打印出其语法。现在我想将概要绑定到按键序列。如何将当前命令行中的命令名称传递给概要?这是所需行为的示例:

1$ bind -x '"\C-h": synopsis !#:0'
2$ ls -F^H 
<ls syntax print out from synopsis> 
3$ ls -F

2 中调用了概要,但没有历史扩展。我得到字符串“!#:0”而不是“ls”。似乎没有什么作用:-/

答案1

在与按键绑定的函数中,可以通过变量访问和修改命令行的当前内容READLINE_LINEREADLINE_POINT。概念验证(未经测试的代码):

synopsis () (
  set -f
  IFS=$'\t\n\r ;&|'
  words=($READLINE_LINE)
  while [[ "${words[1]}" == @([<>]*|[A-Za-z0-9_]##=) ]]; do
    shift words
  done
  command=${words[1]}
  "$command" --help
)
bind -x '"\C-h": synopsis'

您尝试的历史扩展方法不起作用。执行命令行时会执行历史扩展。调用绑定时,没有可扩展的历史记录。

但你的根本问题是你的外壳不够酷。这个功能已经存在于 zsh 中,它的名字叫run-help

bash$ echo '自动加载运行帮助' >~/.zshrc
bash$ zsh
暗星%ls -FAlt+h

答案2

一种可能性是使用bindwithout -xsynopsis在行的开头插入:

bind "'\C-h": "\C-asynopsis \C-j"

只要有一个论点就可以了。更复杂的版本是:

bind '"\C-h": "\C-e !#:0\e^\e\C-] \C-usynopsis\C-j"'

分解一下:

'\C-e '    end-of-line
' !#:0'    insert space and 1st argument of current line
'\e^'      history-expand-line
'\e\C-] '  character-search-backward (to last space)
'\C-u'     unix-line-discard (delete to beginning of line)
'synopsis' insert 'synopsis' in front of the first argument
'\C-j'     accept-line

这处理具有多个参数的行,synopsis仅使用第一个参数运行。 (我也可能使用"\C-xh"or"\eh"代替"\C-h",它可能已经是擦除/退格/“向后删除字符”。)

相关内容