Come scoprire cosa fa veramente una sequenza di tasti


14

Di tanto in tanto osservo comportamenti inaspettati durante la modifica del testo. Il mio primo ricorso è di solito da usare C-h kper scoprire quali funzioni vengono chiamate da una determinata sequenza di tasti. Tuttavia, a volte la documentazione è in contrasto con il comportamento osservato. In questi casi, di solito presumo che qualche altro pacchetto sia stato agganciato a quella funzione o sequenza di tasti e ne stia modificando il comportamento.

Come posso scoprire quali funzioni sono collegate alla mia sequenza di tasti?

Un esempio che ho riscontrato di recente è che ho premuto il "tasto e le virgolette sono state inserite all'inizio e alla fine della regione attiva. Avevo il sospetto che questo non fosse il comportamento predefinito di Emacs, quindi ho C-h k "scoperto quale funzione veniva effettivamente chiamata.

La describe-keydocumentazione mi ha detto che la funzione self-insert-commandveniva chiamata, che è una funzione integrata. Per farla breve, dopo un certo numero di tentativi ed errori, sono stato in grado di determinare che il comportamento era causato da electric-pair-mode. In futuro, c'è un modo più veloce per arrivare a questa conclusione che disattivare i pacchi sospetti uno alla volta fino a trovare il colpevole?


È possibile che sia electric-pair-modestato attivato solo in alcune modalità principali? Non si vede ancora self-insert-commandper "quando si fa C-h kmentre electric-pair-modeè attivo?
Kaushal Modi,

@kaushalmodi: si scopre che electric-pair-modefunziona agganciandosi post-self-insert-hooke non cambiando il keybinding.
nispio,

C-h kti dice esattamente cosa succede per un tasto premuto. Se guardi la documentazione per self-insert-command, dice molto chiaramente che post-self-insert-hookviene eseguito al termine del comando.
shosti,

@shosti: in questo semplice esempio, sì. Ma cosa succede se un'estensione utilizza after-change-functionscome menziona Jordon nella sua risposta? La documentazione per una funzione probabilmente non menzionerà specificamente quell'hook, vero?
nispio,

Scusa, avrei dovuto essere più specifico. C-h k+ gli hook standard == il comportamento completo (più o meno). Ovviamente a volte ciò lascia molte possibilità, ma è ancora molto più trasparente di qualsiasi altro sistema software complesso che io conosca.
shosti,

Risposte:


13

Non esiste un modo semplice per sapere esattamente cosa farà una singola pressione del tasto.

Se vedi un comportamento aggiuntivo controlla sempre i ganci comuni. Vedi l'elenco qui: http://www.gnu.org/software/emacs/manual/html_node/elisp/Standard-Hooks.html

Nella maggior parte dei casi, quelli importanti sono:

  • dopo-cambio-funzioni
  • prima-cambio-funzioni
  • primo-cambio-hook
  • post-command-hook
  • pre-command-hook
  • post-auto-insert-hook

Dovrai ispezionare quei ganci e esaminare le funzioni in essi contenute per vedere quale sta modificando il tuo comportamento.

Se le funzioni di questi hook non descrivono completamente il comportamento osservato, consultare le funzioni per un consiglio che verrà mostrato nella loro documentazione describe-function.


Modifica: ho scritto alcune funzioni per aiutare a descrivere un hook meglio che passare attraverso le funzioni una per una: https://gist.github.com/jordonbiondo/bad03e44bb053db0f1eb È possibile utilizzare describe-hookdefinite lì come le altre funzioni di descrizione. Ecco un esempio del suo output:

Ed ecco tutto il codice, nel caso in cui l'essenza scompaia:

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

Ciò significa che quando viene avvisata una funzione, la documentazione viene automaticamente aggiornata per riflettere la modifica?
nispio,

Non so se le proprietà effettive vengano aggiornate, ma il valore restituito da documentationviene aggiornato per riflettere.
Jordon Biondo,

1
@nispio sì, lo è.
Malabarba,

1
Il codice / funzione in gist.github.com/jordonbiondo/bad03e44bb053db0f1eb potrebbe, e secondo me, dovrebbe essere incluso nella risposta. Penso che una risposta SE abbia un limite di 30.000 caratteri.
Faheem Mitha,

4

Forse non è una risposta completa alla tua domanda, ma il pacchetto helm-descbindsti aiuta a cercare tutti i collegamenti da tastiera definiti dalla rappresentazione ASCII del collegamento. Per ogni hit, mostra la funzione interattiva associata alla scorciatoia da tastiera e puoi chiedere helm-descbindsdi descriverla o eseguirla direttamente dai risultati della ricerca.

inserisci qui la descrizione dell'immagine

Ecco la descrizione del pacchetto dal sito GitHub:

Helm Descbinds fornisce un'interfaccia ai descrizioni-collegamenti di emacs che rendono le associazioni di tasti attualmente attive ricercabili interattivamente con helm.

Inoltre hai le seguenti azioni

  • Esegui il comando
  • Descrivi il comando
  • Trova il comando

E C-zti darà una descrizione persistente del comando corrente.


2
Questo è fantastico Lo legherò sicuramente a C-h b. Il mio unico desiderio è che potrei saltare alla voce dell'elenco immettendo la sequenza di tasti effettiva invece di digitareC - c _ C - p
nispio
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.