Evil:キーバインドをvimの方法でマップしますか?


13

私はEmacsバインディングのようevil-jump-to-tagC-]振る舞う、Evil関数を作成しようとしていM-.ます。

通常の動作はTagsファイルの閲覧には問題ありませんが、Slime slime-edit-definition、Elisps elisp-slime-nav-find-elisp-thing-at-point、Clojures cider-jump-to-varなどでも動作するようにしたいです...

これらのメジャーモードおよびその他の多くのモードでは、定義へのジャンプに相当するものがkeybindingにバインドされていM-.ます。

Evilモードで同じ動作を得るには、これらのすべてのモードでキーバインドをローカルにバインドする必要がありますか、またはキーバインドを取得してEmacsに、このキーが押されるたびにそのキーにバインドされた関数を使用するように指示することは可能ですか? Emacsモードで?


関連(より直接的なvimのようなアプローチ):emacs.stackexchange.com/q/12287/8283
idbrii

回答:


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、slime、goで試してみましたが、それらはすべて機能しています。


1
私が使用するものはよりシンプルで、完全にうまくいくようです:((define-key evil-normal-state-map (kbd "C-]") (kbd "\\ M-.")ここで "\"はにバインドされていますevil-execute-in-emacs-state)。
shosti 14年

@shosti:はい、これは少なくとも同様に動作するはずです。私はこのようにそれを試してみたが、2番目の間にスペースが含まれていませんでした\とM.
マーティン

3

のようなものを試してください

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

または、evil既にこのキーバインドを使用している場合は、次のようなことが必要になる場合があります。

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

これはC-]、現在のメジャーモードに応じて悪の振る舞いを維持したい場合、の振る舞いを完全にオーバーライドします。@ Tylerのソリューションは、M-.esle を呼び出すか実行するかを決定する関数を持つことができるため、より適切です。

これは役立ちますか?


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()(interactive)(evil-emacs-state)(call-interactively(key-binding(kbd "M-。")))(evil-normal-状態))
マーティン14年

私が言ったように、私は邪悪なキーマップを知りません。おそらく、より良い解決策は、evil-jump-to-tag定義されているキーマップを見つけて、そこで自分の関数に再バインドすることです。
タイラー14年

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

私は通常、悪をまったく使用しないため、調整が必要な場合があります(埋め込みコメントを参照)

また、キーバインドが押されるたびに動的に検索するのではなく、(たとえばモードフックで)バインディングを1回検索するのがよりクリーンなアプローチです。しかし、どの邪悪なフックを使用するのかわからないので、これは演習として残されています;)(そしてマイナーモードに使用する順序によって、またはそれらを動的に切り替える場合は間違っているかもしれません)


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スタイルのバインディングを許可するために定義したいくつかの関数と、任意のキーマップまたは任意のバインディング関数のいずれかを取る2つの一般的な関数を次に示します。これらの機能を要点に入れました。

(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-keyマクロuse-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-.")
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.