我刚刚阅读 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 +1
和pushd -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-word
或rl_get_previous_history
代替previous-history
),但这些可能会失败,因为它们读取和写入内存区域那个时候可能无法使用。即使它们是,您也不会得到任何结果,因为它们只会修改行缓冲区并且实际上不会打印任何内容。
Bash 在 readline 中注册了一些可能在readline()
运行时运行的函数,例如当
- 信号到达(例如按下 时ctrlc)。
- 执行 bash 的自定义 readline 命令之一(例如
shell-expand-line
);仅当输入已注册的按键序列时才会发生这种情况。 bind -x
输入注册的任何按键序列。
在这样的挂钩中,理论上您可以执行 readline 命令。但它们都需要击键本身作为触发器,因此与直接绑定相比,使用它们没有任何好处。但最重要的是,正如我之前所解释的,在不编辑行时单独运行 readline 命令可能没有意义。
如果确实必须,您可以临时将任何键绑定到要运行的命令,然后将该击键自动从后台发送到终端本身,请参阅bash 可以写入自己的输入流吗?。