邪恶:以vim方式映射键盘绑定?


13

我试图使Evil函数evil-jump-to-tagC-]行为像Emacs绑定M-.

正常行为适合浏览标签文件,但我希望它也适用于Slime slime-edit-definition,Elisps elisp-slime-nav-find-elisp-thing-at-point,Clojures cider-jump-to-var等。

这些主要模式以及更多其他模式已经将等效的跳转绑定绑定到了键绑定上M-.

为了在Evil模式下获得相同的行为,我是否需要为每种模式本地绑定一个键绑定,或者是否可以进行一个键绑定并告诉Emacs,每当按下此键时,请使用对该键绑定的功能在Emacs模式下?


相关(更直接的类似于vim的方法):emacs.stackexchange.com/q/12287/8283
idbrii,2015年

Answers:


10

多亏您的回答,我现在可以正常工作了:

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

这会将邪恶状态设置为“ Emacs”,调用绑定到M-。的函数,然后在另一个缓冲区中更改回先前的emacs状态。我已经用elisp,slim and go尝试过,它对所有这些都有效。


1
我使用的是更简单的方法,并且似乎完全可以正常工作:((define-key evil-normal-state-map (kbd "C-]") (kbd "\\ M-.")其中“ \”绑定到evil-execute-in-emacs-state)。
shosti 2014年

@shosti:是的,这至少也应该起作用。我已经尝试过这种方法,但是没有包括第二个\和M之间的空格
马丁

3

尝试类似

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

或者,如果evil已经使用此键绑定,则可能需要执行类似操作。

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

C-]如果要根据当前的主模式保持邪恶的行为,这将完全覆盖的行为,@ Tyler的解决方案更为合适,因为您可以使用一个函数来决定是否调用M-.或执行某项操作。

这有帮助吗?


2

我不了解evil的键盘映射,但以下功能目前无法执行任何M-.操作:

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

将此绑定到适当的evil键盘映射应该做您想要的。可能有更evil特定的方法来执行此操作。

evil结合C-]evil-motion-state-map,所以请尝试以下操作:

(eval-after-load "evil-maps"
    '(define-key evil-motion-state-map "\C-]" 'my-tag-jump))

我看不到它怎么能这样工作,因为邪恶模式绑定M-.evil-repeat-pop-next。如果您将函数更改为:(defun my-tag-jump()(交互式)(evil-emacs-state)(交互式调用(key-binding(kbd“ M-。”)))(evil-normal-州))
马丁

如我所说,我不了解邪恶的键盘映射。也许更好的解决方案是在evil-jump-to-tag定义的位置找到键盘映射,然后将其重新绑定到我的函数中。
泰勒

2

通常,这是不可能的。

原因是可能有多个映射定义了相同的绑定,并且无法自动找出想要的映射。(在您的示例中,elisp-slime-nav-mode是次要模式)。因此,唯一真正可靠的方法是让您准确确定所需的定义。

就是说...有可能被黑客入侵(并不总是存在...)棘手的是,您要重新映射的绑定可能已经被邪恶的活动键映射掩盖了,因此获取当前的绑定M-.是没有用的。

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

我通常根本不使用邪恶,因此可能需要进行调整(请参阅嵌入式注释)

同样,一种更干净的方法是一次查找绑定(例如在模式挂钩中),而不是每次按下键绑定时都动态查找。但是我不确定要使用哪个邪恶的钩子,因此请留作练习;)(并且取决于次要模式的使用顺序,或者如果您动态切换它们,则可能不正确)


2

@severin接受的解决方案几乎对我有用,但是,如果找不到该标记,则缓冲区不会返回正常模式。在所有情况下,此替代方法都对我有效:

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

1

我认为最干净的方法是

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

(并添加您感兴趣的所有其他地图)

xref-find-definitionsM-.emacs中绑定的功能,如使用命令所示C-h k


1

一些vim样式的键绑定函数。

我定义了一些函数,以允许在全局映射和各种邪恶状态中进行vim样式的绑定,以及两个采用任意键映射或任意绑定函数的通用函数。我已将这些功能归纳要点

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

通常,最好仅将这些功能用于键盘宏样式的绑定(如问题中的用例),而对其他所有内容使用emacs样式的键绑定。

笔记

  • 程序包中的bind-keyuse-package是出色的通用键绑定功能。
  • 如果要将一个命令替换为另一个命令,则可以使用Emacs的重新映射命令
  • 如果确实将它们用于常规键绑定,请记住没有“ noremap”版本,因此,如果定义中的绑定发生更改,那么用户定义的绑定也会更改。

绑定C-]M-.

请注意,在正常状态下,您将需要绑定到\M-.以访问emacs绑定,因为正常状态下会绑定M-.'evil-repeat-pop-next。因此,可以使用以下方式定义常态绑定:

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

或(重新绑定evil-jump-to-tag处于正常状态的任何键:

(nmap [remap evil-jump-to-tag] "\\ M-.")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.