Como você atualiza uma definição de modo secundário à medida que a desenvolve?

13

Comecei a codificar um modo secundário para fornecer algumas combinações de teclas. Minha tentativa inicial teve um erro de digitação:

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

Eu pretendia usar a bchave e percebi imediatamente que deveria ter usado em "b"vez de [b]. Então, redefini o modo secundário:

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

No entanto, isso não funcionou. Isso me desencadeou em todas as formas de vincular chaves (ou seja, (kbd ...), [...] etc.). Finalmente, percebi que simplesmente reavaliar o (define-minor-mode ...)formulário não estava mudando nada, fiquei preso ao mapa de chaves original e quebrado. Tentei alterar o mapa de teclas diretamente via (define-key borked-mode-map ...)e ainda não consegui carregar o mapa de teclas corrigido. Finalmente, reiniciei o Emacs e meu modo secundário foi carregado corretamente.

Minha pergunta é: como você atualiza uma definição de modo secundário à medida que a desenvolve? Existe alguma maneira de liberar uma definição quebrada ou você precisa reiniciar o emacs para limpar os bits quebrados?

Tyler
fonte

Respostas:

11

Na primeira vez em que você avalia define-minor-mode, define uma variável borked-mode-mapcom as ligações de teclas especificadas. Uma vez que o símbolo tenha sido definido, no entanto, reavaliar o seu define-minor-modenão o mudará.

Você pode excluir os vários borked-mode-xxxsímbolos usando uninterne depois reavaliar seu código. Experimentar:

(unintern 'borked-mode-map)

Você pode estar interessado em expandir a define-minor-modemacro para ver o que está realmente fazendo. Coloque o ponto no final e ligue M-x pp-macroexpand-last-sexp. Isso abrirá um novo buffer mostrando a macro expandida. Lá você verá as defvarchamadas usadas para configurar suas variáveis ​​de modo. Se você ler a ajuda, defvarverá que o valor inicial é usado apenas se o símbolo definido for nulo - uma vez que exista, as defvarchamadas subseqüentes não mudarão seu valor.

glucas
fonte
13

Acho que a melhor resposta que posso lhe dar é ficar longe do "recurso de vinculação de teclas em linha" de define-minor-mode. Usar

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

Em vez de. Então você pode usar C-M-xpara reavaliar essas definições.

Stefan
fonte
1
defvarnão avaliará seu valor novamente depois C-M-x:) Você precisaria defparameterou um separado setf.
wvxvw
Como o @wvxvw aponta, isso não resolve o problema. Seu código de exemplo está fazendo o mesmo que a define-minor-modemacro: chamando defvarpara definir o mapa. Avaliar que defvar uma segunda vez não tem efeito.
glucas
7
@wvxvw Se você usar C-M-x( eval-defun) para reavaliar defvar, a variável será atualizada. Este é um caso especial em eval-defun; se você ligar eval-bufferou eval-regiono valor existente não for alterado.
Gilles 'SO- stop be evil'
Ah - esse parece ser o ponto principal.
glucas
1
Observe que, C-M-xno defvarformulário, apenas atualiza a própria variável mode-map. Você também precisa preencher C-M-xo define-minor-modeformulário para obter o mapa alterado 'instalado' no modo secundário. Tentei descobrir o motivo expandindo as macros, mas está além de mim.
Tyler