这个问题源于我的上一个关于 emacs beta 的问题。简而言之,我想绑定C-;
到终端中的 Emacs 函数,但似乎有东西在到达 Emacs 之前捕获了此键:Emacs 认为我按下了;
。
明显的嫌疑是终端模拟器,但我检查了其中的许多(xterm、gnome-terminal、terminator、terminology),但它们都不起作用。我很可能可以排除窗口管理器,因为在 Emacs 的 GUI 版本中,该键C-;
工作得很好。我还尝试了两种不同的 shell:bash 和 zsh,但再次没有成功。
我还能尝试什么?
答案1
也许您的困惑是因为没有使用实际的终端。当严肃的计算机只有几个立式冰箱那么大时,终端通过串行电缆使用字符和仅使用字符与中央计算机进行通信。这些字符是某些标准化字符集的一部分,例如 ASCII 或 EBCDIC,但通常是 ASCII。 ASCII 有 33 个控制字符,终端操作员通过按特殊键(例如 DEL)或按住 CTRL 键并按另一个键来发送它们。中央计算机只能看到最终的控制字符;它不知道按下什么键来产生该字符。
诸如 xterm 之类的终端仿真程序会模仿这种行为。终端仿真器提供了一种发送所有 33 个 ASCII 控制字符的方法,并且 Emacs 将接收这些字符(如果发送)。但 Emacs 就像上面描述中的中央计算机——当您在终端仿真器下运行它时,它无法知道实际按下了哪些键。因此,如果您按 CTRL 和分号,除非终端仿真程序已将这些按键映射到某个 ASCII 字符,否则 Emacs 将不知道已键入任何内容。
终端仿真器通常使用以下映射来生成控制字符†:
按键 ASCII -------------------- 逃生27 删除 127 退格键8 CTRL+空格键 0 CTRL+@0 CTRL+A 1 CTRL+B 2 CTRL+C 3 ETC... CTRL+X 24 CTRL+Y 25 CTRL+Z 26 CTRL+[ 27 CTRL+\ 28 CTRL+] 29 CTRL+^30 CTRL+_ 31
注意 CTRL+;没有出现在该列表中。终端通常只会发送分配给的可打印字符钥匙如果 CTRL+钥匙未映射到控制字符。那么你的终端模拟器通过发送告诉你什么;唯一的问题是,当您按下 CTRL+; 时,它不知道要做什么。
所有这些仅适用于您使用终端或终端仿真程序的情况。如果您在某个窗口系统下将 Emacs 作为本机应用程序运行,那么 Emacs 可以完全访问击键事件,而不仅仅是字符。因此,Emacs 可以看到您同时按下了 CTRL 和分号,并允许您为该按键对分配一个操作。
†终端通常具有功能键和箭头键,它们也会生成包含控制字符的字符序列。这些序列通常以 ASCII 代码 27 (ESCAPE) 开头。
答案2
终端传输字符(更准确地说:字节),而不是键。当您按下某个键或像Ctrl+这样的键和弦时;,该信息必须编码为字节序列。表示字符的键和弦,如A或Shift+A或À,作为该字符发送:a
, A
, à
(最后一个是一个或两个字节,具体取决于终端的字符编码)。
涉及功能键的按键没有对应的字符,因此它们作为转义序列发送:以转义字符开头的字节序列(\e
在 Emacs 字符串中,^[
如果在缓冲区中逐字输入,则显示为青色)。一些功能键有相应的字节,它们是控制字符。
键和键Ctrl+;没有标准转义序列,因此大多数终端模拟器都会生成字符;
。这会丢失Ctrl按下修改器的信息。
为了定义Ctrl+的绑定;,您需要配置终端模拟器以发送不同的转义序列。我不认为你可以用 Gnome 终端来做到这一点(Gnome 很少是可配置的)。您可以使用 Xterm 来完成。看有没有可以处理所有组合键的 Linux 终端?以获得指示。
不涉及您可能在终端中运行的 shell。 GUI Emacs 没有问题,因为 GUI (X11) 以编码键和修饰符的形式传输输入事件,而不仅仅是字符序列。
看键盘输入和文本输出如何工作?有关输入如何从键盘传输到应用程序的更多详细背景信息。