So finden Sie heraus, was eine Tastenfolge wirklich bewirkt

14

Von Zeit zu Zeit beobachte ich unerwartetes Verhalten beim Bearbeiten von Text. Meine erste Möglichkeit besteht normalerweise darin C-h k, herauszufinden, welche Funktionen von einer bestimmten Tastenfolge aufgerufen werden. Manchmal widerspricht die Dokumentation jedoch dem beobachteten Verhalten. In diesen Fällen gehe ich normalerweise davon aus, dass sich ein anderes Paket in diese Funktion oder Tastenfolge eingebunden hat und ihr Verhalten ändert.

Wie kann ich herausfinden, welche Funktionen in meine Tastenfolge eingebunden sind?

Ein Beispiel, auf das ich kürzlich gestoßen bin, war das Drücken der "Taste und das Einfügen von Anführungszeichen am Anfang und Ende des aktiven Bereichs. Ich hatte den Verdacht, dass dies nicht das Standardverhalten von Emacs war, also habe ich C-h k "herausgefunden, welche Funktion tatsächlich aufgerufen wurde.

Die describe-keyDokumentation hat mir gesagt , dass die Funktion self-insert-commandaufgerufen wurde, die eine eingebaute Funktion ist. Um es kurz zu machen, nach einigem Ausprobieren konnte ich feststellen, dass das Verhalten durch verursacht wurde electric-pair-mode. Gibt es in Zukunft einen schnelleren Weg, um zu dieser Schlussfolgerung zu gelangen, als verdächtige Pakete einzeln auszuschalten, bis der Täter gefunden ist?

Nispio
quelle
Ist es möglich, dass das electric-pair-modenur in einigen Hauptmodi aktiviert wurde? Sehen Sie noch self-insert-commandfür , "wenn Sie tun , C-h kwährend electric-pair-modeaktiv ist?
Kaushal Modi
@kaushalmodi: Es stellt sich heraus, dass dies electric-pair-modefunktioniert, indem man sich einhakt post-self-insert-hookund nicht, indem man die Tastenkombination ändert.
nispio
C-h ksagt Ihnen genau, was bei einem Tastendruck passiert. Wenn Sie sich die Dokumentation ansehen self-insert-command, wird sehr deutlich angezeigt, post-self-insert-hookdass der Befehl ausgeführt wird, nachdem er ausgeführt wurde.
Shosti
@shosti: In diesem einfachen Beispiel ja. Aber was ist, wenn eine Erweiterung after-change-functionswie Jordon in seiner Antwort erwähnt? In der Dokumentation einer Funktion wird dieser Haken wahrscheinlich nicht speziell erwähnt, oder?
Nispio
Entschuldigung, ich hätte genauer sein sollen. C-h k+ die Standard-Hooks == das komplette Verhalten (mehr oder weniger). Natürlich lässt das manchmal eine Menge Möglichkeiten offen, aber es ist immer noch viel transparenter als jedes andere komplexe Softwaresystem, das ich kenne.
Shosti

Antworten:

13

Es gibt keine einfache Möglichkeit, genau zu wissen, was ein einziger Tastendruck bewirkt.

Wenn Sie zusätzliches Verhalten sehen, überprüfen Sie immer die allgemeinen Haken. Die Liste finden Sie hier: http://www.gnu.org/software/emacs/manual/html_node/elisp/Standard-Hooks.html

In den meisten Fällen sind die wichtigsten:

  • After-Change-Funktionen
  • Vor-Wechsel-Funktionen
  • first-change-hook
  • Post-Command-Hook
  • Pre-Command-Hook
  • Post-Self-Insert-Hook

Sie müssen diese Haken untersuchen und die darin enthaltenen Funktionen überprüfen, um festzustellen, welche Ihr Verhalten ändert.

Wenn die Funktionen in diesen Hooks das beobachtete Verhalten nicht vollständig beschreiben, überprüfen Sie die Funktionen auf Hinweise, die in der Dokumentation von aufgeführt werden describe-function.


Bearbeiten: Ich habe einige Funktionen geschrieben, um einen Hook besser zu beschreiben, als die einzelnen Funktionen durchzugehen : https://gist.github.com/jordonbiondo/bad03e44bb053db0f1eb Sie können dort describe-hookdefinierte Funktionen wie die anderen Beschreibungsfunktionen verwenden. Hier ist ein Beispiel für die Ausgabe:

Und hier ist der gesamte Code für den Fall, dass das Wesentliche verschwindet:

(defun guess-all-hooks ()
  "Return a list of all variables that are probably hook lists."
  (let ((syms '()))
    (mapatoms
     (lambda (sym)
       (if (ignore-errors (symbol-value sym))
           (let ((name (symbol-name sym)))
             (when (string-match "-\\(hook[s]?\\|functions\\)$" name)
               (push sym syms))))))
    syms))

(defun face-it (str face)
  "Apply FACE to STR and return."
  (propertize str 'face face))

(defun describe-hook (hook)
  "Display documentation about a hook variable and the
functions it contains."
  (interactive
   (list (completing-read
          "Hook: " (mapcar (lambda (x) (cons x nil)) (guess-all-hooks)))))
  (let* ((sym (intern hook))
         (sym-doc (documentation-property sym 'variable-documentation))
         (hook-docs (mapcar
                     (lambda (func)
                       (cons func (ignore-errors (documentation func))))
                     (symbol-value sym))))
    (switch-to-buffer
     (with-current-buffer (get-buffer-create "*describe-hook*")
       (let ((inhibit-read-only t))
         (delete-region (point-min) (point-max))
         (insert (face-it "Hook: " 'font-lock-constant-face) "\n\n")
         (insert (face-it (concat "`" hook "'") 'font-lock-variable-name-face))
         (replace-string "\n" "\n\t" nil
                         (point)
                         (save-excursion
                           (insert "\n" sym-doc "\n\n")
                           (1- (point))))
         (goto-char (point-max))
         (insert (face-it "Hook Functions: " 'font-lock-constant-face) "\n\n")
         (dolist (hd hook-docs)
           (insert (face-it (concat "`" (symbol-name (car hd)) "'")
                            'font-lock-function-name-face)
                   ": \n\t")
           (replace-string "\n" "\n\t" nil
                           (point)
                           (save-excursion
                             (insert (or (cdr hd) "No Documentation") "\n\n")
                             (1- (point))))
           (goto-char (point-max))))
       (help-mode)
       (help-make-xrefs)
       (read-only-mode t)
       (setq truncate-lines nil)
       (current-buffer)))))
Jordon Biondo
quelle
Bedeutet das, dass die Dokumentation automatisch aktualisiert wird, wenn eine Funktion benachrichtigt wird, um die Änderung widerzuspiegeln?
Nispio
Ich weiß nicht, ob die tatsächlichen Eigenschaften aktualisiert werden, aber der von zurückgegebene Wert documentationwird entsprechend aktualisiert.
Jordon Biondo
1
@nispio ja, das ist es.
Malabarba
1
Der Code / die Funktion in gist.github.com/jordonbiondo/bad03e44bb053db0f1eb könnte und sollte meiner Meinung nach in die Antwort aufgenommen werden. Ich denke, eine SE-Antwort hat ein Limit von 30.000 Zeichen.
Faheem Mitha
4

Möglicherweise ist Ihre Frage nicht vollständig beantwortet, aber das Paket helm-descbindshilft Ihnen beim Durchsuchen aller definierten Tastaturbelegungen in der ASCII-Darstellung der Verknüpfung. Für jeden Treffer wird die mit der Tastenkombination verknüpfte interaktive Funktion angezeigt. Sie können danach fragen helm-descbinds, ob Sie sie beschreiben möchten, oder sie direkt aus den Suchergebnissen ausführen .

Bildbeschreibung hier eingeben

Hier ist die Paketbeschreibung von der GitHub-Site:

Helm Descbinds bietet eine Schnittstelle zu den Beschreibungsbindungen von Emacs, sodass die derzeit aktiven Tastenkombinationen interaktiv mit Helm durchsucht werden können.

Zusätzlich haben Sie folgende Aktionen

  • Führen Sie den Befehl aus
  • Beschreiben Sie den Befehl
  • Suchen Sie den Befehl

Und C-zgibt Ihnen eine dauerhafte Beschreibung des aktuellen Befehls.

Amelio Vazquez-Reina
quelle
2
Das ist toll. Ich werde das definitiv binden C-h b. Mein einziger Wunsch ist , dass ich die aktuelle Tastenfolge auf der Liste zu dem Element springen könnte durch Eingabe statt einer Eingabe ausC - c _ C - p
nispio