Проблемы с сочетаниями клавиш при использовании терминала

30

У меня есть следующая строка в init.el:

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

Это работает очень хорошо в окне GUI, но если emacsвызывается с -nwпараметром, то C-;не комментирует регион, только вставляет ;символ. M-x comment-region RETработает отлично однако.

Я попытался следовать этому ответу на похожую проблему, но C-q C-;возвращается просто, ;и я, очевидно, не хочу связываться голым ;.

Как добиться желаемого эффекта?

WeSenseASoulInSearchOfAnswers
источник
4
Возможно, ваш терминал (что вы используете, кстати?) Не распознает эту последовательность команд. Попробуйте использовать C-;комбо, а затем использовать, M-x view-lossageчтобы увидеть, если это даже добраться до Emacs.
Дан
Я использую gnome-terminalи M-x view-lossageвозвращаю:ESC [ > 1 ; 2 8 0 2 ; 0 c ; ESC x v i e w - l o s s a g e RET
WeSenseASoulInSearchOfAnswers
3
Похоже на терминальную проблему: если бы эта комбинация клавиш достигла Emacs, она бы выглядела C-;скорее, чем c ;(или, по крайней мере, я понял C-;).
Дан
@Dan: Не могли бы вы представить это в качестве ответа? Это пометит вопрос как ответ и облегчит поиск решения, что хорошо для других людей, имеющих такую ​​же проблему. Благодарность!
Тихон Джелвис
Обобщены и размещены с дополнительной ссылкой для дополнительного чтения. Также редактируйте заголовок вопроса, чтобы сделать его более общим.
Дан

Ответы:

17

Во-первых, более общая проблема: эмуляторы терминала часто ограничены в управляющих и управляющих последовательностях, которые они могут отправлять. Итак: может случиться так, что терминал проглотит ваши специальные символы, прежде чем они достигнут Emacs. В качестве общей диагностики вы можете нажать C-h l(или M-x view-lossage), чтобы увидеть, превращаются ли ваши комбинации клавиш в Emacs.

Для более подробного обсуждения этой проблемы просмотрите этот поток переполнения стека и ссылки в нем.

Подводя итоги в комментариях, ваша конкретная проблема предполагает, что проблема заключается не в Emacs, а в терминале. Когда вы пытались, C-;а потом M-x view-lossage, вы получили blah blah blah c ; ESC v i e w - l o s s a g e RET. Это похоже на проблему терминала: если бы комбинация клавиш доходила до Emacs, эта c ;часть была бы похожа C-;.

Дэн
источник
33

В Shift + Up не распознается Emacs в терминале. Я объясняю, как терминалы переводят большинство функциональных клавиш в escape-последовательности, потому что интерфейс между приложениями и терминалами передает символы (или, скорее, байты), а не ключи. Только несколько комбинаций модификатор + символ имеют свой собственный характер:

  • Ctrlплюс буква или один из них @[\]^_превращаются в байты 0–31 ( управляющие символы ASCII ).
  • Часто Ctrl+ ?превращается в байт 127, а Ctrl+ Spaceэквивалентен Ctrl+ @(байт 0).
  • Некоторые функциональные клавиши эквивалентны управляющим символам: Tab= Ctrl+ I, Return= Ctrl+ M, Esc= Ctrl+ [.
  • И Backspace= Ctrl+ Hили Ctrl+ в ?зависимости от конфигурации. Ctrl+ ?удобнее для Emacs, так как Ctrl+ Hэто помощь.
  • Meta+ characterотправляется Escпосле символа .

Так что насчет других комбинаций, таких как Ctrl+ ;или Ctrl+ Shift+ letter? Поскольку соответствующего символа нет, терминал должен либо повторно использовать символ, либо отправить escape-последовательность. Многие терминалы игнорируют модификаторы, когда нет соответствующего символа, поэтому вы в конечном итоге Ctrl+ ;отправка ;, Ctrl+ Shift+ letterэквивалент Ctrl+ letterи т. Д.

Поставщики терминалов долгое время занимались этим простым делом. Не было никакого стандарта для escape-последовательностей, который был самосохраняющимся - поставщики терминалов не реализуют его, приложения не поддерживают его, пользователи не ожидают этого. Некоторые эмуляторы терминала могут быть сконфигурированы для отправки произвольных escape-последовательностей, так что если вы можете, вы можете настроить их и объявить escape-последовательности в Emacs (подробнее об этом позже).

В последнее время ситуация меняется, потому что было два предложения стандартизировать escape-последовательности. Одним из них является libtermkey от LeoNerd с синтаксисом . Другой - xterm Томаса Дики с синтаксисом . Текущие версии xterm (≥216) могут быть настроены для любого синтаксиса путем установки ресурса; функция должна быть активирована путем установки ненулевого значения.ESC [ codepoint ; modifier uESC [ 2 7 ; modifier ; codepoint ~formatOtherKeysmodifyOtherKeys

Если ваш эмулятор терминала не поддерживает эти синтаксисы, но может быть настроен, выберите либо.

Начиная с Emacs 24.4, Emacs автоматически включает эту modifyOtherKeysфункцию, когда обнаруживает, что терминал имеет версию xterm ≥216. Обнаружение Emacs escape-последовательностей для кодирования ключей работает через переменную local-function-key-map. Начиная с Emacs 24.4, поддерживаются не все escape-последовательности. Вы можете использовать следующий код в вашем файле инициализации, чтобы завершить работу.

;; 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))

Если TERMпеременная окружения не установлена xtermили такой вариант, как xterm-256color, Emacs не будет активировать эти последовательности. Если в Emacs уже есть поддержка вашего значения TERM, вы можете добавить поддержку, определив функцию, аналогичную приведенной выше, которая будет выполняться после загрузки файла Lisp, именем которого является значениеTERM . Если в Emacs такой поддержки нет, вы можете добавить ее, создав подкаталог, который вызывается где- termто в вашем load-pathфайле, и создав файл Lisp с именем term/$TERM.elгде $TERMэто значение TERM, определяя вызываемую функцию terminal-init-$TERM.

Когда я пишу, кажется, что немногие терминальные эмуляторы, кроме xterm, приняли эти escape-последовательности. В OSX вы можете настроить iTerm2 , выбирая escape-последовательность для каждой комбинации клавиш, одну за другой.

Жиль "ТАК - перестань быть злым"
источник
2
Твои ответы на эту тему всегда превосходны, Жиль. Очень признателен.
Филс
Большой!. Хотя мне довольно сложно найти способ заставить urxvt отправлять эти последовательности. Не могли бы вы мне помочь :)
Амос
@ Amos Я не использую rxvt. В Unix и Linux вы должны спросить, как заставить urxvt отправлять те же escape-последовательности, что и xterm, с modifyOtherKeys.
Жиль "ТАК - перестань быть злым"
не работает на macOS xterm-256color. M-C-%быть признаннымESC 5
LoranceChen
@LoranceChen Это ожидаемое поведение, если modifyOtherKeysфункция не активна. Обратите внимание, что он поддерживается только в достаточно последних версиях xterm и активируется только автоматически, начиная с Emacs 24.4. Я не знаю, поставляется ли OSX с последними версиями. Если это не так, и это не работает для вас, я предлагаю вам задать новый вопрос. Укажите версии, которые вы используете.
Жиль "ТАК - перестань быть злым"
2

В ответе Жиля говорилось: у On OSX, you can configure iTerm2 by selecting an escape sequence for each key combination, one by one. меня возникли небольшие проблемы, поэтому здесь подробное объяснение на случай, если вы похожи на меня, запутались.

Если при запуске Emacs в терминале (например, Terminal.app по умолчанию для Mac) C-x C-;не запускается comment-line, и вам нужна эта функциональность, вам необходимо переключиться на iTerm2 (Terminal.app не имеет возможности) и создать сопоставление клавиш. под профилями ... ключи, как следует:

^;     ^[[59;5u

Это достигается нажатием на +кнопку, которая вызывает небольшое окно под названием «Сочетание клавиш»; это окно изначально имеет два поля; верхняя часть имеет значение «Click to Set», а нижняя имеет значение «Ignore». Нажмите верхнюю кнопку и введите C-;. Это устанавливает комбинацию клавиш, которая будет запускать действие и код. Щелкните по нижнему полю «Действие», найдите и нажмите «Отправить последовательность побега», которая находится чуть ниже половины пути. После того, как вы нажмете на это, появится третье поле, которое называется «Esc +». Внутри этого поля введите:

[59;5u

59Десятичный ASCII - код запятой, в и 5является кодом Ctrl. Затем нажмите «ОК», чтобы закончить. Правильная комбинация клавиш для последовательности клавиш теперь будет включена в настройки iTerm2. Когда вы запустите Emacs в iTerm, вы получите доступ к C-x C-;функциональности.

сосновая шишка
источник