Problemy ze skrótami klawiszowymi podczas korzystania z terminala


30

Mam następujący wiersz init.el:

(global-set-key [(control \;)] 'comment-region)

Działa bardzo dobrze w oknie GUI, ale jeśli emacszostanie wywołane z tą -nwopcją C-;, nie komentuje regionu, tylko wstawia ;znak. M-x comment-region RETdziała jednak dobrze.

Próbowałem postępować zgodnie z tą odpowiedzią na podobny problem, ale C-q C-;po prostu powraca ;i oczywiście nie chcę się wiązać ;.

Jak osiągnąć pożądany efekt?


4
Możliwe, że twój terminal (przy okazji, czego używasz?) Nie rozpoznaje tej sekwencji poleceń. Spróbuj użyć C-;kombinacji, a następnie użyj, M-x view-lossageaby sprawdzić, czy w ogóle dociera do Emacsa.
Dan

Używam gnome-terminali M-x view-lossagezwraca:ESC [ > 1 ; 2 8 0 2 ; 0 c ; ESC x v i e w - l o s s a g e RET
WeSenseASoulInSearchOfAnswers

3
Wygląda na problem końcowy: gdyby ta kombinacja klawiszy dotarła do Emacsa, wyglądałaby C-;raczej niż c ;(a przynajmniej dostaję C-;).
Dan

@ Dan: Czy możesz podać to jako odpowiedź? Oznaczałoby to pytanie jako udzielone i ułatwia znalezienie rozwiązania, które jest dobre dla innych osób mających ten sam problem. Dzięki!
Tikhon Jelvis,

Podsumowane i opublikowane z dodatkowym linkiem, aby uzyskać więcej informacji. Również edytuj tytuł pytania, aby był nieco bardziej ogólny.
Dan

Odpowiedzi:


17

Po pierwsze, bardziej ogólny problem: emulatory terminali są często ograniczone w sekwencjach kontrolnych i sekwencjach ucieczki, które mogą wysłać. Tak więc: może się zdarzyć, że terminal połknie twoje znaki specjalne, zanim dotrą do Emacsa. Jako ogólną diagnostykę możesz nacisnąć C-h l(lub M-x view-lossage), aby sprawdzić, czy twoje kombinacje klawiszy przekształcają się w Emacsa.

Aby uzyskać więcej informacji na ten temat, zapoznaj się z tym wątkiem Przepełnienie stosu i znajdującymi się tam linkami.

Podsumowując komentarze w przód i w tył, twój konkretny problem sugeruje, że problemem jest terminal, a nie Emacs. Kiedy próbujesz, C-;a potem M-x view-lossagemasz blah blah blah c ; ESC v i e w - l o s s a g e RET. To wygląda na problem końcowy: gdyby kombinacja klawiszy dotarła do Emacsa, c ;część wyglądałaby tak C-;.


33

W Shift + Up nie jest rozpoznawany przez Emacsa w terminalu Wyjaśniam, jak terminale tłumaczą większość klawiszy funkcyjnych na sekwencje specjalne, ponieważ interfejs między aplikacjami a terminalami przesyła znaki (a raczej bajty), a nie klucze. Tylko kilka kombinacji modyfikatora + postaci ma swój własny charakter:

  • Ctrlplus litera lub jeden z @[\]^_zamienia się w bajty 0–31 (znaki sterujące ASCII ).
  • Często Ctrl+ ?zamienia się w bajt 127, a Ctrl+ Spaceodpowiada Ctrl+ @(bajt 0).
  • Niektóre klawisze funkcyjne są równoważne ze znakami kontrolnymi: Tab= Ctrl+ I, Return= Ctrl+ M, Esc= Ctrl+ [.
  • I Backspace= Ctrl+ Hlub Ctrl+ w ?zależności od konfiguracji. Ctrl+ ?jest wygodniejszy dla Emacsa, ponieważ Ctrl+ Hto pomoc.
  • Meta+ characterjest wysyłany zgodnie z Escnastępującym po nim znakiem .

A co z innymi kombinacjami, takimi jak Ctrl+ ;lub Ctrl+ Shift+ letter? Ponieważ nie ma odpowiedniego znaku, terminal musi albo ponownie użyć znaku, albo wysłać sekwencję zmiany znaczenia. Wiele terminali ignoruje modyfikatory, gdy nie ma odpowiedniego znaku, więc kończy się na Ctrl+ ;wysyłaniu ;, Ctrl+ Shift+ letterrównoważnym Ctrl+ letteritp.

Dostawcy terminali przez długi czas robili tę prostą rzecz. Nie było standardu dla sekwencji ucieczki, który byłby samonapędzający się - dostawcy terminali go nie implementują, aplikacje nie obsługują go, użytkownicy tego nie oczekują. Niektóre emulatory terminali można skonfigurować tak, aby wysyłały dowolne sekwencje specjalne, więc jeśli możesz, możesz je skonfigurować i zadeklarować sekwencje specjalne Emacsowi (więcej na ten temat później).

Ostatnio sytuacja się zmienia, ponieważ pojawiły się dwie propozycje standaryzacji sekwencji ucieczki. Jednym z nich jest libtermkey LeoNerda ze składnią . Kolejnym jest xterm Thomasa Dickeya ze składnią . Obecne wersje xterm (≥216) można skonfigurować dla dowolnej składni przez ustawienie zasobu; funkcja musi zostać aktywowana poprzez ustawienie wartości niezerowej.ESC [ codepoint ; modifier uESC [ 2 7 ; modifier ; codepoint ~formatOtherKeysmodifyOtherKeys

Jeśli emulator terminala nie obsługuje tych składni, ale można go skonfigurować, wybierz jedno z nich.

Od Emacsa 24.4 Emacs automatycznie włącza tę modifyOtherKeysfunkcję, gdy wykryje, że terminal jest w wersji xterm ≥216. Wykrywanie przez Emacsa sekwencji ucieczki do kodowania kluczy działa poprzez zmienną local-function-key-map. Począwszy od Emacsa 24.4, nie wszystkie sekwencje specjalne są obsługiwane. Możesz użyć następującego kodu w pliku init, aby ukończyć zadanie.

;; xterm with the resource ?.VT100.modifyOtherKeys: 1
;; 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))
    (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;3u" meta)
                ("\e\[%d;5u" control)
                ("\e\[%d;6u" control shift)
                ("\e\[%d;7u" control meta)
                ("\e\[%d;8u" control meta shift)))
        (setq c (1+ c))))))
(eval-after-load "xterm" '(my-eval-after-load-xterm))

Jeśli TERMzmienna środowiskowa nie jest ustawiona na xtermlub wariant taki jak xterm-256color, Emacs nie aktywuje tych sekwencji. Jeśli Emacs ma już wsparcie dla twojej wartości TERM, możesz dodać wsparcie definiując funkcję podobną do powyższej, która ma być wykonywana po załadowaniu pliku Lisp, którego nazwa jest wartościąTERM . Jeśli Emacs nie ma takiego wsparcia, możesz go dodać, tworząc podkatalog wywoływany termgdzieś w twoim load-path, i tworząc plik Lisp o nazwie term/$TERM.elgdzie $TERMjest wartość TERM, definiując wywoływaną funkcję terminal-init-$TERM.

Jak piszę, wydaje się, że niewiele emulatorów terminali innych niż xterm przyjęło te sekwencje specjalne. W OSX można skonfigurować iTerm2 , wybierając sekwencję zmiany znaczenia dla każdej kombinacji klawiszy, jeden po drugim.


2
Twoje odpowiedzi na ten temat są zawsze wspaniałe, Gilles. Bardzo mile widziane.
phils,

Świetny!. Chociaż trudno mi znaleźć sposób, aby urxvt wysyłał te sekwencje. Czy mógłbyś mi pomóc :)
Amos

@Amos Nie używam rxvt. Powinieneś zapytać na Unixie i Linuksie, jak zmusić urxvt do wysyłania tych samych sekwencji specjalnych, co xterm za pomocą editOtherKeys.
Gilles 'SO - przestań być zły'

nie działa na macOS xterm-256color. M-C-%być rozpoznanymESC 5
LoranceChen

@LoranceChen To oczekiwane zachowanie, jeśli modifyOtherKeysfunkcja nie jest aktywna. Pamiętaj, że jest obsługiwany tylko w wystarczających wersjach xterm i jest aktywowany automatycznie od Emacsa 24.4. Nie wiem, czy OSX jest dostarczany z najnowszymi wersjami. Jeśli to nie działa i nie działa dla ciebie, proponuję zadać nowe pytanie. Wymień używane wersje.
Gilles „SO- przestań być zły”,

2

Odpowiedź Gillesa brzmiała: On OSX, you can configure iTerm2 by selecting an escape sequence for each key combination, one by one. Miałem trochę problemów z dotarciem, więc tutaj szczegółowe wyjaśnienie na wypadek, gdybyś był taki jak ja, zdezorientowany.

Jeśli podczas uruchamiania Emacsa w terminalu (np. Domyślnym Terminal.app dla Maca) C-x C-;nie działa comment-linei chcesz tę funkcjonalność, musisz przełączyć się na iTerm2 (Terminal.app nie ma takiej możliwości) i utworzyć mapowanie klawiszy w obszarze Profile ... Następujące klucze :

^;     ^[[59;5u

Dokonuje się tego poprzez kliknięcie +przycisku, który wyświetla małe okno o nazwie „Skrót klawiaturowy”; to okno ma początkowo dwa pola; góra ma wartość „Kliknij, aby ustawić”, a dół ma wartość „Ignoruj”. Kliknij górny przycisk i wpisz C-;. Ustawia to kombinację klawiszy, która uruchomi akcję i kod. Kliknij dolne pole „Akcja”, a następnie znajdź i kliknij „Wyślij sekwencję ucieczki”, która znajduje się nieco ponad połowę. Po kliknięciu pojawi się trzecie pole o nazwie „Esc +”. W tym polu wpisz:

[59;5u

Jest 59to dziesiętny kod ASCII przecinka i 5jest to kod dla Ctrl. Następnie naciśnij „OK”, aby zakończyć. Prawidłowa kombinacja klawiszy do sekwencji klawiszy będzie teraz uwzględniona w preferencjach iTerm2. Po uruchomieniu Emacsa w iTerm będziesz mieć dostęp do C-x C-;funkcjonalności.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.