Sie können die C-[Bindung auf Karten auf Benutzerebene nicht wirklich ändern , wie Sie es tun würden global-set-key
. Sie können es jedoch als Tastaturereignis ändern, bevor es diese Keymaps erreicht. Sie können zum Beispiel sagen:
(define-key input-decode-map
(kbd "C-[")
[control-bracketleft])
und dann [control-bracketleft]
in Ihren Keymaps verwenden. Ziemlich einfach, nicht wahr?
Director's Cut
Leider ist es nicht so einfach, und diese Lösung erfordert einige Anpassungen, die sehr schmerzhaft erscheinen. Du wurdest gewarnt. Aber lassen Sie uns zuerst sehen, warum Karten auf Benutzerebene die Frage nicht beantworten können. Im Folgenden verweise ich auf das Emacs Lisp-Handbuch für Emacs 26.1, wenn ich ohne weitere Genauigkeit "etwas sehen" sage.
C-[wird sehr früh als ASCII-Steuerzeichen interpretiert ESC
(siehe 21.7.1 - Tastaturereignisse ). Dieser Code wird als Präfix für längere Sequenzen an allen anderen Stellen verteilt. Dafür gibt es einen Grund: ESC
Ist eigentlich das Meta-Präfix (siehe meta-prefix-char
), und alle Bindungen, die M-etwas lesen
, werden in eine Sequenz übersetzt, die mit beginnt ESC
. Daher reicht es nicht aus, die globale Karte zu ändern: Sie müssen sie zuerst ändern meta-prefix-char
und dann in jeder verwendeten Karte ESC
neu zuordnen , bevor Sie sie sicher zuordnen können .meta-prefix-char
M-C-[
OK dann natürlich: lass uns verwenden input-decode-map
. Es gibt einige ähnliche Karten, die wir möglicherweise verwenden möchten (siehe Abschnitte 21.8.3 und 22.14), aber bleiben wir bei dieser. Und nun ... das funktioniert! Du bist fertig, nicht wahr?
Nein, die Geschichte endet hier nicht. Dies funktioniert ... solange Sie ein Fenstersystem verwenden. Wenn Sie aufgrund von Pech in einem Notfallzustand in der Linux-Konsole eingesperrt sind, stellen Sie fest, wie dramatisch die Situation geworden ist: Pfeiltasten Homeund natürlich M-Bindungen sind allesamt Müll. Warum? Denn wenn das Terminal sagt ESC
(was es bei der Eingabe tut C-[), bedeutet dies wirklich ESC
, dass eine Sequenz der gleichen Art gestartet wird, mit der Nicht-ASCII-Zeichen übertragen werden.
Wenn Sie die Katastrophe beobachten, können Sie es für sinnvoll halten, die oben genannte input-decode-map
Änderung so zu schützen , dass sie nur aktiviert wird, wenn ein Fenstersystem die Tastatur steuert:
(let ((frame (framep (selected-frame))))
(or (eq t frame)
(eq 'pc frame)
(define-key input-decode-map
(kbd "C-[")
[control-bracketleft])
)))
Die Terminals funktionieren dann wie früher.
Können wir uns jetzt mit C-[Terminals befassen ? Ja, das können wir sowohl auf der Linux-Konsole als auch auf den anderen Terminal-Emulatoren, mit denen ich spielen kann. Aber das macht die Geschichte ziemlich lang, da neue Charaktere die Szene betreten. Denn es sind nicht mehr nur Emacs: Das Terminal hat jetzt die zentrale Rolle.
Lassen Sie uns ein Ohr für das haben, was die Linux-Konsole zu sagen hat. Geben Sie C-vvor einer Taste ein, um sie deutlich zu hören. C-[ist ESC
; so ist es Esc. Der Aufwärtspfeil klingt wie ESC [ A
, solange es M-aist
ESC A
. Hmm ... Sieht so aus, als ob diese Meta-Key-Umwälzungen in Emacs nicht wahr sind? Wie auch immer.
Es sei denn , wir sind bereit , ein paar Tricks auf der Grundlage der Zeit zwischen den Zeichen Ereignissen verstrichene zu spielen (die übrigens nicht unterscheiden
Escvon C-[), es scheint , dass wir keine andere Wahl haben , aber die Konsole zu sagen , was wir tun , eigentlich nicht gemein ESC
wenn wir tippen C-[. Darüber hinaus scheint es ziemlich bald so zu sein, dass dies C-[nicht das einzige Problem mit Standard-Terminalcodes ist: Modifikatoren werden die übertragenen Informationen meistens gelöscht. Wir müssen das Terminal aus dem gleichen Grund anpassen, aus dem wir Emacs anpassen: Es wäre viel praktischer, wenn wir dies tun würden.
An dieser Stelle sollten Sie einen tiefen Blick in die Dokumentationsaugen Ihres Terminals werfen: Manpages loadkeys(1)
für die Linux-Konsole, für xterm
xterm(1)
im Abschnitt Benutzerdefinierte Tastenkombinationen und alles , was ich für andere Terminals nicht weiß . In KDE konsole
können Sie benutzerdefinierte Übersetzungen unter Einstellungen / Aktuelles Profil bearbeiten ... und
dann Tastatur definieren . Hier ist ein Auszug aus ~/.local/share/konsole/Test.keytab
dem letzten Dialog:
key [+Ctrl+AnyModifier : "\EO*["
Sobald Sie das Terminal senden haben ESC O 5 [
für
C-[(wie in der obigen Konfiguration) können Sie auf Emacs zurück. Natürlich bist du noch nicht fertig.
Um Emacs anzuweisen, welchen Dialekt ein bestimmtes Terminal verwendet, können Sie ihn anpassen input-decode-map
. Ja, dies ist zufällig genau das, was wir zu Beginn dieser Geschichte geändert haben, und dies ist
term/xterm.el
genau das, was berührt wird, wenn es um xterm geht. Ein guter Ort für die Anpassung ist tty-setup-hook
(siehe Abschnitt 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))
)
)))
Beachten Sie, dass dieser Hook nur ausgeführt wird, wenn Sie sich in einem Terminal befinden. Daher können Sie hier den Code für die Fenstersysteminitialisierung nicht einfügen. Hier ist die Übersetzungsfunktion für sich:
(defun map-my-term-codes (map)
(define-key map (kbd "M-O 5 [")
[control-bracketleft])
)
Und dann können Sie sich etwas ausruhen: Es ist das Ende der Reise. Wenn Sie sich nicht für Terminals interessieren, können Sie natürlich schnell den ganzen schmerzhaften Teil überspringen. Aber Sie werden zugeben, dass es auch ziemlich unvollständig ist.
Zwei abschließende Anmerkungen:
Ich entscheide mich ESC O 5 [
für Code C-[. Dies ist nur ein Beispiel: Ich werde nicht so tun, als wäre es eine gute Wahl. Nur der 5
Teil, das heißt C-, scheint einer etablierten Konvention zu gehorchen
Die Konfiguration der Linux-Konsole hinterlässt einen schlechten Geschmack: Es scheint nicht möglich zu sein, die Bindung ohne Verwendung eines vorhandenen Zwischensymbols durchzuführen, und diejenigen, die ich benötigen würde
, existieren nicht . Ich verwende Symbole im Bereich F21- F246wie in den meisten Internetbeispielen, aber es ist nicht sehr zufriedenstellend. Es ist in Ordnung für ein paar nicht verwandte Bindungen, aber es wird kein systematisches Schema dienen.
Bearbeiten
- Ich habe dies mit dem EscFall abgeschlossen - der seine eigene Persönlichkeit hat - in einem anderen Beitrag: So entfernen Sie Bindungen an den ESC-Präfixschlüssel
Hier ist ein Fragment einer Konfiguration, mit der gefüttert loadkeys
werden soll. Ich füge dies in /root/custom.kmap ein und lade es, wenn ich muss (was selten ist). Meine eigentliche Konfiguration ordnet auch Pfeile und verschiedene Kombinationen von Modifikatoren zu, aber es ist ziemlich lang, die Auswahl von Symbolen und Sequenzen ist fraglich und ich bin nicht sicher, ob die Tastencodes für meine Tastatur mit Ihren übereinstimmen. Lassen Sie es uns also auf dem richtigen Niveau halten: Dies ist nichts anderes als eine Illustration.
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["