¿Cómo actualiza una definición de modo menor a medida que la desarrolla?

13

Comencé a codificar un modo menor para proporcionar algunas combinaciones de teclas. Mi intento inicial tuvo un error tipográfico:

(define-minor-mode borked-mode
  "A mode defined with a broken key binding"
  nil nil
  '(([b] . 'previous-line)))

Tenía la intención de usar la bllave e inmediatamente me di cuenta de que debería haberlo usado en "b"lugar de hacerlo [b]. Así que redefiní el modo menor:

(define-minor-mode borked-mode
  "A mode defined with a broken key binding"
  nil nil
  '(("b" . 'previous-line)))

Sin embargo, esto no funcionó. Esto me puso en una persecución salvaje a través de todas las diversas formas de vincular teclas (es decir, (kbd ...), [...], etc.). Finalmente me di cuenta de que simplemente reevaluar el (define-minor-mode ...)formulario no estaba cambiando nada, me quedé atrapado con el mapa de teclas roto original. Luego intenté cambiar el mapa de teclas directamente a través de (define-key borked-mode-map ...)y todavía no pude cargar el mapa de teclas corregido. Finalmente reinicié Emacs, y mi modo menor se cargó correctamente.

Mi pregunta es: ¿cómo actualiza una definición de modo menor a medida que la desarrolla? ¿Hay alguna forma de vaciar una definición rota, o tienes que reiniciar emacs para borrar los bits rotos?

Tyler
fuente

Respuestas:

11

La primera vez que evalúa su define-minor-modedefine una variable borked-mode-mapcon las asociaciones de teclas que especificó. Sin embargo, una vez que se haya definido ese símbolo, volver a evaluarlo define-minor-modeno lo cambiará.

Puede eliminar los diversos borked-mode-xxxsímbolos usando uninterny luego volver a evaluar su código. Tratar:

(unintern 'borked-mode-map)

Quizás le interese expandir la define-minor-modemacro para ver qué está haciendo realmente. Poner punto al final y llamar M-x pp-macroexpand-last-sexp. Esto abrirá un nuevo búfer que muestra la macro expandida. Allí verá las defvarllamadas utilizadas para configurar sus variables de modo. Si lee la ayuda defvar, verá que el valor inicial solo se usa si el símbolo que se define es nulo; una vez que exista, las defvarllamadas posteriores no cambiarán su valor.

glucas
fuente
13

Creo que la mejor respuesta que puedo darle es mantenerse alejado de la "función de combinación de teclas en línea" de define-minor-mode. Utilizar

(defvar borked-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map [b] 'previous-line)
    ...
    map))

(define-minor-mode borked-mode
  "A mode defined with a broken key binding"
  :global nil
  ...)

En lugar. Luego puede usar C-M-xpara reevaluar esas definiciones.

Stefan
fuente
1
defvarno evaluará su valor nuevamente después de C-M-x:) Necesitarías defparametero por separado setf.
wvxvw
Como señala @wvxvw, esto en realidad no aborda el problema. Su código de ejemplo está haciendo lo mismo que la define-minor-modemacro: llamando defvarpara definir el mapa. Evaluar ese defvar por segunda vez no tiene ningún efecto.
glucas
77
@wvxvw Si usa C-M-x( eval-defun) para reevaluar defvar, la variable se actualiza. Este es un caso especial en eval-defun; si llama eval-buffero eval-regionluego el valor existente no cambia.
Gilles 'SO- deja de ser malvado'
Ah, ese parece ser el punto clave.
glucas
1
Tenga C-M-xen cuenta que en el defvarformulario solo se actualiza la variable mode-map en sí. También debe hacerlo C-M-xen el define-minor-modeformulario para 'instalar' el mapa modificado en el modo menor. Traté de entender por qué expandiendo las macros, pero está más allá de mí.
Tyler