Если бы вы хотели такое поведение во всем Emacs, было бы тривиально добиться этого с помощью key-translation-map
, карты ключей , предоставленной специально для этой цели. Желание использовать его только в определенных основных режимах несколько усложняет ситуацию. Наилучший способ, который я нашел до сих пор, - это определить второстепенный режим, который выполняет перевод в соответствии с заданной таблицей ключей, а затем добавить хук для активации этого второстепенного режима вместе с каждым основным режимом, к которому вы хотите его применить. ,
Вот определение второстепенного режима. Перетащите это в файл swap-braces.el
где - нибудь в вашем пути загрузки.
;;; swap-braces.el - a minor mode to swap square and curly braces
;;; Installation:
;; Drop it in your load path and (require 'swap-braces).
;; Possibly also (add-hook 'foo-mode-hook 'swap-braces-mode).
;;; Commentary:
;; The swap function explicitly instructs Linum to schedule an update,
;; if Linum mode is enabled; otherwise, Linum does not automatically
;; update while Swap-Braces mode is enabled.
;; This seems like it should not be necessary, and I'm uncertain whether
;; it has greater implications regarding interaction between this mode
;; and others.
;; (That is, it makes me worry that something about how I've implemented
;; this makes it screw up other modes using post-command-hook. Caveat user!)
;;; Author
;; Aaron Miller (me@aaron-miller.me)
(setq swap-braces-map (make-sparse-keymap))
(define-key swap-braces-map (kbd "{") "[")
(define-key swap-braces-map (kbd "}") "]")
(define-key swap-braces-map (kbd "[") "{")
(define-key swap-braces-map (kbd "]") "}")
(define-minor-mode swap-braces-mode
"When active, swap square braces and curly braces, so that e.g. pressing [
elicits '{', and S-[ elicits '['.
The keymap `swap-braces-map' defines this mode's behavior. It is strongly
recommended that you do not define keys in this map which are not self-
inserting characters; the resulting behavior is indeterminate, but almost
certainly not what you intended."
:init-value nil
:lighter " [{"
(if swap-braces-mode
(add-hook 'post-command-hook
'swap-braces-mode-swap)
(remove-hook 'post-command-hook
'swap-braces-mode-swap)))
(defun swap-braces-mode-swap ()
;; this worries me
(if (and (boundp 'linum-mode)
(not (eq nil linum-mode)))
(linum-schedule))
(when (and (eq (char-before) last-command-event)
(not (window-minibuffer-p (selected-window))))
(let* ((translation (lookup-key swap-braces-map (string (char-before)))))
(if (stringp translation)
(progn
(backward-delete-char 1)
(insert translation))))))
(provide 'swap-braces)
Это не идеально; обратите внимание на предостережения относительно режима linum и то, что это странное неправильное поведение может указывать на эффекты этого режима для других, которые используют post-command-hook. Я использую несколько таких режимов, и не видел никаких проблем (кроме linum, не обновляющихся) во время тестирования, но ваш пробег может отличаться, так что будьте внимательны. (Как ни странно, использование post-self-insert-hook вместо этого не имело никакого значения; я остановился на post-command-hook, потому что post-self-insert-hook, очевидно, является новым в Emacs 24 и не предлагает никакой разницы в поведении Стоит отказаться от обратной совместимости.)
Затем, где-то в вашем коде инициализации, (require 'swap-braces)
; отныне вы можете активировать режим обмена с помощью M-x swap-braces-mode
.
Наконец, чтобы активировать второстепенный режим вместе с основным режимом, добавьте его в хук загрузки основного режима. Если основной режим, который вы используете, называется «foo-mode», то вы добавите следующее в код инициализации:
(add-hook 'foo-mode-hook 'swap-braces-mode)
Настроить по вкусу; в вашем случае, он, вероятно, будет называться latex-mode-hook
, но проверьте документацию режима, чтобы убедиться в этом.
Отредактировано 2013-10-09 для применения перевода только тогда, когда выбранное окно не является минибуфером; см комментарии