2010-03-22 17 views
9

Ich habe einen kleinen Modus. Wenn dieser Modus aktiv ist und der Benutzer auf DEL klickt, möchte ich eine Aktion ausführen, aber nur, wenn eine Bedingung erfüllt ist. Wenn die Bedingung gilt und die Aktion ausgeführt wird, möchte ich danach nichts mehr tun . Aber wenn die Bedingung fehlschlägt, möchte ich nichts tun und lassen Sie die Standard-DEL-Aktion ausführen.Emacs Schlüssel Binding Fallback

Nicht sicher, wie ich das lösen könnte. Aber ich denke, ich es auf zwei Arten tun könnte:

1) ich die DEL-Taste, um eine Funktion in Moll rebind konnte und dann überprüfen, ob die Bedingungen nicht ot halten. Aber woher weiß ich dann, was der Standardbefehl für DEL ist?

2) Ich könnte einen Pre-Befehl Hook wie folgt hinzufügen. Führen Sie den Befehl und dann brechen Sie die Kette. Aber wie durchbrich ich die Kette?

(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) 
      ))) 

In welcher Weise würden Sie es lösen? Vielen Dank!

+0

Sind Del und Backspace gleich? – Amos

Antwort

12

Der Weg, dies zu tun, ist vorübergehend deaktivieren Sie Ihre Neben-Modus, dann nachschlagen die Tastenbindung.

Geben Sie vor, dass Sie 'do-thingy an DEL gebunden haben. Dann würde dies den Trick (vorausgesetzt, die Bedingung, die Sie auslösen wollen, ist (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!"))) 

Hinweis: Dieses Verhalten vorausgesetzt, dass Sie Ihre key bindings die standard way a minor-mode would einrichten Insbesondere sollten Sie Ihre keymap auf die Variable minor-mode-map-alist hinzuzufügen. (my-minor-mode . my-minor-mode-keymap) durch ein Element hinzugefügt wird. das ist, wie die oben let Anweisung funktioniert, es sucht die Bindung Sie mit Ihrem Modus wollen vorübergehend deaktiviert.

Wenn Sie define-minor-mode verwenden Ihre Moll zu definieren, wird die keymap die „richtige Art und Weise einrichten "automatisch.

+0

Perfekt, Danke! – rejeep

+2

Wie wäre es mit einem willkürlichen Fallback, bei dem Sie nicht im Voraus wissen, um welchen Schlüssel es sich handelt, auf dessen Bindung Sie zurückgreifen möchten? Wie können Sie die Bindung programmatisch nachschlagen, um den Wert von original-func zu verwenden? (vergiss es: es sieht so aus, als ob man diesen Befehl-Schlüssel-Vektor benutzt). –

-3

Es scheint keine Möglichkeit zu geben, das zu tun, was Sie zuverlässig wollen. Wenn Ihr neuer Befehl an DEL gebunden ist, ist das, was zuvor in der aktuellen Tastaturbelegung an DEL gebunden war, nicht mehr vorhanden. Der andere Ansatz, den Sie vorgeschlagen haben, funktioniert nicht, da Pre-Command-Hooks die folgende Aktion nicht verhindern. Sie könnten auch daran denken, die weitere Ausführung mit^G (Keyboard-Quit) zu unterbrechen, aber das ist ein unkontrollierter Interrupt, der möglicherweise mehr Dinge stoppt, als Sie wollen.

Auch wenn Sie den Prozess der Einrichtung der neuen Bindung ein wenig ausgefeilter als nur neu binden, und merken Sie sich, was dort zuvor gebunden wurde, so dass Sie es später aufrufen können, haben Sie nicht wirklich, was Sie suchen zum. Wenn jemand die "Standard" -Aktion erneut binden möchte, muss er dies tun, indem er die Funktion ändert, anstatt die Schlüsselanbindung zu ersetzen.

Was Sie tun möchten, passt nicht in Emacs 'Modell, wie die Schlüsselbindung funktioniert.

2

Dies ist, was ich für meine smart-tab-Paket verwenden, die genau das tut.

(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)]))))) 

Und in dem Befehl smart-tab, hat es die folgenden (die man auf die Registerkarte in der kleinen Modus gebunden ist):

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

Es prüft zunächst, ob es Modus Bindungen für alle minor Registerkarte (nicht einschließlich smart-tab-mode), dann lokale und schließlich globale Tastaturbelegung.