在没有键绑定的情况下执行 readline 函数?

在没有键绑定的情况下执行 readline 函数?

我刚刚阅读 readline 手册页,发现了一堆我不知道的很棒的命令。但是,有些没有默认的键绑定。有没有办法从 shell 执行未绑定的命令?

我不是问如何在 ~/.inputrc 中绑定命令,而是问如何从 shell 或 bash 脚本中“一次性”执行它。

例如,“转储变量”命令。是否有一些命令我可以将“转储变量”作为参数提供给它来执行?

答案1

我相信您正在寻找的是bind命令本身。根据man builtin信息,运行bind <readline-command>允许您一次性运行,但是,我无法让它像手册上所说的那样工作......它一直使密钥对我不起作用;你的旅费可能会改变。我确实找到了以下可能对您有用的命令。

bind -p # Equivalent to dump-functions [machine readable]
bind -P # Equivalent to dump-functions [human readable]

bind -s # Equivalent to dump-macros    [machine readable]
bind -S # Equivalent to dump-macros    [human readable]

bind -v # Equivalent to dump-variables [machine readable]
bind -V # Equivalent to dump-variables [human readable]

编辑备注 我想指出它并不像手册所说的那样工作是多么烦人,因为如果您输入bind然后按 Tab 键自动完成,它会显示所有命令。

答案2

一种很有意义的情况是,当该行为空时,“重载”默认击键,因为在这种情况下许多绑定是没有意义的,因此许多最舒适的击键被浪费了,而它们可能非常有用。就像是

alt_n() {
    [ -z $READLINE_LINE ] && do_something_else || execute_default_command
}
bind -x '"\en": alt_n'

否则,您必须为所有受影响的绑定实现默认行为,这在某些情况下相当容易,而其他时候则不然,然后它永远只是一个黑客行为,容易出现奇怪的错误。一个实际有效的例子(幸运的是,EOF 就是这样处理的),因为我一直不小心关闭会话,所以我在 .profile 中有stty eof ^B和。export IGNOREEOF=2现在,<C-B>当光标离开时,在行编辑器中工作得很好,但在空提示下我可以按 3 次来终止。

至少对我来说,它从来没有引起混乱,我总是知道我是在输入命令还是只是坐在空行上。换句话说,所有提示都是隐式模态的,浪费了很多热键空间,如果将其中一些与辅助绑定一起使用,那就真的很整洁了。具体来说,我来到这里是因为我想分别使用<M-f><M-b>来调用pushd +1pushd -1,同时保留原始功能。

我什至在考虑修补 bash,虽然我不是 C 专家,但这不可能很难扩展bind内置函数以接受单个参数,然后调用相应的 readline 函数。我想知道是否有人已经这样做了。

答案3

我认为你在这里忽略了一个理论问题。

执行 readline 命令仅在读取内容时才有意义。但是当 bash 命令运行时,bash 通常不再读取。

Readline 是一个库,独立于 bash。你用它就像

// start reading 
char * input = readline("this is the prompt$ ");
// at this place, reading ended
// do something with input
free(input);

Readline 只能在运行forward-word时执行其命令(例如 ) 。readline()

当您输入imaginary_cmd_for_executing_readline forward-word并按bash回车键时,则readline()已经终止,因此无法forward-word再执行。在 bash 的源代码中(或在自定义可加载内置函数中),您可以自己调用任何 readline 命令后面的 C 函数(例如rl_forward_word代替forward-wordrl_get_previous_history代替previous-history),但这些可能会失败,因为它们读取和写入内存区域那个时候可能无法使用。即使它们是,您也不会得到任何结果,因为它们只会修改行缓冲区并且实际上不会打印任何内容。

Bash 在 readline 中注册了一些可能在readline()运行时运行的函数,例如当

  • 信号到达(例如按下 时ctrlc)。
  • 执行 bash 的自定义 readline 命令之一(例如shell-expand-line);仅当输入已注册的按键序列时才会发生这种情况。
  • bind -x输入注册的任何按键序列。

在这样的挂钩中,理论上您可以执行 readline 命令。但它们都需要击键本身作为触发器,因此与直接绑定相比,使用它们没有任何好处。但最重要的是,正如我之前所解释的,在不编辑行时单独运行 readline 命令可能没有意义。

如果确实必须,您可以临时将任何键绑定到要运行的命令,然后将该击键自动从后台发送到终端本身,请参阅bash 可以写入自己的输入流吗?

相关内容