Резервная привязка ключей Emacs

У меня есть второстепенный режим. Если этот режим активен и пользователь нажимает DEL, я хочу выполнить какое-то действие, но только если выполняется какое-то условие. Если условие выполнено и действие выполнено, после этого я больше ничего не хочу делать. Но если условие не выполняется, я не хочу ничего делать и разрешить выполнение действия DEL по умолчанию.

Не уверен, как я мог решить это. Но, думаю, я мог бы сделать это двумя способами:

1) Я мог бы привязать клавишу DEL к функции в вспомогательном режиме, а затем проверить, выполняются ли условия. Но тогда как мне узнать, что команда по умолчанию для DEL?

2) Я мог бы добавить предварительный командный хук, как это. Выполните команду и затем разорвите цепочку. Но как мне разорвать цепь?

(add-hook 'pre-command-hook
          (lambda()
            (when (equal last-input-event 'backspace)
              ;; Do something and then stop (do not execute the
              ;; command that backspace is bound to)
              )))

Как бы вы решили это? Спасибо!

3 ответа

Решение

Способ сделать это - временно отключить ваш второстепенный режим, а затем посмотреть привязку клавиш.

Притворись, что ты связан 'do-thingy в DEL. Тогда это поможет (если условие, которое вы хотите вызвать, это (equal last-input-event 'backspace):

(defun do-thingy ()
  "Do something, unless last event was backspace."
  (interactive)
  (if (equal last-input-event 'backspace)
      (let* ((my-minor-mode nil)
             (original-func (key-binding (kbd "DEL"))))
        ;; original-func is whatever DEL would be if
        ;; my-minor-mode were disabled
        (call-interactively original-func))
    (message "Here's my minor mode behavior!")))

Примечание. В этом случае предполагается, что вы установили привязки клавиш стандартным образом, как в младшем режиме. В частности, вы должны добавить свою таблицу ключей в переменную minor-mode-map-alist добавив элемент (my-minor-mode . my-minor-mode-keymap), Вот как выше let Оператор работает, он ищет нужную привязку с временно отключенным режимом.

Если вы используете define-minor-mode чтобы определить ваш второстепенный режим, раскладка клавиатуры автоматически настраивается на "правильный путь".

Это то, что я использую для моего smart-tab пакет, который делает именно это.

(defun smart-tab-default ()
  "Indents region if mark is active, or current line otherwise."
  (interactive)
  (if mark-active
      (indent-region (region-beginning)
                     (region-end))

    (call-interactively
     (or
      ;; Minor mode maps for tab (without smart-tab-mode)
      (cdar (assq-delete-all 'smart-tab-mode (minor-mode-key-binding "\t")))
      (cdar (assq-delete-all 'smart-tab-mode (minor-mode-key-binding [(tab)])))
      (local-key-binding "\t")
      (local-key-binding [(tab)])
      (global-key-binding "\t")
      (global-key-binding [(tab)])))))

И в команде smart-tab (который привязывается к вкладке в второстепенном режиме), имеет следующее:

(if (smart-tab-must-expand prefix)
    ;; use smart tab
  (smart-tab-default))

Сначала проверяется наличие каких-либо незначительных привязок режима для вкладки (не включаяsmart-tab-mode), затем локальные и, наконец, глобальные сочетания клавиш.

Кажется, нет способа сделать то, что вы хотите, надежно. Если ваша новая команда привязана к DEL, то того, что раньше было привязано к DEL в текущей раскладке, больше не существует. Другой предложенный вами подход не сработает, потому что предварительные командные хуки не мешают выполнению следующих действий. Вы можете также подумать о том, чтобы прервать дальнейшее выполнение с помощью ^G (Keyboard-Quit), но это неконтролируемое прерывание, которое может остановить больше вещей, чем вы хотите.

Даже если вы сделаете процесс настройки нового связывания немного более сложным, чем просто перепривязка, и вспомните, что было там связано раньше, так что вы можете назвать его потом, у вас действительно не будет того, что вы ищете. Если кто-то хочет перепривязать действие "по умолчанию", он должен сделать это, изменив свою функцию вместо замены привязки клавиш.

То, что вы хотите сделать, не соответствует модели Emacs о том, как работает связывание ключей.

Другие вопросы по тегам