Cómo descubrir qué hace realmente una secuencia de teclas

14

De vez en cuando observo un comportamiento inesperado al editar texto. Mi primer recurso suele ser utilizar C-h kpara averiguar qué funciones está llamando una secuencia de teclas determinada. Sin embargo, a veces la documentación está en desacuerdo con el comportamiento observado. En estos casos, generalmente asumo que algún otro paquete se ha conectado a esa función o secuencia de teclas y está modificando su comportamiento.

¿Cómo puedo averiguar qué funciones se enganchan en mi secuencia de teclas?

Un ejemplo que encontré recientemente fue que presioné la "tecla y las comillas se insertaron al principio y al final de la región activa. Tenía la sospecha de que este no era el comportamiento predeterminado de Emacs, así que solía C-h k "averiguar qué función se llamaba realmente.

La describe-keydocumentación me dijo que self-insert-commandse estaba llamando a la función , que es una función incorporada. Para resumir, después de una cierta cantidad de prueba y error, pude determinar que el comportamiento fue causado por electric-pair-mode. En el futuro, ¿hay una manera más rápida de llegar a esta conclusión que apagar los paquetes sospechosos de uno en uno hasta encontrar al culpable?

nispio
fuente
¿Es posible que electric-pair-modese haya activado solo en algunos modos principales? ¿Todavía ve self-insert-commandpara "cuando lo hace C-h kmientras electric-pair-modeestá activo?
Kaushal Modi
@kaushalmodi: Resulta que electric-pair-modefunciona enganchándose post-self-insert-hooky no cambiando la combinación de teclas.
nispio
C-h kle dice exactamente qué sucede con una pulsación de tecla. Si observa la documentación self-insert-command, dice claramente que post-self-insert-hookse ejecuta una vez que finaliza el comando.
shosti
@shosti: En este simple ejemplo, sí. Pero, ¿y si una extensión usa after-change-functionscomo Jordon menciona en su respuesta? La documentación para una función probablemente no mencionará específicamente ese gancho, ¿verdad?
nispio
Lo siento, debería haber sido más específico. C-h k+ los ganchos estándar == el comportamiento completo (más o menos). Por supuesto, a veces eso deja muchas posibilidades, pero aún es mucho más transparente que cualquier otro sistema de software complejo que conozco.
shosti

Respuestas:

13

No hay una manera fácil de saber exactamente qué hará una sola pulsación de tecla.

Si ve un comportamiento adicional, siempre verifique los ganchos comunes. Vea la lista aquí: http://www.gnu.org/software/emacs/manual/html_node/elisp/Standard-Hooks.html

En la mayoría de los casos, los importantes son:

  • funciones posteriores al cambio
  • funciones antes del cambio
  • primer cambio de gancho
  • gancho de comando posterior
  • gancho de precomando
  • post-self-insert-hook

Tendrá que inspeccionar esos ganchos y examinar las funciones que contienen para ver cuál está modificando su comportamiento.

Si las funciones en estos ganchos no describen completamente el comportamiento observado, verifique las funciones para obtener consejos que aparecerán en su documentación describe-function.


Editar: he escrito algunas funciones para ayudar a describir un gancho mejor que pasar por las funciones una por una: https://gist.github.com/jordonbiondo/bad03e44bb053db0f1eb . Puede usar describe-hooklas funciones definidas allí como las otras funciones de descripción. Aquí hay una muestra de su salida:

Y aquí está todo el código, en caso de que la esencia desaparezca:

(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
fuente
¿Significa eso que cuando se aconseja una función, la documentación se actualiza automáticamente para reflejar el cambio?
nispio
No sé si las propiedades reales se actualizan, pero el valor devuelto por documentationse actualiza para reflejar.
Jordon Biondo
1
@nispio sí, lo es.
Malabarba
1
El código / función en gist.github.com/jordonbiondo/bad03e44bb053db0f1eb podría, y en mi opinión, debería incluirse en la respuesta. Creo que una respuesta SE tiene un límite de 30,000 caracteres.
Faheem Mitha
4

Quizás no sea una respuesta completa a su pregunta, pero el paquete lo helm-descbindsayuda a buscar todas las vinculaciones de teclado definidas desde la representación ascii del atajo. Para cada golpe, muestra la función interactiva asociada con el método abreviado de teclado, y puede solicitar helm-descbindsque lo describa o ejecutarlo directamente desde los resultados de búsqueda.

ingrese la descripción de la imagen aquí

Aquí está la descripción del paquete del sitio de GitHub:

Helm Descbinds proporciona una interfaz para los enlaces de descripción de emacs que hacen que los enlaces de teclas actualmente activos se puedan buscar interactivamente con helm.

Además tienes las siguientes acciones

  • Ejecutar el comando
  • Describe el comando
  • Encuentra el comando

Y C-zle dará una descripción persistente del comando actual.

Amelio Vazquez-Reina
fuente
2
Esto es genial. Definitivamente voy a unir esto C-h b. Mi único deseo es poder saltar al elemento de la lista ingresando la secuencia de teclas real en lugar de escribirC - c _ C - p
nispio