Ác: bản đồ keybindings cách vim?


13

Tôi đang cố gắng để làm cho chức năng Evil evil-jump-to-tag, C-]hoạt động như ràng buộc Emacs M-..

Hành vi bình thường là tốt để duyệt các tệp Thẻ, nhưng tôi muốn nó cũng hoạt động với Slime slime-edit-definition, Elisps ' elisp-slime-nav-find-elisp-thing-at-point, Clojures cider-jump-to-var, v.v.

Các chế độ chính này và nhiều chế độ khác đã ràng buộc một số tương đương của bước nhảy đến định nghĩa cho liên kết phím M-..

Để có hành vi tương tự cho chế độ Ác ma, tôi cần phải liên kết một phím bấm cục bộ cho mọi chế độ này, hoặc có thể lấy một phím bấm và nói với Emacs, rằng bất cứ khi nào phím này được nhấn, hãy sử dụng chức năng bị ràng buộc cho phím đó trong chế độ Emacs?


Liên quan (một cách tiếp cận giống như vim trực tiếp hơn): emacs.stackexchange.com/q/12287/8283
idbrii

Câu trả lời:


10

Tôi đã làm cho nó hoạt động ngay bây giờ, nhờ câu trả lời của bạn:

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

Điều này sẽ đặt trạng thái ác thành "Emacs", gọi hàm bị ràng buộc với M-., Và thay đổi trở lại trạng thái emacs trước đó trong bộ đệm khác. Tôi đã thử nó với elisp, slime và đi và nó hoạt động cho tất cả chúng.


1
Những gì tôi sử dụng đơn giản hơn và dường như hoạt động hoàn toàn tốt: (define-key evil-normal-state-map (kbd "C-]") (kbd "\\ M-.")(trong đó "\" bị ràng buộc evil-execute-in-emacs-state).
shosti

@shosti: Vâng, cái này ít nhất cũng phải hoạt động. Tôi đã thử nó như thế này, nhưng không bao gồm khoảng trắng giữa giây thứ hai và M.
martin

3

Hãy thử một cái gì đó như

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

hoặc, nếu evilđã sử dụng keybind này, bạn có thể cần phải làm một cái gì đó như.

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

Điều này sẽ hoàn toàn ghi đè hành vi của C-], nếu bạn muốn giữ hành vi của kẻ ác tùy thuộc vào chế độ chính hiện tại, giải pháp của @ Tyler phù hợp hơn vì bạn có thể có một chức năng quyết định nên gọi M-.hay làm gì đó.

Không giúp đỡ à?


2

Tôi không hiểu evilkeymap của mình, nhưng chức năng sau đây sẽ làm bất cứ điều gì M-.bị ràng buộc vào lúc này:

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

Liên kết này với evilsơ đồ phím thích hợp sẽ làm những gì bạn muốn. Có thể có một evilcách cụ thể hơn để làm điều này.

evilliên kết C-]trong evil-motion-state-map, vì vậy hãy thử như sau:

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

Tôi không thấy làm thế nào điều này có thể hoạt động như thế này, bởi vì chế độ tà ác liên kết M-.với evil-repeat-pop-next. Nếu bạn thay đổi chức năng của mình thành: tiểu bang))
martin

Như tôi đã nói, tôi không biết keymap. Có lẽ giải pháp tốt hơn là tìm sơ đồ bàn phím evil-jump-to-tagđược xác định và gắn lại nó với chức năng của tôi ở đó.
Tyler

2

Nói chung, điều đó là không thể.

Lý do là có thể có một số bản đồ xác định cùng một ràng buộc và không có cách nào để tự động tìm ra cái nào bạn muốn. (trong ví dụ của bạn, elisp-slime-nav-modelà một chế độ nhỏ như vậy). Vì vậy, cách tiếp cận thực sự đáng tin cậy duy nhất là để bạn tìm ra chính xác định nghĩa bạn muốn.

Điều đó nói rằng ... có một khả năng hack (không phải lúc nào cũng có ...) Một phần trong những điều khiến nó khó hiểu là ràng buộc mà bạn muốn ánh xạ lại có khả năng bị che dấu bởi một sơ đồ hoạt động xấu, do đó có được ràng buộc hiện tại của M-.là vô dụng

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

Tôi thường không sử dụng cái ác nào cả, vì vậy có thể cần điều chỉnh (xem bình luận được nhúng)

Ngoài ra, một cách tiếp cận sạch hơn sẽ là tìm kiếm các liên kết một lần (ví dụ trong móc chế độ), thay vì tìm kiếm động mỗi khi nhấn phím. Nhưng tôi không chắc nên sử dụng hook hook ác nào, vì vậy đây là một bài tập;) (và tùy thuộc vào thứ tự bạn sử dụng cho các chế độ nhỏ của mình hoặc nếu bạn chuyển đổi chúng một cách linh hoạt, nó có thể không chính xác)


2

Giải pháp được chấp nhận bởi @severin gần như hoạt động với tôi, nhưng, khi không tìm thấy thẻ, bộ đệm không trở về chế độ bình thường. Sự thay thế này hoạt động với tôi trong mọi trường hợp:

(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

Tôi nghĩ rằng cách sạch nhất là

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

(và cũng thêm mọi bản đồ khác mà bạn quan tâm)

xref-find-definitionslà hàm được liên kết M-.trong emacs, như bạn có thể thấy bằng cách sử dụng lệnh C-h k.


1

Một số chức năng keybinding kiểu vim.

Dưới đây là một số chức năng tôi đã xác định để cho phép liên kết kiểu vim trong bản đồ toàn cầu và các trạng thái xấu khác nhau, cũng như hai chức năng chung có chức năng liên kết khóa tùy ý hoặc ánh xạ tùy ý. Tôi đã đặt các chức năng này trong một ý chính .

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

Nói chung, tốt hơn là chỉ sử dụng các chức năng này cho các ràng buộc kiểu bàn phím-macro (như trường hợp sử dụng trong câu hỏi) và sử dụng liên kết phím kiểu emacs cho mọi thứ khác.

ghi chú

  • Các bind-keyvĩ mô từ use-packagegói là một tuyệt vời và linh hoạt chức năng then chốt mang tính ràng buộc.
  • Nếu bạn muốn thay thế một lệnh bằng một lệnh khác, bạn có thể sử dụng các lệnh ánh xạ lại của Emacs .
  • Nếu bạn sử dụng chúng cho các ràng buộc khóa thông thường, hãy nhớ rằng không có phiên bản "noremap", vì vậy nếu các ràng buộc trong định nghĩa của bạn thay đổi, thì các ràng buộc do người dùng xác định cũng sẽ thay đổi.

Liên kết C-]với M-..

Lưu ý rằng ở trạng thái bình thường, bạn sẽ muốn liên kết \M-.để truy cập liên kết emacs, vì trạng thái bình thường liên kết M-.với 'evil-repeat-pop-next. Vì vậy, một ràng buộc trạng thái bình thường có thể được xác định với:

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

hoặc (đóng lại bất kỳ evil-jump-to-tagphím nào ở trạng thái bình thường:

(nmap [remap evil-jump-to-tag] "\\ M-.")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.