Diferenças entre definir as principais teclas de modo com um gancho e adicioná-las ao mapa de modos

13

Suponha que eu baixei um modo principal chamado magical-modee ele tem seu próprio mapa de teclas mágico chamado magical-mode-map. Este modo também fornece um gancho magical-mode-hookque é executado cada vez que magical-modese torna o modo principal de um buffer. Agora eu quero modificar meu arquivo init para adicionar algumas associações de teclas personalizadas para usar nesse modo.

Parece que existem (pelo menos) duas maneiras de configurar ligações de teclas personalizadas magical-mode. O que eu vejo mais comumente é o seguinte:

(defun my-magical-keys ()
  (local-set-key (kbd "C-i") 'previous-line)
  (local-set-key (kbd "C-k") 'next-line)
  (local-set-key (kbd "C-j") 'backward-char)
  (local-set-key (kbd "C-l") 'forward-char))
(add-hook 'magical-mode-hook 'my-magical-keys)

Mas também é possível fazê-lo desta maneira:

(define-key magical-mode-map (kbd "C-i") 'previous-line)
(define-key magical-mode-map (kbd "C-k") 'next-line)
(define-key magical-mode-map (kbd "C-j") 'backward-char)
(define-key magical-mode-map (kbd "C-l") 'forward-char)

O segundo método realmente parece mais limpo para mim. Existem vantagens em fazer isso de uma maneira ou de outra?

nispio
fonte
Eu uso as mesmas teclas para os comandos básicos de movimento. Esteja avisado: esta é uma batalha difícil e você pode aprender um pouco mais sobre as combinações de teclas antes de começar a fazer isso.
tarsius
@ tarsius Uma batalha difícil de fato. Eu tenho ido por esse caminho antes, mas agora estou de volta ao bom e velho C-ne C-p. O exemplo é apenas código fictício. Eu queria criar alguns modos de exemplo e ligações de exemplo muito simples, precisamente para que as próprias ligações não desviassem o objetivo real da pergunta.
Nispio 10/10

Respostas:

15

A segunda abordagem é preferível, pois modifica o mapa de teclas do modo apenas uma vez.

Se você fizer isso usando o gancho do modo, isso será chamado sempre que esse modo for ativado em algum buffer. Fazer isso de novo normalmente não terá efeito, porque as chaves estão novamente ligadas ao que elas já estão ligadas. Os mapas de teclas do modo principal são "locais" para o modo principal e não os buffers individuais que usam esse modo; portanto, se você alterar uma ligação em um desses buffers usando local-set-key, isso afetará todos os buffers com o mesmo modo principal.

local-set-keydestina-se principalmente a ser usado como um comando. Depois de determinar que você gostaria de fazer algumas alterações persistentes, use define-keycom o mapa de teclas de modo como o primeiro argumento.

Se você usar um gancho para modificar o mapa de teclas repetidamente, isso poderá entrar em conflito com o uso pretendido de local-set-key. Digamos que você usou M-x local-set-key RET C-i fancy-previous-line RETporque deseja experimentar essa variante de previous-line. Se você agora abrir um novo buffer que usa o mesmo modo principal, o gancho será executado novamente e substituirá sua ligação temporária em todos os buffers que usam esse modo principal, incluindo o buffer no qual você usou anteriormente local-set-key.

tarso
fonte
Eu gosto desta resposta, mas e se o modo for carregado automaticamente?
Remvee 10/10
2
Você pode atrasar o carregamento qualquer código até depois de alguma biblioteca foi carregado: (eval-after-load 'magical '(progn (define-key magical-mode-map ...) ...)).
tarsius
4

Usar (define-key my-magical-mode-map …)é o caminho normal.

Quando você usa um gancho e local-set-key, as teclas são adicionadas sempre que você entra no modo Mágico em algum buffer. Isso é estranho porque local-set-keyafeta todos os buffers que estão no mesmo modo (mais geralmente, todos os buffers usando o mesmo mapa de teclas). Portanto, se você tiver feito alterações no mapa de teclas, elas serão substituídas toda vez que você entrar no modo Mágico em um buffer.

O segundo método também pode ser confuso se você personalizar o mapa de teclas em locais diferentes. Os ganchos são executados na ordem inversa da ordem em que foram adicionados e, até a primeira vez em que são executados, você não verá nenhum vestígio de suas personalizações.

Gilles 'SO- parar de ser mau'
fonte
2

Aparentemente, você não está perguntando sobre a definição de um mapa de teclas de modo principal, mas sobre o código do usuário para adicionar ou alterar algumas ligações de teclas em um mapa de teclas de modo principal existente . Você diz "personalizado", o que sugere isso, mas é melhor deixarmos claro.

Para ter certeza, o que você diz que vê com mais frequência para isso não é o que geralmente é usado para definir um mapa de teclas no modo principal. É não o que você encontra no código fonte Emacs, por exemplo. E é não o que é recomendado no manual Elisp (nó Major Mode Conventions).

Só queria tirar isso do caminho, para ficar claro para os outros: geralmente você não deseja usar o gancho de modo para definir o mapa do modo principal.


Para sua pergunta sobre personalizações de chave do usuário -

De qualquer forma, não é para local-set-keyvocê usar em um gancho de modo. Basta usar define-keycom o mapa de teclas do modo principal, exatamente como no seu primeiro exemplo. @tarsius já explicou isso bem.

Fora isso, a resposta é: faz pouca diferença, em geral , se você liga as teclas (usando define-keycom o mapa de modo) de uma vez por todas ou se usa o gancho para ligá-las cada vez que entra no modo.

Mas pode fazer a diferença se as ligações no mapa mudarem - por exemplo, ao carregar algum outro código que as altere. Nesse caso, colocar as ligações no gancho do modo principal garante que, quando o modo for inserido, as ligações sejam estabelecidas. Ou seja, garante que eles serão feitos, mas não garante que nada mais os altere posteriormente (por exemplo, outra função no mesmo gancho, chamada posteriormente). Lembre-se de que você tem pouco controle sobre o que é executado em um gancho e quando - a menos que, é claro, tenha certeza de que apenas seu próprio código mexe com ele.

Essa é a única diferença de efeito em que consigo pensar. Para você decidir quando considera essa diferença uma vantagem de uma ou outra abordagem. FWIW, olhando para o meu próprio código, acho que nunca vinculo chaves em um gancho de modo.

Desenhou
fonte
Obrigado. Modifiquei a pergunta para esclarecer, com sorte, que não estou criando um modo principal, simplesmente adicionando minhas próprias associações de teclas ao modo principal existente .
Nispio 10/10
0

Seu nome é um pouco confuso (acho que você deve remover myna sua segunda parte da pergunta).

De qualquer forma, assumindo que my-magical-keysé uma função de personalização do usuário magical-mode, vejo uma vantagem óbvia. É fácil remover (por remove-hook) o gancho de uma só vez.

A segunda vantagem é para que servem as funções. Quero dizer, eles são reutilizáveis. você pode conectá-los a outros modos.

Editar:

Como o @tarsius apontou, remover o gancho não restaurará o comportamento original e transformar a função em um modo menor pode ser melhor.

tipo de herói
fonte
Estou personalizando um modo principal hipotético chamado my-magical-mode. No entanto, se o uso do my-prefixo é confuso, certamente posso editar a pergunta.
Nispio 10/10
Sim, isso seria melhor, geralmente (pelo menos como eu vejo na natureza) my-é adicionado para as funções do usuário.
Kindahero # 10/14
1
Acordado. Eu apenas apliquei o método my-para que ninguém pensasse que eu estava perguntando como configurar um modo real chamado magical-mode(se existir).
Nispio 10/10
1
Não, remover o gancho não restaurará as ligações antigas. Pelo menos não até o Emacs ser reiniciado, e não vejo necessidade de comentar apenas uma linha em vez de quatro, como uma grande melhoria.
tarsius
2
Quanto à segunda vantagem que você menciona: aqui seria preferível criar um modo menor que poderia ser ativado para vários modos principais e / ou apenas alguns dos buffers usando um modo principal específico.
tarsius