Сэм описал проблему, но для общего решения вам в основном нужно научить Emacs различать ESC, полученный в ответ на то, что вы нажмете клавишу «Escape» из ESC, полученного как часть «escape-последовательности», , Конечно, в целом это невозможно сделать, но на практике вы можете проверить время: если за ESC следует немного времени простоя, то это, вероятно, «клавиша эвакуации», и в противном случае это, вероятно, escape-последовательность ".
Этот прием используется в VI эмуляторов, таких как Viper или Зла:
(defvar viper-fast-keyseq-timeout 200)
(defun viper--tty-ESC-filter (map)
(if (and (equal (this-single-command-keys) [?\e])
(sit-for (/ viper-fast-keyseq-timeout 1000.0)))
[escape] map))
(defun viper--lookup-key (map key)
(catch 'found
(map-keymap (lambda (k b) (if (equal key k) (throw 'found b))) map)))
(defun viper-catch-tty-ESC()
"Setup key mappings of current terminal to turn a tty's ESC into `escape'."
(when (memq (terminal-live-p (frame-terminal)) '(t pc))
(let ((esc-binding (viper--lookup-key input-decode-map ?\e)))
(define-key input-decode-map
[?\e] `(menu-item "" ,esc-binding :filter viper--tty-ESC-filter)))))
Если вы звоните viper-catch-tty-ESC
, он будет настроить декодирование таким образом, что нажав клавишу побег теперь должен генерировать escape
событие (вместо ESC
события). Это автоматически будет отображаться на ESC
, если нет привязки для escape
, благодаря привязке в function-key-map
(это используется в режиме графического интерфейса, в котором ключ эвакуации действительно отправляет событие escape
).
Обратите внимание, что это не устранит вашу проблему: «ESC ESC up» по-прежнему будет вставлять «OA». Проблема в том, что на клавиатурный перевод Emacs по-прежнему будет отображаться «ESC ESC ESC O A» (первые два появятся в раунде, пройдя через escape
и обратно). Таким образом, чтобы окончательно решить эту проблему, вам дополнительно нужно удалить «ESC ESC ESC» связывание и заменить его с привязкой, который будет срабатывать только с новым escape
события:
(global-unset-key [?\e ?\e ?\e])
(global-set-key [?\e ?\e escape] 'keyboard-escape-quit)
Примечания: Это все сложное дело , Я хорошо знаком с соответствующим кодом, но мои первые две попытки при написании этого ответа не удались из-за некоторого взаимодействия, которого я не ожидал.
Стефан, спасибо вам пример. Но он переводит ESC ESC ESC, чтобы «ESC ESC ESC», а не «ESC ESC escape» или «escape escape escape». – Netsu
Здесь более общее и точное решение (из злого режима) https://gist.github.com/Pitometsu/f2f68d5e81862ceffb0d76d277376cf1 – Netsu