2010-03-22 2 views
9

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

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

1) Я мог бы привязать ключ DEL к функции в малом режиме, а затем проверки, если условия выполняется ВЗ нет. Но откуда узнать, какая команда DELETE для 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) 
      ))) 

В каком виде вы бы решили это? Благодаря!

+0

Являются ли del и backspace одинаковыми? – Amos

ответ

12

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

Притворись, что вы связали '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!"))) 

Примечания: Это поведение предполагает, что вы настроили ваш key bindingsstandard way a minor-mode would В частности, вы должны добавить раскладку к переменным minor-mode-map-alist. путь добавления элемента (my-minor-mode . my-minor-mode-keymap). Вот как работает над let заявление, он смотрит связывание вы хотите с режимом временно отключен.

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

+0

Отлично, спасибо! – rejeep

+2

Как насчет произвольного отступления, когда вы заранее не знаете, какой ключ является привязкой, к которой вы хотите вернуться? Как вы можете программным образом найти привязку для использования для значения функции original-func? (nevermind: похоже, что используется этот-command-keys-vector). –

-3

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

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

Что вы хотите сделать, не соответствует модели Emacs, как работает привязка клавиш.

2

Это то, что я использую для своего пакета 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), а затем локальные и, наконец, глобальные привязки клавиш.