GUI框架
在GUI框架(是否为X11,Windows,OSX等)中,Emacs会将Tab键读取为tab
功能键。但是,由于Tab传统上终端上的按键会发送^I
(Control + I)字符,因此Emacs 会将tab
功能键转换为Control + I字符(字符9),显示为TAB
。此翻译是通过进行的function-key-map
。
其他一些功能键也会发生类似的转换。(Backspace而且Delete是一个棘手的案例,在这里我不会详细讨论。)
Function key Translated to character Notes
Number Name Decomposition
backspace 127 DEL Ctrl+? May be translated to C-h instead
tab 9 TAB Ctrl+I
linefeed 10 LFD Ctrl+J Few keyboards have this key
return 13 RET Ctrl+M
escape 27 ESC Ctrl+[
如果您想完全Tab与Ctrl+ 分开,请从中I删除绑定function-key-map
:
(define-key function-key-map [tab] nil)
但是,这不是很有用,因为其中的条目function-key-map
被特定于模式的键映射或全局映射中的绑定覆盖。因此,如果您想为定义一个不同的绑定tab
,就可以做到这一点(在Elisp中,不是交互式的,因为按键阅读提示会应用function-key-map
翻译,所以您最终会重新绑定TAB
而不是tab
):
(global-set-key [tab] '…)
(define-key some-mode-map [tab] '…)
所有修改Tab按键动作的标准模式都通过修改TAB
按键来完成,按键是C-i
按键组合Ctrl+ 生成的字符的昵称I。如果您希望将标准绑定应用于tab
而不是C-i
,则不要使用键function-key-map
模式和模式,而是将Ctrl+ 重定向I到其他键。
(define-key input-decode-map [(control ?i)] [control-i])
(define-key input-decode-map [(control ?I)] [(shift control-i)])
(define-key some-mode-map [control-i] '…)
现在Emacs将报告Ctrl+ I为“ <control-i>
(翻译自TAB
)”。这不是很漂亮,但这是不可避免的:TAB
Emacs源代码中内置的字符9的漂亮字体。
端子架
在终端机架中,问题更加棘手,通常是不可能的。终端不传输密钥,而是传输字符(更确切地说,实际上,它们传输字节)。的Tab是控制+ I,相同什么组合键-键作为制表符发送Ctrl+ I生成。没有对应字符的功能键(例如光标键)作为转义序列传输,即以ESC
= Control + [ 开头的字符序列(这就是Emacs定义escape为前缀键的原因- ESC
必须为前缀)。请参阅键盘输入和文本输出如何工作?以获得更多背景。
有几个可以配置为发送功能键的不同按键序列的终端,但不是很多。无论LeoNerd的libtermkey / libtickit和托马斯Dickey的xterm(因为216的版本)支持此功能。在Xterm中,该功能是可选的,可以通过modifyOtherKeys
资源激活。但是,除了支持xterm的xterm之外,我不了解任何流行的终端仿真器,尤其是许多基于libvte构建的仿真器。一些终端仿真器允许您通过用户定义的键和弦到转义序列的对应关系来手动执行此操作。
这种机制允许区分许多键组合,而不仅仅是制表符/ Ci,返回键/ Cm和转义键/ C- [。有关更多详细说明,请参见使用终端时的键绑定问题。
从Emacs 24.4开始支持基本的xterm功能。然而基本面(尤其是Tab,Return,Escape,Backspace)还是发送了传统的控制字符,因为这是应用程序的期望。有一种模式,其中Ctrl+ letter发送一个转义序列而不是控制字符。因此,要将功能键与CtrlEmacs 24.4上的组合区分开来,可以modifyOtherKeys
通过将资源设置为2而不是1来修改其对使用此模式的支持。
;; xterm with the resource ?.VT100.modifyOtherKeys: 2
;; GNU Emacs >=24.4 sets xterm in this mode and define
;; some of the escape sequences but not all of them.
(defun character-apply-modifiers (c &rest modifiers)
"Apply modifiers to the character C.
MODIFIERS must be a list of symbols amongst (meta control shift).
Return an event vector."
(if (memq 'control modifiers) (setq c (if (or (and (<= ?@ c) (<= c ?_))
(and (<= ?a c) (<= c ?z)))
(logand c ?\x1f)
(logior (lsh 1 26) c))))
(if (memq 'meta modifiers) (setq c (logior (lsh 1 27) c)))
(if (memq 'shift modifiers) (setq c (logior (lsh 1 25) c)))
(vector c))
(defun my-eval-after-load-xterm ()
(when (and (boundp 'xterm-extra-capabilities) (boundp 'xterm-function-map))
;; Override the standard definition to set modifyOtherKeys to 2 instead of 1
(defun xterm-turn-on-modify-other-keys ()
"Turn the modifyOtherKeys feature of xterm back on."
(let ((terminal (frame-terminal)))
(when (and (terminal-live-p terminal)
(memq terminal xterm-modify-other-keys-terminal-list))
(send-string-to-terminal "\e[>4;2m" terminal))))
(let ((c 32))
(while (<= c 126)
(mapc (lambda (x)
(define-key xterm-function-map (format (car x) c)
(apply 'character-apply-modifiers c (cdr x))))
'(;; with ?.VT100.formatOtherKeys: 0
("\e\[27;3;%d~" meta)
("\e\[27;5;%d~" control)
("\e\[27;6;%d~" control shift)
("\e\[27;7;%d~" control meta)
("\e\[27;8;%d~" control meta shift)
;; with ?.VT100.formatOtherKeys: 1
("\e\[%d;3~" meta)
("\e\[%d;5~" control)
("\e\[%d;6~" control shift)
("\e\[%d;7~" control meta)
("\e\[%d;8~" control meta shift)))
(setq c (1+ c)))))
(define-key xterm-function-map "")
t)
(eval-after-load "xterm" '(my-eval-after-load-xterm))