您实际上无法C-[像使用那样在用户级地图上更改绑定global-set-key
。但是,您可以在到达这些键盘映射之前将其更改为键盘事件。您可以说例如:
(define-key input-decode-map
(kbd "C-[")
[control-bracketleft])
然后[control-bracketleft]
在您的键盘映射中使用。很简单,不是吗?
导演剪辑版
不幸的是,它并不是那么简单,并且该解决方案需要进行一些调整,这似乎非常痛苦。您已被警告。但首先让我们看看为什么用户级地图不能回答这个问题。在下文中,当我说“看到一些东西”而没有更高的精度时,我将参考emacs 26.1的Emacs Lisp手册。
C-[在很早的阶段就被解释为ASCII控制字符ESC
(请参见21.7.1- 键盘事件)。此代码将其他地方扩展为更长序列的前缀。还有一个原因:ESC
实际元前缀(见meta-prefix-char
),并读取所有绑定
M-的东西将转化为一个序列开始用ESC
。因此,仅更改全局地图是不够的:您需要先进行更改meta-prefix-char
,然后再重新映射ESC
至meta-prefix-char
所使用的每张地图中的新地图,M-然后才能安全地进行映射C-[。
那当然可以了:让我们使用input-decode-map
。我们可能会尝试使用几张相似的地图(请参阅第21.8.3和22.14节),但让我们继续坚持下去。好吧...这有效!完成了,不是吗?
其实,不,故事还没有结束。只要您使用的是窗户系统,它就可以工作。如果由于运气不好而在紧急状态下被囚禁在Linux控制台中,那么您就会意识到这种情况变得多么严重:箭头键,Home当然还有M-绑定都是垃圾。为什么?因为当终端说出ESC
(键入时会执行此操作C-[)时,它实际上表示 ESC
,并启动了与传输非ASCII字符相同类型的序列。
观察灾难,您可能认为明智input-decode-map
的做法是,以仅在窗口系统正在控制键盘的情况下激活的方式保护上述修改:
(let ((frame (framep (selected-frame))))
(or (eq t frame)
(eq 'pc frame)
(define-key input-decode-map
(kbd "C-[")
[control-bracketleft])
)))
然后,终端可以像往常一样工作。
现在,我们可以C-[在终端上处理吗?实际上,是的,在Linux控制台以及我可以使用的其他终端仿真器上,我们可以做到。但是随着新角色的出现,这使得这个故事很长。因为不再仅仅是emacs:终端现在扮演着中心角色。
让我们听听linux控制台怎么说。键入C-v某些键之前听到它平原。C-[是ESC
; 也是Esc。向上箭头听起来像ESC [ A
,M-a而是
ESC A
。嗯...看起来像是emacs中的meta键绕行了,不是吗?无论如何。
除非我们已准备好根据字符事件(其中的方式将不区分之间的时间玩一些技巧
Esc的C-[),看来我们得无奈地告诉控制台其实我们不要吝啬ESC
当我们键入C-[。此外,似乎很快C-[就不再是库存终端代码的唯一问题:修饰符大部分时间都被抹去了所传输的信息。我们出于与定制emacs相同的原因而需要定制终端:如果这样做,它将更加实用。
此时,您应该深入了解终端的文档眼睛:loadkeys(1)
Linux控制台的手册页,“ 自定义键绑定”xterm(1)
部分的xterm
以及其他终端的what-i-dont-know。在,您可以定义自定义转换设置/编辑当前配置文件...
然后键盘。以下是
播放后一个对话框后的摘录:KDE konsole
~/.local/share/konsole/Test.keytab
key [+Ctrl+AnyModifier : "\EO*["
一旦你的终端发送ESC O 5 [
的
C-[(如上面的配置),你可以回去emacs的。当然,您还没有完成。
要指示emacs给定终端使用什么方言,可以调整input-decode-map
。是的,很幸运,这是我们在本文开头所修改的内容,并且是
term/xterm.el
涉及xterm时的内容。进行调整的好地方是tty-setup-hook
(请参阅第40.1.3节):
(add-hook 'tty-setup-hook
(lambda ()
(let ((term (getenv "TERM")))
(cond
(;; xterm-function-map not in doc, but in term/xterm.el
(boundp 'xterm-function-map)
(map-my-term-codes xterm-function-map))
((equal term "linux")
(map-my-term-codes input-decode-map))
)
)))
请注意,只有在终端中时,此挂钩才会运行。因此,您不能在此处插入窗口系统初始化的代码。这里是翻译功能本身:
(defun map-my-term-codes (map)
(define-key map (kbd "M-O 5 [")
[control-bracketleft])
)
然后您可以休息一下:这是旅程的终点。当然,如果您不关心终端,那将很快,因为您将跳过所有痛苦的部分。但是您会承认它还很不完整。
最后两个注意事项:
编辑
- 我Esc在另一篇文章:如何删除与ESC前缀键的绑定中完成了这种具有自己个性的案例
这是要提供的配置的一部分loadkeys
。我将其放在/root/custom.kmap中,并在需要时加载它(这种情况很少见)。我的实际配置还映射了箭头和修饰符的不同组合,但是它相当长,选择符号和序列是有问题的,而且我不确定键盘的键码是否会与您的键盘匹配。因此,让我们将其保持在适当的水平:这只是一个例证。
keymaps 0-127
# http://tldp.org/HOWTO/Keyboard-and-Console-HOWTO-15.html
# web+man:keymaps
# web+man:loadkeys
# escape
keycode 1 = F100
alt keycode 1 = Escape # keep the Escape behavior somewhere
# keycode 26 = bracketleft
control keycode 26 = F115 # Control_bracketleft does not exist
string F100 = "\033OO" # map this to [escape] in map-my-term-codes
string F115 = "\033O5["