对于我所尝试的,TAB
在C-i
.inputrc 中似乎意味着同样的事情,无论我绑定到一个,都会绑定到另一个。我知道最初是同一件事,而且这种行为是从旧时代继承下来的,但现在,除了终端仿真器之外,所有 X 应用程序都区分了 aC-i
和TAB
press。
那么有没有办法在我按下该TAB
键时运行终端命令(例如“完成”)并在按下时运行另一个命令C-i
?
(同样的问题适用于C-m
和ENTER
、C-z
、C-d
以及所有这些控制序列,我想通过原始绑定之外的其他方式发送这些控制序列,并将我自己的命令应用于这些珍贵的键绑定)
顺便说一句,如果你能解释一下从按键到 shell 解释的过程,这将有助于我理解。现在我明白键盘事件由 Xmodmap 翻译,然后由 .inputrc 翻译,结果由 shell 或类似的东西解释。
我目前使用 Guake,有时还使用 gnome-terminal 作为终端模拟器。
在遵循评论中提出的链接后,终端仿真器似乎是将TAB
keysym 从 X 服务器转换为C-i
并将其发送到 bash shell 的链的元素,因为它不理解诸如TAB
、ENTER
和同级之类的东西。因此,配置 readline 本身将不起作用,因为它位于终端模拟器之后、bash shell 之前。那么问题可以这样精确:如何配置我的终端模拟器,以便将TAB
and C-i
、ENTER
andC-m
等转换为不同的字符序列对?也许制作TAB
并ENTER
发送一个新的自定义转义序列,该序列可以稍后在 .inputrc 中映射到原始命令,并最终能够用于C-i
其他C-m
目的。或者离开TAB
并ENTER
制作C-i
并C-m
发送转义序列。
答案1
终端模拟器将“Tab按键被按下”等事件转换为终端中运行的应用程序(在您的情况下为 bash)读取的字符序列。看键盘输入和文本输出如何工作?有关此主题的更详细介绍。
Ctrl由于历史原因,一些键发送的字符与按下其他字符相同: Tab= Ctrl+ I、Return= Ctrl+ M、Esc= Ctrl+ [。这是因为历史物理终端这样做了,所以在终端中运行的应用程序期望它,所以终端这样做。
Guake 和 Gnome 终端都使用VTE图书馆,这不允许配置从键和弦到字符序列的映射。你有同样的问题bash - 与 control+alt+space 的键序列绑定错误
Xterm具有完全可配置的键绑定。您可以让Tab按键发送制表符(这是默认值),或者让它发送字符串hello
,或者您选择的任何内容。 Xterm 配置通过X资源。例如,要在按下和释放时Tab发送转义序列,请将其放入您的:\e[t
\e]t
~/.Xresources
XTerm.vt100.translations: #override \
<Key>Tab: string("\033[t") \n\
<KeyRelease>Tab: string("\033]t") \n\
或者您可能会留下Tab发送制表符并 make Ctrl+I发送其他内容:
XTerm.vt100.translations: #override \
Ctrl~Meta~Shift<Key>I: string("\033[a5i") \n\
Ctrl~Meta Shift<Key>I: string("\033[a6i") \n\
然后,您可以\e[a5i
使用可配置的键绑定绑定到 bash 和其他终端应用程序中您想要的任何内容。
请注意,按照惯例,多字符转义序列以转义字符开头(在编程语言和配置文件中通常表示为\e
or\033
或\x1b
);某些应用程序可能会遇到以其他字符开头的转义序列的问题,当然,您不能拥有一个既是转义序列又是其自己的键的字符,除非您愿意接受超时(这就是它在像 vi 这样的应用程序Esc本身就绑定了某些功能)。如果您定义自己的键序列,请注意不要与功能键和光标键发送的键序列冲突,这些键序列是或多或少事实上标准化。
答案2
为了添加 Gilles 的出色答案,在 urxvt 终端模拟器中,也可以通过配置键映射.Xresources
:例如,我将以下行添加到该文件中,以便与Ctrl+Backspace
(Ctrl+H
比较这个问题),这样我就可以以不同的方式使用两个关键和弦:
# Map Ctrl+Backspace to little-used escape sequence
urxvt.keysym.C-BackSpace: \033[33~
之后我将以下内容添加到 my 中~/.zshkbd
以使 zsh 区分两个关键和弦:
bindkey "^H" kill-line
# Ctrl + Backspace
bindkey "\033[33~" backward-delete-word
我相信对于zshCtrl+I
和TAB
其他应用程序来说,它应该以类似的方式工作(尽管在这种情况下,显然会重新映射Ctrl+I
到不同的字符)。