Ramki GUI
W ramkach GUI (X11, Windows, OSX,…) Emacs odczytuje Tabklawisz jako tab
klawisz funkcyjny. Ponieważ jednak Tabklawisz terminali tradycyjnie wysyła znak ^I
( Control + I), Emacs tłumaczy tab
klawisz funkcyjny na znak Control + I (znak 9), który jest wyświetlany jako TAB
. Tłumaczenie odbywa się za pośrednictwem function-key-map
.
Podobne tłumaczenie dzieje się z niektórymi innymi klawiszami funkcyjnymi. ( Backspacei Deletesą drażliwą sprawą, której nie będę tutaj szczegółowo omawiać).
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+[
Jeśli chcesz całkowicie oddzielić Tabod Ctrl+ I, usuń powiązanie z function-key-map
:
(define-key function-key-map [tab] nil)
Nie jest to jednak bardzo przydatne, ponieważ wpisy w function-key-map
są zastępowane przez powiązania w mapach klawiszy specyficznych dla trybu lub na mapie globalnej. Więc jeśli chcesz zdefiniować inne wiązanie tab
, po prostu zrób to (w Elisp, nie interaktywnie, ponieważ monit o odczytanie klucza stosuje function-key-map
tłumaczenie, aby skończyć wiązanie, TAB
a nie tab
):
(global-set-key [tab] '…)
(define-key some-mode-map [tab] '…)
Wszystkie standardowe tryby, które modyfikują działanie Tabklawisza, robią to poprzez modyfikację TAB
klawisza, który jest pseudonimem dla C-i
znaku generowanego przez kombinację klawiszy Ctrl+ I. Jeśli chcesz zastosować standardowe powiązania tab
zamiast C-i
, pozostaw klawisze function-key-map
klawiszy trybu i pozostaw w spokoju, a zamiast tego przekieruj Ctrl+ Ido innego klucza.
(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] '…)
Teraz Emacs zgłosi Ctrl+ Ijako „ <control-i>
(przetłumaczone z TAB
)”. To nie jest ładne, ale jest nieuniknione: ładne drukowanie znaku 9, takiego jak TAB
wbudowany w kod źródłowy Emacsa.
Ramy terminali
W ramkach terminali problem jest trudniejszy i często niemożliwy. Terminale nie przesyłają kluczy, przesyłają znaki (a dokładniej, w rzeczywistości bajty). TabKlucz jest przekazywana jako znak - co jest zakładka Control + I, a tym samym, co kombinacja klawiszy Ctrl+ Igeneruje. Klawisze funkcyjne, które nie mają odpowiedniego znaku (takie jak klawisze kursora) są przesyłane jako sekwencje specjalne, tj. Sekwencje znaków rozpoczynające się od ESC
= Control + [(dlatego Emacs definiuje escapejako klawisz prefiksu - ESC
musi być prefiksem). Zobacz Jak działa wprowadzanie za pomocą klawiatury i tekst? po więcej tła.
Istnieje kilka terminali, które można skonfigurować do wysyłania różnych sekwencji klawiszy dla klawiszy funkcyjnych, ale nie wiele. Zarówno libtermkey / libtickit LeoNerda, jak i xterm Thomasa Dickeya (od wersji 216) obsługują to. W Xterm funkcja jest opcjonalna i aktywowana przez modifyOtherKeys
zasób. Jednak nie znam żadnego popularnego emulatora terminali innego niż xterm, który to obsługuje, w szczególności wielu emulatorów zbudowanych na libvte . Niektóre emulatory terminali pozwalają to zrobić ręcznie poprzez zdefiniowaną przez użytkownika korespondencję od słów kluczowych do sekwencji ucieczkowych.
Ten mechanizm pozwala na rozróżnienie wielu kombinacji klawiszy, nie tylko tab / Ci, return / Cm i escape / C- [. Aby uzyskać bardziej szczegółowy opis, zobacz Problemy ze skrótami klawiszowymi podczas korzystania z terminala .
Podstawowa funkcja xterm jest obsługiwana od Emacsa 24.4. Jednak podstawy (w szczególności Tab, Return, Escape, Backspace) nadal wysyłać tradycyjne znaki sterujące, bo to właśnie aplikacje spodziewać. Istnieje tryb, w którym Ctrl+ letterwysyła sekwencję zmiany znaczenia zamiast znaku sterującego. Aby odróżnić klawisze funkcyjne od Ctrlkombinacji w Emacsie 24.4, zmodyfikuj jego obsługę dla modifyOtherKeys
używania tego trybu, ustawiając zasób na 2 zamiast 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))