Изменения связывания ключей в Emacs между Emacs 23 и Emacs 24
Я недавно обновился до Emacs24, и в результате этого несколько моих пользовательских комбинаций клавиш перестали работать.
В соответствии с прекрасным руководством, можно заставить Emacs перестать совмещать функциональные клавиши с их управляющими кодами ASCII (например, возможно иметь C-m
а также RET
связаны с разными вещами, или C-i
а также TAB
, и так далее). Это всегда было моей любимой мозолью с Emacs, так что такие ценные сочетания клавиш "первого уровня" тратятся впустую на вещи, для которых у меня уже есть специальные клавиши на моей клавиатуре. В моем случае я хочу связать их с разными вещами, чтобы "модернизировать" сочетания клавиш, подражая gedit. В Emacs23 это работало прекрасно:
(global-set-key (kbd "C-i") 'goto-line)
(global-set-key (kbd "C-m") 'comment-or-uncomment-region)
(global-set-key (kbd "C-d") 'kill-whole-line)
;; Fix some stuff broken by the above
(global-set-key [delete] 'delete-char)
(global-set-key (kbd "TAB") 'indent-for-tab-command)
(global-set-key (kbd "RET") 'newline)
Затем я обновился до Emacs24, и он сломался. Это все еще "работает" в том смысле, что C-m
безусловно, делает одну вещь, и RET
делает другое, но проблема в том, что клавиша возврата больше не работает должным образом в режиме терминала или в минибуфере. Вместо того, чтобы активировать только что набранную команду, в обоих случаях клавиша возврата просто перемещает курсор вниз на следующую строку, и у меня нет возможности активировать вводимые мной команды в минибуфере или терминале.
По иронии судьбы, Emacs24 внес много изменений в поведение удаления, и в процессе они отделены C-d
от DEL
так что на самом деле теперь безопасно связывать C-d
к чему-то без необходимости связывать DEL
вернемся к ожидаемому поведению, поэтому было бы здорово, если бы я мог добиться аналогичного поведения "это просто работает" для моего ключа возврата, в то время как C-m
связан с чем-то еще.
Итак, я могу представить два возможных решения этой проблемы. Кто-то может выглядеть так:
(global-set-key (kbd "C-m") 'comment-or-uncomment-region)
(global-set-key (kbd "RET") 'do-what-i-expect-the-return-key-to-do-in-any-mode)
ИЛИ, что-то вроде этого было бы еще лучше:
(setq decouple-ascii-control-codes-from-function-keys t)
Но я не знаю ни одной такой переменной или функции, которая бы помогла мне в этом сценарии.
Я предпринял несколько неудачных попыток использования ловушек режимов для восстановления правильных привязок в терминальном и минибуферном режимах, но я просто не могу заставить что-либо работать. Помогите!
Благодарю.
2 ответа
По умолчанию эти "родственные ключи" обрабатываются в Emacs для перенаправления (через function-key-map) специальных клавиш (например, tab
, а также return
) к их эквиваленту ASCII, а затем добавьте только привязки клавиш к версии ASCII. Таким образом, вы можете легко добавить новые значения в версию без ASCII с помощью чего-то вроде
(global-set-key [return] 'my-new-command)
но в вашем случае вы хотите сделать наоборот, чтобы return
вести себя как раньше при изменении C-m
, Самый надежный способ сделать это (надежный в том смысле, что он должен работать с большинством основных / второстепенных режимов) - это переназначить C-m
рано и безоговорочно к какому-то новому событию, как в:
(define-key input-decode-map [?\C-m] [C-m])
(define-key input-decode-map [?\C-i] [C-i])
это не повлияет на обработку return
а также tab
поскольку input-decode-map
применяется раньше function-key-map
, т.е. до того, как эти ключи превращаются в управляющие клавиши ASCII. Таким образом, вы можете сделать:
(global-set-key [C-m] 'my-new-command)
(global-set-key [C-i] 'my-newer-command)
Недостатком является то, что это относится не только к привязкам для C-i
но и привязки для C-c C-i
который теперь будет работать только как C-c TAB
(что иногда будет просто хорошо, но иногда может быть менее мнемоническим).
Еще одним недостатком является то, что если есть обязательство для tab
, затем tab
не будет полезным для достижения C-i
связывание. Но мы можем исправить эти две проблемы, добавив следующее:
(define-key function-key-map [C-i] [?\C-i])
(define-key function-key-map [C-m] [?\C-m])
который превратит новый C-i
событие возвращается в нормальное русло C-i
в случае, когда нет привязки, которая использует новое событие.
Это похоже на работу:
(add-hook 'find-file-hook
(lambda ()
(local-set-key (kbd "C-m") 'comment-or-uncomment-region)
(local-set-key (kbd "<return>") 'newline-and-indent)))
Идея здесь в том, что вместо того, чтобы возиться с ключом возврата глобально (что и разрушает буферы терминала и минибуфера), мы устанавливаем эти привязки клавиш только для каждого буфера, за исключением того, что мы делаем это безоговорочно для всех буферов, которые представляют файлы на диск.
Это немного неэффективно, запускаться каждый раз, когда я открываю файл, но это приятно, поскольку мне не нужно думать о каждом возможном режиме, чтобы "исправить", он просто не нарушает режимы терминала / минибуфера / и т.д. в первое место.