Evil: แผนที่ทำหน้าที่เป็นกลุ่ม


13

ฉันกำลังพยายามที่จะทำให้การทำงานของความชั่วร้ายevil-jump-to-tag, C-]ประพฤติเช่น Emacs M-.ผูกพัน

พฤติกรรมปกติดีสำหรับการเรียกดูไฟล์แท็ก แต่ฉันต้องการให้มันทำงานได้ดีกับ Slime's slime-edit-definition, Elisps ' elisp-slime-nav-find-elisp-thing-at-point, Clojures cider-jump-to-var, ฯลฯ ...

เหล่านี้โหมดที่สำคัญและอื่น ๆ M-.อีกมากมายได้ถูกผูกไว้เทียบเท่าบางส่วนของการกระโดดให้ละเอียดเพื่อปุ่มลัด

เพื่อให้มีพฤติกรรมแบบเดียวกันสำหรับโหมดความชั่วร้ายฉันจำเป็นต้องผูกปุ่มลัดไว้ในเครื่องสำหรับทุกโหมดเหล่านี้หรือเป็นไปได้ที่จะใช้ปุ่มลัดและบอกกับ Emacs ว่าเมื่อใดก็ตามที่กดปุ่มนี้ให้ใช้ฟังก์ชั่น อยู่ในโหมด Emacs?


ที่เกี่ยวข้อง (วิธีที่คล้ายเสียงเรียกร้องโดยตรงมากขึ้น): 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)

สิ่งนี้จะตั้งค่า evil-state เป็น "Emacs" เรียกใช้ฟังก์ชันที่ถูกผูกไว้กับ M- และเปลี่ยนกลับไปเป็นสถานะ emacs ก่อนหน้าในบัฟเฟอร์อื่น ฉันได้ลองกับ elisp, slime และ go และมันใช้ได้กับพวกมันทุกคน


1
สิ่งที่ฉันใช้นั้นง่ายกว่าและดูเหมือนจะใช้ได้ดีทั้งหมด: (define-key evil-normal-state-map (kbd "C-]") (kbd "\\ M-.")(โดยที่ "\" ถูกผูกไว้กับevil-execute-in-emacs-state)
shosti

@shosti: ใช่มันควรจะทำงานได้อย่างน้อยเช่นกัน ฉันได้ลองแบบนี้แล้ว แต่ไม่ได้รวมช่องว่างระหว่างตัวที่สอง \ และ M.
มาร์ติน

3

ลองสิ่งที่ชอบ

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

หรือถ้าevilใช้ปุ่มลัดนี้อยู่แล้วคุณอาจต้องทำอะไรบางอย่าง

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

สิ่งนี้จะแทนที่พฤติกรรมของC-]ถ้าคุณต้องการที่จะรักษาพฤติกรรมของความชั่วร้ายขึ้นอยู่กับโหมดหลักในปัจจุบันวิธีการแก้ปัญหาของM-.@Tyler มีความเหมาะสมมากขึ้นเพราะคุณสามารถมีฟังก์ชั่นที่ตัดสินใจว่าจะโทรหรือทำอะไรบางอย่าง

สิ่งนี้ช่วยได้ไหม?


2

ฉันไม่เข้าใจevilคีย์แมปของ แต่ฟังก์ชั่นต่อไปนี้จะทำสิ่งที่M-.ถูกผูกไว้ในขณะนี้:

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

การโยงสิ่งนี้เข้ากับevilkeymap ที่เหมาะสมควรทำในสิ่งที่คุณต้องการ อาจมี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) (การโทรแบบโต้ตอบ (การโยงคีย์ (kbd "M-."))) (evil-normal- รัฐ))
martin

ดังที่ฉันพูดฉันไม่ทราบว่าแป้นพิมพ์ชั่วร้าย บางทีทางออกที่ดีกว่าคือการหา keymap ที่evil-jump-to-tagกำหนดไว้และเชื่อมโยงไปยังฟังก์ชันของฉันอีกครั้ง
Tyler

2

โดยทั่วไปแล้วมันเป็นไปไม่ได้

เหตุผลก็คืออาจมีหลายแผนที่ที่กำหนดการเชื่อมโยงเดียวกันและไม่มีวิธีที่จะคิดออกโดยอัตโนมัติในสิ่งที่คุณต้องการ (ในตัวอย่างของคุณelisp-slime-nav-modeมันเป็นโหมดรอง) ดังนั้นวิธีการที่เชื่อถือได้เพียงวิธีเดียวคือให้คุณหาคำจำกัดความที่คุณต้องการอย่างแท้จริง

ที่กล่าวว่า ... มีแฮ็คที่เป็นไปได้ (ไม่เสมอไป ... ) ส่วนหนึ่งของสิ่งที่ทำให้มันยุ่งยากคือการรวมที่คุณต้องการทำการแมปอาจถูกหลอกลวงโดย keymap ที่ใช้งานที่ชั่วร้ายดังนั้นเพื่อให้ได้ผลผูกพันปัจจุบัน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-]"))

ปกติแล้วฉันจะไม่ใช้ความชั่วร้ายดังนั้นอาจจำเป็นต้องมีการปรับเปลี่ยน (ดูความคิดเห็นที่ฝังไว้)

นอกจากนี้วิธีการที่สะอาดกว่าคือการค้นหาการเชื่อมโยงหนึ่งครั้ง (ใน hook ของโหมดเป็นต้น) แทนที่จะค้นหาแบบไดนามิกทุกครั้งที่กดปุ่มลัด แต่ฉันไม่แน่ใจว่าจะใช้ตะขอตัวร้ายอะไรดังนั้นสิ่งนี้จึงเหลือไว้เป็นแบบฝึกหัด) (และขึ้นอยู่กับคำสั่งที่คุณใช้สำหรับโหมดรองของคุณหรือหากคุณสลับมันแบบไดนามิกอาจไม่ถูกต้อง)


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-definitionsเป็นฟังก์ชั่น binded ไปM-.ใน emacs C-h kที่คุณสามารถดูโดยใช้คำสั่ง


1

ฟังก์ชั่นปุ่มลัดสำหรับฟังก์ชั่น 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-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.