Comment remplacer les liaisons en mode majeur


38

Parfois, mes combinaisons de touches globales sont remplacées par un mode majeur. Un exemple simple est le paramètre suivant dans mon fichier init

(global-set-key (kbd "C-j") 'newline-and-indent)

Mais, ce qui est gênant, cette liaison est masquée par le mode majeur "Lisp Interaction", qui est le mode par défaut du tampon de travail.

Lorsque je me trouve dans une situation où un mode majeur (ou un mode mineur) masque ma liaison de clé globale, comment puis-je la récupérer?

Note: Ma question n'est pas « Comment puis - je lier C-jà newline-and-indent« ? Mode » dans » Lisp Interaction Je suis intéressé par une réponse beaucoup plus générale sur la façon de traiter les keymaps en conflit ou les associations de touches utilisateur qui sont masquées par un mode majeur / mineur.


Réponses:


39

Il existe également une approche de "raccourci" pour la même solution si vous ne souhaitez pas définir votre propre mode mineur (dont je parle dans ma première réponse).

Vous pouvez installer le use-packagepackage disponible à partir Melpa et utiliser bind-key*ou bind-keys*macro qui fait partie du bind-keypaquet qui est livré avec use-package.

De la documentation de bind-key.el:

;; If you want the keybinding to override all minor modes that may also bind
;; the same key, use the `bind-key*' form:
;;
;;   (bind-key* "<C-return>" 'other-window)

;; To bind multiple keys in a `bind-key*' way (to be sure that your bindings
;; will not be overridden by other modes), you may use `bind-keys*' macro:
;;
;;    (bind-keys*
;;     ("C-o" . other-window)
;;     ("C-M-n" . forward-page)
;;     ("C-M-p" . backward-page))

Si vous êtes curieux, sachez qu’il s’agit d’un mode mineur en coulisse. Il adopte une approche différente des conflits avec d’autres modes mineurs, en utilisant emulation-mode-map-alistspour appliquer la priorité.
phils

J'ai marqué cela comme la réponse à cause de sa simplicité. Il s’agit essentiellement de la même chose que cette réponse , mais il effectue commodément la majeure partie du travail pour vous dans les coulisses.
nispio

@ nispio Vous avez raison. D'après mon expérience, la seule différence est la méthode utilisée pour faire en sorte que les liaisons de mode mineur aient priorité sur les autres modes globalement. Mais l’avantage de l’autre approche (d’avoir votre propre mode mineur) est que vous pouvez le désactiver momentanément pour essayer les liaisons emacs d’origine si vous en aviez besoin (j’ai eu besoin de le faire quelques fois).
Kaushal Modi

1
Ajoutez (bind-key* "C-M-&" 'override-global-mode)à votre init, et vous pouvez généralement obtenir les liaisons de votre chemin rapidement si vous en avez besoin. Étant donné qu’il override-global-modene s’agit pas d’un mode mineur «global», vous devrez toujours le désactiver, tampon par tampon. Donc, si vous désactivez fréquemment les clés de substitution globales, cette solution n’est pas pratique.
nispio

25

Vous pouvez définir votre propre mode mineur et sa carte de touches et faire en sorte que ceux-ci remplacent tous les autres modes (mineur + majeur). C'est exactement pourquoi j'ai choisi d'écrire mon propre mode mineur.

Étapes à suivre pour que vos liaisons de clé remplacent toutes les liaisons:

  • Définissez votre propre mode mineur et votre carte de touches comme indiqué ci-dessous.
  • Activer votre mode mineur globalement
  • (define-key my-mode-map (kbd "C-j") #'newline-and-indent)

De même, les autres raccourcis clavier définis dans votre mode mineur remplaceront ceux des autres modes.

Je recommande fortement de lire le billet de blog de Christopher Wellons sur la façon d'écrire un mode mineur. Ce blog, ajouté à la contrariété de devoir définir plusieurs raccourcis clavier nildans plusieurs modes majeurs et mineurs, m'a incité à écrire mon propre mode mineur.

La meilleure partie de cette approche est que, lorsque vous voulez vérifier ce que les raccourcis-clés font dans la configuration par défaut d’emacs, vous désactivez simplement le mode mineur; vous le rallumez et vous retrouvez vos raccourcis clavier personnalisés.

;; Main use is to have my key bindings have the highest priority
;; https://github.com/kaushalmodi/.emacs.d/blob/master/elisp/modi-mode.el

(defvar my-mode-map (make-sparse-keymap)
  "Keymap for `my-mode'.")

;;;###autoload
(define-minor-mode my-mode
  "A minor mode so that my key settings override annoying major modes."
  ;; If init-value is not set to t, this mode does not get enabled in
  ;; `fundamental-mode' buffers even after doing \"(global-my-mode 1)\".
  ;; More info: http://emacs.stackexchange.com/q/16693/115
  :init-value t
  :lighter " my-mode"
  :keymap my-mode-map)

;;;###autoload
(define-globalized-minor-mode global-my-mode my-mode my-mode)

;; https://github.com/jwiegley/use-package/blob/master/bind-key.el
;; The keymaps in `emulation-mode-map-alists' take precedence over
;; `minor-mode-map-alist'
(add-to-list 'emulation-mode-map-alists `((my-mode . ,my-mode-map)))

;; Turn off the minor mode in the minibuffer
(defun turn-off-my-mode ()
  "Turn off my-mode."
  (my-mode -1))
(add-hook 'minibuffer-setup-hook #'turn-off-my-mode)

(provide 'my-mode)

;; Minor mode tutorial: http://nullprogram.com/blog/2013/02/06/

5

Pour qu'une liaison globale remplace une liaison en mode majeur, définissez simplement la liaison sur nildans le mode majeur:

(define-key my-major-mode-map (kbd "C-j") nil)

Il n’est pas possible d’avoir la liaison globale prioritaire sur tous les modes en général (sinon il ne servirait à rien d’avoir des modes majeurs), mais vous pouvez le contourner en créant votre propre mode mineur avec vos liaisons les plus importantes. Dans ce cas, vous auriez au moins préséance sur la plupart des modes (mais pas nécessairement sur tous).


Est-ce que cela fonctionnera pour n'importe quel mode majeur arbitraire? En d'autres termes, si j'installe un mode majeur appelé "foo-mode", je peux insérer (define-key foo-mode (kbd "C-j") nil)mon fichier .emacs dans l'espoir que cela fonctionne?
nispio

En fait, vous voudrez que ce soit le cas foo-mode-map(mon exemple de réponse était mauvais), mais oui, cela désactivera la liaison de clé dans le mode majeur, de sorte que la liaison de clé globale sera utilisée à la place (à moins qu'un mode mineur différent ne l'utilise).
Shosti

Est-il assez universel que le keymap foo-modesoit appelé foo-mode-map?
nispio

@nispio oui, c'est vrai pour la grande majorité des modes (bien qu'il y ait quelques voyous là-bas).
Shosti

0

Vous pouvez utiliser ces macros:

(defmacro expose-global-keybinding (binding map)
  `(define-key ,map ,binding (lookup-key (current-global-map) ,binding)))

(defmacro expose-bindings (map bindings)
  `(dolist (bnd ,bindings)
     (expose-global-keybinding (kbd bnd) ,map)))

EDIT :

Vérifiez l'exemple ci-dessous:

Si le clavier X supprime votre liaison globale Y, vous écrivez:

(expose-bindings X '("Y"))

Et alors la dérogation sera «annulée».


votre macro profite de l’utilisation de la citation précédente: `(define-key, map, binding (lookup-key (reliée à la carte actuelle), binding))
Sigma le

Pouvez-vous commenter ce que fait la macro et comment l'utiliser? Ce n'est pas clair pour moi d'après le code.
Nispio

La première macro ne fait que rechercher la clé dans la carte globale et attribuer le résultat à la other map, exposant ainsi la liaison de la carte globale par le biais de other map. La seconde vous permet simplement d’appliquer l’ancien à une liste de liaisons.
Renan Ranelli

Désolé si je suis dense, mais je ne comprends toujours pas complètement l'utilisation. Dois-je définir mon propre keymap global spécial? A-t-il besoin d'appartenir à un mode mineur? Est-ce que je expose-bindingscommence par exécuter et ensuite, je lie globalement ces clés aux commandes que je veux? Vous pourriez peut-être montrer un exemple de ce que je pourrais mettre dans mon fichier init pour que cela fonctionne.
nispio

2
Notez que ces noms de macro sont des noms incorrects. Ils ne "dévoilent" pas la liaison globale, mais ils dupliquent plutôt la liaison globale. Si la liaison globale réelle change, ces copies en double ne le seront pas.
phils
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.