Zło: mapowanie skrótów w sposób vim?

13

Staram się, aby funkcję Zło evil-jump-to-tag, C-]zachowują się jak powiązanie Emacs M-..

Normalne zachowanie jest odpowiednie do przeglądania plików slime-edit-definitionTagów , ale chcę, aby działało również w przypadku Slime , Elisps elisp-slime-nav-find-elisp-thing-at-point, Clojures cider-jump-to-varitp.

Te główne tryby i wiele innych wiązały jakiś odpowiednik przeskakiwania do definicji z klawiszami M-..

Aby uzyskać takie samo zachowanie w trybie Zła, czy muszę powiązać przyporządkowanie klawiszy lokalnie dla każdego z tych trybów, czy też możliwe jest przypisanie skrótu klawiaturowego i poinformowanie Emacsa, że ​​za każdym razem, gdy ten klawisz zostanie naciśnięty, użyj funkcji powiązanej z tym klawiszem w trybie Emacsa?

jaskółka oknówka
źródło
Powiązane (bardziej bezpośrednie podejście podobne do vima): emacs.stackexchange.com/q/12287/8283
idbrii

Odpowiedzi:

10

Działa teraz dzięki twoim odpowiedziom:

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

Spowoduje to ustawienie stanu zła na „Emacs”, wywołanie funkcji powiązanej z M- i powrót do poprzedniego stanu emacs w drugim buforze. Próbowałem z elisp, śluzem i idź i działa na nich wszystkich.

jaskółka oknówka
źródło
1
To, czego używam, jest prostsze i wydaje się działać całkiem dobrze: (define-key evil-normal-state-map (kbd "C-]") (kbd "\\ M-.")(gdzie „\” jest związane evil-execute-in-emacs-state).
shosti
@shosti: Tak, to powinno przynajmniej działać. Próbowałem w ten sposób, ale nie uwzględniłem spacji między drugim \ a M.
martin
3

Spróbuj czegoś takiego

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

lub, jeśli eviljuż używasz tego skrótu klawiszowego, być może będziesz musiał zrobić coś takiego.

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

To całkowicie zastąpi zachowanie C-], jeśli chcesz zachować zachowanie zła w zależności od bieżącego trybu głównego, rozwiązanie @ Tylera jest bardziej odpowiednie, ponieważ możesz mieć funkcję, która decyduje, czy zadzwonić, M-.czy zrobić coś esle.

czy to pomaga?

Malabarba
źródło
2

Nie rozumiem evilmap klawiszy, ale następująca funkcja robi wszystko, co M-.jest obecnie wymagane:

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

Powiązanie tego z odpowiednią evilmapą klawiszy powinno robić, co chcesz. Może to być bardziej evilspecyficzny sposób.

evilwiąże się C-]w evil-motion-state-map, więc spróbuj:

(eval-after-load "evil-maps"
    '(define-key evil-motion-state-map "\C-]" 'my-tag-jump))
Tyler
źródło
I nie rozumiem, jak to może działać w ten sposób, ponieważ wiąże złego trybu M-.na evil-repeat-pop-next. Jeśli zmienisz swoją funkcję na: (defun my-tag-jump () (Interactive) (evil-emacs-state) (call-Interactive (bindowanie klawiszy (kbd „M-.”))) (Evil-normal- state))
martin
Jak powiedziałem, nie znam złych map klawiszy. Być może lepszym rozwiązaniem jest znalezienie mapy klawiszy, w której evil-jump-to-tagjest zdefiniowana, i ponowne powiązanie jej z moją funkcją.
Tyler
2

Zasadniczo nie jest to możliwe.

Powodem jest to, że może istnieć kilka map, które definiują to samo wiązanie, i nie ma sposobu, aby automatycznie ustalić, który z nich chcesz. (w twoim przykładzie elisp-slime-nav-modejest to taki niewielki tryb). Tak więc jedyne naprawdę niezawodne podejście polega na tym, aby dokładnie ustalić, jakiej definicji chcesz.

To powiedziawszy ... istnieje możliwość włamania (nie zawsze tam jest ...) Częścią tego, co sprawia, że ​​jest to trudne, jest to, że wiązanie, które chcesz odwzorować, jest potencjalnie już maskowane przez złą aktywną mapę klawiszy, więc uzyskanie bieżącego wiązania M-.jest bezużyteczny.

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

Zwykle w ogóle nie używam zła, więc mogą być potrzebne poprawki (patrz osadzone komentarze)

Bardziej czystym podejściem byłoby też sprawdzenie powiązań jeden raz (na przykład w trybie haka), zamiast dynamicznego wyszukiwania za każdym razem, gdy naciśnie się klawisz. Ale nie jestem pewien, jakiego złego haka użyć, więc pozostało to jako ćwiczenie;) (i w zależności od kolejności, w której używasz swoich mniejszych trybów lub jeśli przełączasz je dynamicznie, może to być niepoprawne)

Sigma
źródło
2

Akceptowane przez @severin rozwiązanie prawie działa dla mnie, ale gdy tag nie zostanie znaleziony, bufor nie wraca do normalnego trybu. Ta alternatywa działa dla mnie we wszystkich przypadkach:

(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
źródło
1

Myślę, że to najczystszy sposób

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

(a także dodaj każdą inną mapę, którą jesteś zainteresowany)

xref-find-definitionsjest funkcją powiązaną z M-.emacsem, jak widać za pomocą polecenia C-h k.

mookid
źródło
1

Niektóre funkcje klawiszy w stylu Vima.

Oto niektóre funkcje, które zdefiniowałem, aby umożliwić wiązanie w stylu vima na mapie globalnej i różnych stanach zła, a także dwie ogólne funkcje, które przyjmują dowolną mapę klucza lub dowolną funkcję wiązania. Umieściłem te funkcje w skrócie .

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

Zasadniczo lepiej jest używać tych funkcji tylko w przypadku powiązań w stylu makr klawiaturowych (takich jak przypadek użycia w pytaniu) i używania skrótów klawiszowych w stylu emacsa do wszystkiego innego.

notatki

  • bind-keyMakro z use-packagepakietu jest doskonałym i wszechstronnym funkcją przycisku wiążące.
  • Jeśli chcesz zastąpić jedno polecenie innym, możesz użyć poleceń mapowania Emacsa .
  • Jeśli używasz ich do zwykłych powiązań klawiszy, pamiętaj, że nie ma wersji „noremap”, więc jeśli powiązania w twojej definicji się zmienią, to również powiązania zdefiniowane przez użytkownika.

Powiązanie C-]z M-..

Należy zauważyć, że w normalnym-państwa, będziemy chcieli, aby wiązać się \M-.aby uzyskać dostęp do emacsowi wiążące, ponieważ wiąże normalnego stanu M-.do 'evil-repeat-pop-next. Wiązanie stanu normalnego można więc zdefiniować za pomocą:

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

lub (ponowne przypisanie dowolnego evil-jump-to-tagklawisza w stanie normalnym:

(nmap [remap evil-jump-to-tag] "\\ M-.")
pirokrastyka
źródło