Кадри графічного інтерфейсу
У кадрах графічного інтерфейсу (будь то 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
)". Це не дуже, але це неминуче: симпатичний друк символу 9 як TAB
вбудований у вихідний код Emacs.
Термінальні рами
У термінальних кадрах проблема складніше і часто неможлива. Термінали не передають ключі, вони передають символи (точніше, насправді, вони передають байти). TabКлюч передається як символ табуляції - який Control + I, такий же , як то , що комбінація клавіш Ctrl+ Iгенерує. Функціональні клавіші, що не мають відповідного символу (наприклад, клавіші курсору), передаються у вигляді послідовностей відведення, тобто послідовності символів, що починаються з ESC
= Control + [(саме тому Emacs визначає escapeяк ключ префіксу - ESC
повинен бути префіксом). Див. Як працюють введення з клавіатури та вихід тексту? для отримання додаткової інформації.
Є кілька терміналів, які можна налаштувати для надсилання різних послідовностей клавіш для функціональних клавіш, але їх не багато. Як libtermkey / libtickit LeoNerd, так і xterm Томаса Дікі (починаючи з версії 216) це підтримують. У Xterm функція є необов'язковою та активується через modifyOtherKeys
ресурс. Однак я не знаю жодного популярного емулятора терміналу, окрім xterm, який підтримує це, зокрема багатьох емуляторів, побудованих на libvte . Деякі емулятори терміналів дозволяють вам це робити вручну за допомогою визначеної користувачем кореспонденції з клавіатур для виходу з послідовностей.
Цей механізм дозволяє виділити багато комбінацій клавіш, а не лише вкладку / Ci, return / Cm та escape / C- [. Детальніший опис див. Проблеми з прив'язкою клавіатури при використанні терміналу .
Основна функція xterm підтримується з Emacs 24.4. Однак основи (зокрема Tab, Return, Escape, Backspace) до сих пір відправити традиційні керуючі символи, тому що це те , що очікують додаток. Існує режим, коли Ctrl+ letterнадсилає послідовність евакуації замість символу управління. Отже, щоб відрізнити функціональні клавіші від Ctrlкомбінацій на Emacs 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))