Mal: mapper les raccourcis clavier à la manière de Vim?

13

J'essaye de faire la fonction Evil evil-jump-to-tag, C-]se comporter comme la liaison Emacs M-..

Le comportement normal convient pour la navigation dans les fichiers de balises, mais je veux que cela fonctionne également pour Slime slime-edit-definition, Elisps elisp-slime-nav-find-elisp-thing-at-point, Clojures cider-jump-to-var, etc.

Ces modes majeurs et bien d'autres ont lié un équivalent de saut à la définition au raccourci clavier M-..

Pour obtenir le même comportement pour le mode Evil, dois-je lier une liaison de touches localement pour chacun de ces modes, ou est-il possible de prendre une liaison de touches et de dire à Emacs que chaque fois que cette touche est enfoncée, utilisez la fonction liée à cette touche en mode Emacs?

Martin
la source
Connexes (une approche plus directe de type vim): emacs.stackexchange.com/q/12287/8283
idbrii

Réponses:

10

Je le fais fonctionner maintenant, grâce à vos réponses:

(defun my-jump-to-tag ()
  (interactive)
  (evil-emacs-state)
  (call-interactively (key-binding (kbd "M-.")))
  (evil-change-to-previous-state (other-buffer))
  (evil-change-to-previous-state (current-buffer)))

(define-key evil-normal-state-map (kbd "C-]") 'my-jump-to-tag)

Cela définira evil-state sur "Emacs", appellera la fonction liée à M-., Et reviendra à l'état emacs précédent dans l'autre tampon. Je l'ai essayé avec elisp, slime and go et ça marche pour tous.

Martin
la source
1
Ce que j'utilise est plus simple et semble fonctionner parfaitement: (define-key evil-normal-state-map (kbd "C-]") (kbd "\\ M-.")(où "\" est lié à evil-execute-in-emacs-state).
shosti
@shosti: Oui, cela devrait fonctionner au moins aussi. Je l'ai essayé comme ça, mais je n'ai pas inclus l'espace entre le second \ et M.
martin
3

Essayez quelque chose comme

(global-set-key "\C-]" "\M-.")

ou, s'il evilutilise déjà ce raccourci clavier, vous devrez peut-être faire quelque chose comme.

(define-key evil-mode-map "\C-]" "\M-.")

Cela remplacera complètement le comportement de C-], si vous voulez garder le comportement du mal en fonction du mode majeur actuel, la solution de @ Tyler est plus appropriée car vous pouvez avoir une fonction qui décide d'appeler M-.ou de faire quelque chose d'esle.

est-ce que cela aide?

Malabarba
la source
2

Je ne comprends pas evilles keymaps de, mais la fonction suivante fait tout ce qui M-.est lié pour le moment:

(defun my-tag-jump ()
    (interactive)
    (call-interactively (key-binding (kbd "M-."))))

Le evillier à la table de touches appropriée devrait faire ce que vous voulez. Il peut y avoir un moyen plus evilspécifique de le faire.

evilse fixe C-]à evil-motion-state-map, donc les opérations suivantes:

(eval-after-load "evil-maps"
    '(define-key evil-motion-state-map "\C-]" 'my-tag-jump))
Tyler
la source
Je ne vois pas comment cela pourrait fonctionner comme ça, car le mode diabolique se lie M-.à evil-repeat-pop-next. Si vous changez votre fonction en ceci: (defun my-tag-jump () (interactive) (evil-emacs-state) (call-interactively (key-binding (kbd "M-.")))) Evil-normal- état))
martin
Comme je l'ai dit, je ne connais pas les keymaps maléfiques. La meilleure solution est peut-être de trouver le clavier où evil-jump-to-tagest défini et de le lier à ma fonction là-bas.
Tyler
2

En général, ce n'est pas possible.

La raison en est qu'il peut y avoir plusieurs cartes qui définissent la même liaison, et il n'y a aucun moyen de déterminer automatiquement celle que vous souhaitez. (dans votre exemple, elisp-slime-nav-modec'est un mode si mineur). La seule approche vraiment fiable consiste donc à déterminer exactement quelle définition vous souhaitez.

Cela dit ... il y a un piratage possible (n'est-ce pas toujours le cas ...) Une partie de ce qui le rend difficile est que la liaison que vous souhaitez remapper est potentiellement déjà masquée par une mauvaise carte de touches active, donc obtenir la liaison actuelle de M-.est inutile.

(defun lookup-no-evil (key)
  ;; excluding evil maps from the lookup. not sure if 
  ;; anything more than evail-normal-state-map is needed
  (let* ((evil-maps (list evil-normal-state-map))
         (bindings
          (remq nil
                (mapcar
                 (lambda (map)
                   (unless (memq map evil-maps)
                     (lookup-key map key)))
                 (current-active-maps)))))
    (when bindings
      ;; let's assume the first one is the right one. 
      ;; Given that minor modes are at the beginning 
      ;; (although this is *not* documented so should not 
      ;; be relied upon), it might be what we would have 
      ;;without evil-mode indeed
      (car bindings))))

(defmacro evil-remap (from to)
  ;; assuming that we want to put it in the normal-state map.
  ;; not sure about that
  `(define-key evil-normal-state-map ,to
       (lambda ()
         (interactive)
         (call-interactively (lookup-no-evil ,from)))))

(evil-remap (kbd "M-.") (kbd "C-]"))

Normalement, je n'utilise pas du tout le mal, donc il pourrait y avoir des ajustements nécessaires (voir les commentaires intégrés)

En outre, une approche plus propre consisterait à rechercher les liaisons une fois (dans un crochet de mode par exemple), au lieu de rechercher dynamiquement chaque fois que la liaison de touches est enfoncée. Mais je ne sais pas quel mauvais crochet utiliser, donc cela reste un exercice;) (et selon l'ordre que vous utilisez pour vos modes mineurs, ou si vous les basculez dynamiquement, cela pourrait être incorrect)

Sigma
la source
2

La solution acceptée par @severin fonctionne presque pour moi, mais, lorsque la balise n'est pas trouvée, le tampon ne revient pas en mode normal. Cette alternative fonctionne pour moi dans tous les cas:

(defun my-jump-to-tag ()
    (interactive)
    (evil-execute-in-emacs-state)
    (call-interactively (key-binding (kbd "M-."))))
(define-key evil-normal-state-map (kbd "C-]") 'my-jump-to-tag)
Zak King
la source
1

Je pense que la façon la plus propre est

(define-key evil-normal-state-map (kbd "M-.") 'xref-find-definitions)

(et ajoutez également toutes les autres cartes qui vous intéressent)

xref-find-definitionsest la fonction liée à M-.emacs, comme vous pouvez le voir à l'aide de la commande C-h k.

mookid
la source
1

Certaines fonctions de raccourci clavier de style vim.

Voici quelques fonctions que j'ai définies pour permettre la liaison de style vim dans la carte globale et divers états malveillants, ainsi que deux fonctions générales qui prennent soit une carte-clé arbitraire soit une fonction de liaison arbitraire. J'ai mis ces fonctions dans un sens .

(defun kbd+ (keyrep &optional need-vector)
  (if (vectorp keyrep) keyrep (edmacro-parse-keys keyrep need-vector)))

(defun gmap (keyrep defstr)
  "Vim-style global keybinding. Uses the `global-set-key' binding function."
  (global-set-key (kbd+ keyrep) (edmacro-parse-keys defstr t)))

(defun fmap (keybind-fn keyrep defstr)
  "Vim-style keybinding using the key binding function KEYBIND-FN."
  (call keybind-fn (kbd+ keyrep) (edmacro-parse-keys defstr t)))

(defun xmap (keymap keyrep defstr)
  "Vim-style keybinding in KEYMAP. Uses the `define-key' binding function."
  (define-key keymap (kbd+ keyrep) (edmacro-parse-keys defstr t)))

(defun nmap (keyrep defstr) "Vim-style keybinding for `evil-normal-state.' Uses the `define-key' binding function."
      (xmap evil-normal-state-map keyrep defstr))
(defun imap (keyrep defstr) "Vim-style keybinding for `evil-insert-state'. Uses the `define-key' binding function."
      (xmap evil-insert-state-map keyrep defstr))
(defun vmap (keyrep defstr) "Vim-style keybinding for `evil-visual-state'. Uses the `define-key' binding function."
      (xmap evil-visual-state-map keyrep defstr))
(defun mmap (keyrep defstr) "Vim-style keybinding for `evil-motion-state'. Uses the `define-key' binding function."
      (xmap evil-motion-state-map keyrep defstr))

En général, il est préférable de n'utiliser ces fonctions que pour les liaisons de style clavier-macro (comme le cas d'utilisation de la question) et d'utiliser le raccourci clavier de type emacs pour tout le reste.

Remarques

  • La bind-keymacro du use-packagepackage est une fonction de liaison de touches excellente et polyvalente.
  • Si vous souhaitez remplacer une commande par une autre, vous pouvez utiliser les commandes de remappage d' Emacs .
  • Si vous les utilisez pour des raccourcis clavier réguliers, gardez à l'esprit qu'il n'y a pas de versions "noremap", donc si les liaisons dans votre définition changent, vos liaisons définies par l'utilisateur le seront aussi.

Reliure C-]à M-..

Notez qu'en état normal, vous voudrez vous lier à \M-.pour accéder à la liaison emacs, car l'état normal se lie M-.à 'evil-repeat-pop-next. Ainsi, une liaison à l'état normal peut être définie avec:

(nmap "C-]" "\\ M-.")

ou (reliant n'importe quelle evil-jump-to-tagclé à l'état normal:

(nmap [remap evil-jump-to-tag] "\\ M-.")
pyrocrastie
la source