Nie można tak naprawdę zmienić C-[powiązania na mapach na poziomie użytkownika, tak jak zrobiłbyś to global-set-key
. Można go jednak zmienić jako zdarzenie na klawiaturze, zanim dotrze do tych map klawiszy. Możesz powiedzieć na przykład:
(define-key input-decode-map
(kbd "C-[")
[control-bracketleft])
a następnie użyj [control-bracketleft]
w swoich mapach klawiszy. Całkiem proste, prawda?
Wersja reżyserska
Niestety nie jest to takie proste, a to rozwiązanie wymaga pewnych korekt, które będą bardzo bolesne. Zostałeś ostrzeżony. Ale najpierw zobaczmy, dlaczego mapy na poziomie użytkownika nie mogą odpowiedzieć na pytanie. W dalszej części odsyłam do instrukcji Emacs Lisp dla emacsa 26.1, kiedy mówię „zobacz coś” bez większej precyzji.
C-[jest interpretowany na bardzo wczesnym etapie jako znak kontrolny ASCII ESC
(patrz 21.7.1 - Zdarzenia klawiatury ). Ten kod jest rozłożony na inne miejsca jako prefiks dla dłuższych sekwencji. Jest tego powód: w ESC
rzeczywistości jest to prefiks meta (patrz meta-prefix-char
), a wszystkie wiązania, które czytają
M-coś, zostaną przetłumaczone na sekwencję, która zaczyna się od ESC
. Dlatego zmiana mapy globalnej nie wystarczy: najpierw musisz zmienić meta-prefix-char
, a następnie zmienić mapowanie ESC
na nową meta-prefix-char
na każdej mapie, z której korzysta, M-zanim będzie można bezpiecznie mapować C-[.
OK, oczywiście: użyjmy input-decode-map
. Istnieje kilka podobnych map, których możemy ulec pokusie (patrz rozdziały 21.8.3 i 22.14), ale trzymajmy się tej. No cóż ... to działa! Skończyłeś, prawda?
Właściwie nie, historia nie kończy się tutaj. Działa to ... dopóki używasz systemu okiennego. Jeśli z powodu pecha zostałeś uwięziony w konsoli Linuksa w stanie wyjątkowym, zdajesz sobie sprawę, jak dramatyczna stała się sytuacja: klawisze strzałek Homei, oczywiście, M-powiązania są śmieciami. Dlaczego? Ponieważ kiedy terminal mówi ESC
(co robi podczas pisania C-[), naprawdę oznacza to ESC
i rozpoczyna sekwencję tego samego rodzaju, której używa do przesyłania znaków spoza ASCII.
Obserwując katastrofę, możesz uznać, że rozsądnie jest chronić powyższą input-decode-map
modyfikację w taki sposób, aby aktywowała się tylko w przypadku, gdy system okien kontroluje klawiaturę:
(let ((frame (framep (selected-frame))))
(or (eq t frame)
(eq 'pc frame)
(define-key input-decode-map
(kbd "C-[")
[control-bracketleft])
)))
Terminale działają wtedy tak, jak kiedyś.
Czy możemy sobie teraz poradzić C-[na terminalach? Właściwie tak, możemy, zarówno na konsoli Linux, jak i na innych emulatorach terminali, z którymi mogę grać. Ale to sprawia, że historia jest dość długa, ponieważ nowe postacie wkraczają na scenę. Ponieważ nie jest to już tylko emacs: terminal pełni teraz centralną rolę.
Przyjrzyjmy się, co ma do powiedzenia konsola Linux. Wpisz C-vprzed jakimś klawiszem, aby usłyszeć to wyraźnie. C-[jest ESC
; tak jest Esc. Strzałka w górę brzmi jak ESC [ A
, gdy M-ajest
ESC A
. Hmm ... Wygląda na to, że ten meta-kluczowy obieg w emacsie, prawda? Tak czy siak.
O ile nie jesteśmy gotowi zagrać w niektóre sztuczki w oparciu o czas, jaki upłynął między wydarzeniami postaci (które, nawiasem mówiąc, nie odróżniają się
Escod nich C-[), wydaje się, że nie mamy wyboru, jak tylko powiedzieć konsoli, co tak naprawdę nie mamy na myśli ESC
kiedy piszemy C-[. Co więcej, wkrótce wydaje się, że C-[nie jest to jedyny problem z zapasowymi kodami terminali: modyfikatory są w większości przypadków usuwane z przesyłanych informacji. Musimy dostosować terminal z tego samego powodu, dla którego dostosowujemy emacs: byłoby to o wiele bardziej praktyczne, gdybyśmy to zrobili.
W tym momencie odważysz się spojrzeć głęboko w dokumentację terminala: strony loadkeys(1)
podręcznika użytkownika dla konsoli Linux, xterm
xterm(1)
w sekcji Niestandardowe przypisania klawiszy i cokolwiek innego dla innych terminali. W KDE konsole
możesz zdefiniować niestandardowe tłumaczenia w Ustawieniach / Edytuj bieżący profil ...
a następnie Klawiatura . Oto fragment z ~/.local/share/konsole/Test.keytab
gry w tym ostatnim oknie dialogowym:
key [+Ctrl+AnyModifier : "\EO*["
Po wysłaniu terminala ESC O 5 [
do
C-[(jak w powyższej konfiguracji) możesz wrócić do emacsa. Oczywiście jeszcze nie skończyłeś.
Aby poinstruować emacsa, jakiego dialektu używa dany terminal, możesz dostosować input-decode-map
. Tak, to na szczęście ten, który zmodyfikowaliśmy na początku tej historii, i to jest ten, który
term/xterm.el
dotyka, gdy zaangażowany jest xterm. Dobrym miejscem do regulacji jest tty-setup-hook
(patrz punkt 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))
)
)))
Pamiętaj, że ten hak działa tylko wtedy, gdy jesteś w terminalu. Dlatego nie można wstawić tutaj kodu inicjującego system okien. Oto sama funkcja tłumaczenia:
(defun map-my-term-codes (map)
(define-key map (kbd "M-O 5 [")
[control-bracketleft])
)
A potem możesz odpocząć: to koniec podróży. Oczywiście, jeśli nie przejmujesz się terminalami, jest to szybkie, ponieważ pominiesz wszystkie bolesne części. Ale przyznasz, że jest również raczej niekompletny.
Dwie końcowe uwagi:
Wybieram ESC O 5 [
kod C-[. To tylko przykład: nie będę udawać, że to dobry wybór. Tylko ta 5
część, która oznacza C-, wydaje się przestrzegać jakiejś ustalonej konwencji
konfiguracja konsoli linux pozostawia zły gust: nie wydaje się możliwe wykonanie powiązania bez użycia pośredniego istniejącego symbolu, a te, których potrzebowałbym
, nie istnieją . Używam symboli z zakresu F21- F246jak w większości przykładów internetowych, ale nie jest to zbyt satysfakcjonujące. Jest OK dla kilku niepowiązanych powiązań, ale nie posłuży do systematycznego schematu.
Edytować
- Skończyłem to ze Escsprawą - która ma swoją osobowość - w innym poście: Jak usunąć powiązania z kluczem prefiksu ESC
tutaj jest fragment konfiguracji, którą można karmić loadkeys
. Umieszczam to w /root/custom.kmap i ładuję, kiedy trzeba (co jest rzadkie). Moja aktualna konfiguracja mapuje również strzałki i różne kombinacje modyfikatora, ale jest dość długa, wybór symboli i sekwencji jest wątpliwy i nie jestem pewien, czy kody klawiszy dla mojej klawiatury będą pasować do twojej. Trzymajmy to na właściwym poziomie: to tylko ilustracja.
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["
Poniższe rozwiązanie jest nieco nieprzyzwoite, ale wydaje się działać:
Niech
~/.xbindkeysrc
zawierają następujące elementy:Teraz
xbindkeys
będą tłumaczyć się C-[na C-<f13>i C-]na C-<f14>, aby mogli być swobodnie związani w emacs. Prawdopodobnie będziesz chciał powiązaćabort-recursive-edit
coś innego niż C-], na przykład C-S-g.Minusem jest to, że teraz C-[jest zepsuta w każdej aplikacji oprócz Emacsa, co można naprawić, dodając logikę do testowania, czy kombinacja klawiszy jest wysyłana do emacsa ...
źródło
C-]
.C-]
wiązanie przestało działać po tym, jak uruchomiłem Xbindkeys, więc też go odbiłem.