Différences entre la définition de touches de mode principales avec un crochet et leur ajout à la carte de mode

13

Supposons que j'ai téléchargé un mode majeur appelé magical-mode, et qu'il a son propre clavier magique appelé magical-mode-map. Ce mode fournit également un hook magical-mode-hookqui est exécuté chaque fois qu'il magical-modedevient le mode principal d'un tampon. Maintenant, je veux modifier mon fichier init pour ajouter quelques raccourcis clavier personnalisés à utiliser dans ce mode.

Il semble qu'il existe (au moins) deux façons de configurer des liaisons de touches personnalisées pour magical-mode. Celui que je vois le plus souvent est le suivant:

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

Mais il est également possible de le faire de cette façon:

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

La deuxième méthode me semble en fait plus propre. Y a-t-il des avantages à le faire d'une manière par rapport à l'autre?

nispio
la source
J'utilise les mêmes touches pour les commandes de mouvement de base. Soyez averti: c'est une bataille difficile et vous voudrez peut-être en savoir un peu plus sur les raccourcis clavier avant de commencer.
tarsius
@tarsius Une bataille difficile en effet. Je suis allé dans cette voie avant, mais maintenant je suis de retour à la bonne vieille C-net C-p. L'exemple n'est qu'un code factice. Je voulais proposer des modes d'exemple et des liaisons d'exemple très simples, précisément pour que les liaisons elles-mêmes ne distraient pas le but réel de la question.
nispio

Réponses:

15

La deuxième approche est préférable car elle ne modifie le clavier du mode qu'une seule fois.

Si vous le faites en utilisant le hook du mode, cela sera appelé à chaque fois que ce mode est activé dans un tampon. Le faire à nouveau n'aura généralement aucun effet, car les clés sont à nouveau liées à ce à quoi elles sont déjà liées. Les images clés du mode principal sont "locales" pour le mode principal et non pour les tampons individuels qui utilisent ce mode, donc si vous modifiez une liaison dans l'un de ces tampons en utilisant local-set-keyalors cela affecte tous les tampons avec le même mode principal.

local-set-keyest principalement destiné à être utilisé comme une commande. Une fois que vous avez déterminé que vous souhaitez rendre certains changements persistants, utilisez define-keyle mode keymap comme premier argument.

Si vous utilisez un hook pour modifier le keymap encore et encore, cela pourrait entrer en conflit avec l'utilisation prévue de local-set-key. Supposons que vous l'ayez utilisé M-x local-set-key RET C-i fancy-previous-line RETparce que vous souhaitez essayer cette variante de previous-line. Si vous ouvrez maintenant un nouveau tampon qui utilise le même mode principal, le hook s'exécutera à nouveau et remplacera votre liaison temporaire, dans tous les tampons utilisant ce mode principal, y compris le tampon dans lequel vous l'avez utilisé précédemment local-set-key.

tarse
la source
J'aime cette réponse mais que faire si le mode est chargé automatiquement?
remise du
2
Vous pouvez retarder le chargement de code jusqu'après une bibliothèque a été chargée: (eval-after-load 'magical '(progn (define-key magical-mode-map ...) ...)).
tarsius
4

L'utilisation (define-key my-magical-mode-map …)est la manière normale.

Lorsque vous utilisez un crochet et local-set-key, les clés sont ajoutées chaque fois que vous entrez dans le mode My Magical dans un tampon. C'est étrange car cela local-set-keyaffecte tous les tampons qui sont dans le même mode (plus généralement, tous les tampons utilisant le même clavier). Donc, si vous avez apporté des modifications au clavier, elles seront remplacées chaque fois que vous entrerez en mode My Magical dans un tampon.

La deuxième méthode peut également prêter à confusion si vous personnalisez le clavier à différents endroits. Les hooks sont exécutés dans l'ordre inverse de l'ordre dans lequel ils sont ajoutés, et jusqu'à la première exécution, vous ne verrez aucune trace de vos personnalisations.

Gilles 'SO- arrête d'être méchant'
la source
2

Vous apparemment pas demander au sujet de la définition d' un grand keymap mode , mais à propos de l' utilisateur code pour ajouter ou modifier quelques raccourcis clavier dans un existant important en mode keymap. Vous dites "personnalisé", ce qui suggère cela, mais nous pourrions aussi bien le dire clairement.

Pour être sûr, ce que vous dites que vous voyez le plus souvent pour cela n'est pas ce qui est généralement utilisé pour définir une carte de touches en mode majeur. Ce n'est pas ce que vous trouvez dans le code source d'Emacs, par exemple. Et ce n'est pas ce qui est recommandé dans le manuel Elisp (nœud Major Mode Conventions).

Je voulais juste éliminer cela, pour être clair pour les autres: vous ne voulez généralement pas utiliser le crochet de mode pour définir la carte en mode principal.


À votre question sur les personnalisations des clés utilisateur -

En tout cas ce n'est pas local-set-keyque vous devez utiliser dans un hook de mode. Utilisez-le simplement define-keyavec le clavier du mode principal, exactement comme dans votre premier exemple. @tarsius l'a déjà bien expliqué.

En dehors de cela, la réponse est: peu importe, en général , que vous liez les clés (à l'aide define-keyde la carte de mode) une fois pour toutes ou que vous utilisiez le crochet pour les lier chaque fois que vous entrez dans le mode.

Mais cela peut faire une différence si les liaisons dans la carte changent - par exemple, en chargeant un autre code qui les change. Dans ce cas, placer des liaisons sur le crochet du mode principal garantit que lorsque le mode est entré, les liaisons seront établies. Autrement dit, il garantit qu'ils seront effectués, mais il ne garantit pas que rien d'autre ne les modifie par la suite (par exemple, une autre fonction sur le même crochet, invoquée par la suite). N'oubliez pas que vous avez peu de contrôle sur ce qui est exécuté sur un hook et quand - à moins, bien sûr, que vous soyez sûr que seul votre propre code le gêne.

C'est la seule différence d'effet à laquelle je puisse penser. À vous de décider quand vous considérez cette différence comme un avantage de l'une ou l'autre approche. FWIW, en regardant mon propre code, je ne pense pas que je lie jamais des clés sur un crochet de mode.

A dessiné
la source
Merci. J'ai modifié la question pour, espérons-le, clarifier le fait que je ne crée pas de mode principal, en ajoutant simplement mes propres raccourcis clavier et le mode principal existant .
nispio
0

Votre dénomination est peu confuse (je pense que vous devriez supprimer mydans votre deuxième partie de la question).

Quoi qu'il en soit, en supposant que my-magical-keysc'est une fonction de personnalisation de l'utilisateur magical-mode, je vois un avantage évident. Il est facile de retirer (par remove-hook) le crochet en une seule fois.

Le deuxième avantage est de savoir à quoi servent les fonctions. Je veux dire qu'ils sont réutilisables. vous pouvez les accrocher à d'autres modes.

Éditer:

Comme l'a souligné @tarsius, la suppression du crochet ne rétablira pas le comportement d'origine et il peut être préférable de transformer la fonction en mode mineur.

kindahero
la source
Je personnalise un mode majeur hypothétique appelé my-magical-mode. Cependant, si l'utilisation du my-préfixe prête à confusion, je peux certainement modifier la question.
nispio
Oui, ce serait mieux, généralement (au moins comme je le vois dans la nature) my-est ajouté pour les fonctions utilisateur.
kindahero
1
D'accord. Je viens d'appliquer le my-afin que personne ne pense que je demandais comment configurer un mode réel appelé magical-mode(s'il existe).
nispio
1
Non, retirer le crochet ne restaurera pas les anciennes fixations. Du moins pas jusqu'à ce qu'Emacs soit redémarré, et je ne vois donc pas devoir commenter une seule ligne au lieu de quatre comme une grande amélioration.
tarsius
2
Quant au deuxième avantage que vous mentionnez: ici, il serait préférable de créer un mode mineur qui pourrait ensuite être activé pour divers modes majeurs et / ou seulement certains des tampons utilisant un mode majeur particulier.
tarsius