แนวทางปฏิบัติที่ดีที่สุดของ Evil Mode? [ปิด]


104

ฉันใช้ Vim เป็นตัวแก้ไขหลักมาหลายปีแล้วและลองใช้ Emacs หลายครั้งในช่วงเวลานั้น จากนั้นฉันก็ค้นพบEvilและตัดสินใจว่ามันตรงกับความต้องการของฉันสำหรับการเคลื่อนไหวที่รวดเร็วดีพอที่ฉันจะไปยัง Emacs ได้ในที่สุด

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

คำตอบ:


71

ฉันใช้ vim ที่ปรับแต่งเองอย่างมากและตอนนี้ใช้ emac ที่ปรับแต่งได้มากขึ้น ฉันคิดว่าคุณจะพบทุกอินสแตนซ์ของการแมปคีย์ในไฟล์กำหนดค่าการแมปคีย์ของฉันhttps://github.com/mbriggs/.emacs.d-oldv2/blob/master/init/init-keymaps.el

โปรดทราบว่าฉันกำลังย้อนกลับไปในสิ่งที่ผู้ใช้ emacs ตัวจริงจะมองว่านอกรีตดังนั้น YMMV หากคุณต้องการเรียนรู้ emac "ของจริง" (ฉันไม่ชอบจริงๆ)

สิ่งหนึ่งที่ฉันอยากแนะนำให้กับอดีตนักต้มตุ๋นคือสิ่งนี้

;;; esc quits
(defun minibuffer-keyboard-quit ()
  "Abort recursive edit.
In Delete Selection mode, if the mark is active, just deactivate it;
then it takes a second \\[keyboard-quit] to abort the minibuffer."
  (interactive)
  (if (and delete-selection-mode transient-mark-mode mark-active)
      (setq deactivate-mark  t)
    (when (get-buffer "*Completions*") (delete-windows-on "*Completions*"))
    (abort-recursive-edit)))
(define-key evil-normal-state-map [escape] 'keyboard-quit)
(define-key evil-visual-state-map [escape] 'keyboard-quit)
(define-key minibuffer-local-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-ns-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-completion-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-must-match-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-isearch-map [escape] 'minibuffer-keyboard-quit)

เพื่อให้ esc ออกจากทุกอย่างจริง ๆ (เช่นรอการแจ้งเตือนในมินิบัฟเฟอร์)


7
สามารถดูคำจำกัดความของมินิบัฟเฟอร์ - คีย์บอร์ด - เลิกได้ที่นี่: github.com/davvil/.emacs.d/blob/master/init.el
Adam Bell

1
@ อดัมขอโทษด้วย>.> ฉันติดตั้งหลายอย่างบางครั้งฉันใช้ฟังก์ชันที่ฉันคิดว่ามีในตัว แต่จริงๆแล้วมาจากที่อื่น
Matt Briggs

3
ฉันพบว่าสิ่งนี้ไม่ได้ผลสำหรับฉัน ฉันใช้ Emacs 24.4 ล่าสุดมีใครเคยสัมผัสเหมือนกันไหม
Dzung Nguyen

1
ลิงค์เสีย ฉันเชื่อว่านี่คืออันใหม่: github.com/mbriggs/.emacs.d/blob/master/config/keybinds.el
Sean Leather

1
@SeanLeather อัปเดตคำตอบสำหรับลิงก์ที่ใช้งานได้
Christopher Bottoms

34

ในฐานะคนที่มาจาก emacs ลองใช้ vim และตระหนักว่ามีหลายสิ่งหลายอย่างที่จะได้รับฉันทำการทดลองมากมายเมื่อฉันเริ่มใช้ความชั่วร้ายครั้งแรก ในขณะที่สิ่งต่อไปนี้เป็นที่ถกเถียงกันอยู่ฉันต้องการเก็บคีย์ emacs ที่ใช้กันอย่างแพร่หลายในเทอร์มินัล firefox โกโก้ ฯลฯ ... แต่ไม่ต้องการสูญเสียความสามารถในการแก้ไขเป็นกลุ่ม ฉันตัดสินใจที่จะเชื่อมโยงคีย์ต่อไปนี้ใน. emac ของฉันใหม่:

(define-key evil-normal-state-map "\C-e" 'evil-end-of-line)
(define-key evil-insert-state-map "\C-e" 'end-of-line)
(define-key evil-visual-state-map "\C-e" 'evil-end-of-line)
(define-key evil-motion-state-map "\C-e" 'evil-end-of-line)
(define-key evil-normal-state-map "\C-f" 'evil-forward-char)
(define-key evil-insert-state-map "\C-f" 'evil-forward-char)
(define-key evil-insert-state-map "\C-f" 'evil-forward-char)
(define-key evil-normal-state-map "\C-b" 'evil-backward-char)
(define-key evil-insert-state-map "\C-b" 'evil-backward-char)
(define-key evil-visual-state-map "\C-b" 'evil-backward-char)
(define-key evil-normal-state-map "\C-d" 'evil-delete-char)
(define-key evil-insert-state-map "\C-d" 'evil-delete-char)
(define-key evil-visual-state-map "\C-d" 'evil-delete-char)
(define-key evil-normal-state-map "\C-n" 'evil-next-line)
(define-key evil-insert-state-map "\C-n" 'evil-next-line)
(define-key evil-visual-state-map "\C-n" 'evil-next-line)
(define-key evil-normal-state-map "\C-p" 'evil-previous-line)
(define-key evil-insert-state-map "\C-p" 'evil-previous-line)
(define-key evil-visual-state-map "\C-p" 'evil-previous-line)
(define-key evil-normal-state-map "\C-w" 'evil-delete)
(define-key evil-insert-state-map "\C-w" 'evil-delete)
(define-key evil-visual-state-map "\C-w" 'evil-delete)
(define-key evil-normal-state-map "\C-y" 'yank)
(define-key evil-insert-state-map "\C-y" 'yank)
(define-key evil-visual-state-map "\C-y" 'yank)
(define-key evil-normal-state-map "\C-k" 'kill-line)
(define-key evil-insert-state-map "\C-k" 'kill-line)
(define-key evil-visual-state-map "\C-k" 'kill-line)
(define-key evil-normal-state-map "Q" 'call-last-kbd-macro)
(define-key evil-visual-state-map "Q" 'call-last-kbd-macro)
(define-key evil-normal-state-map (kbd "TAB") 'evil-undefine)

(defun evil-undefine ()
 (interactive)
 (let (evil-mode-map-alist)
   (call-interactively (key-binding (this-command-keys)))))

น่าเสียดายที่สิ่งเหล่านี้ทับซ้อนกับการดำเนินการเป็นกลุ่ม "เลื่อนขึ้นหรือลงหนึ่งหน้าจอ" อย่างไรก็ตามฉันรู้สึกสบายใจที่จะใช้สิ่งต่อไปนี้แทน:

(define-key evil-normal-state-map (kbd "DEL") (lambda ()
                    (interactive)
                    (previous-line 10)
                    (evil-scroll-line-up 10)
                    ))

(define-key evil-normal-state-map (kbd "=") (lambda ()
                      (interactive)
                      (next-line 10)
                      (evil-scroll-line-down 10)
                      ))

นอกจากนี้หากคุณมาจากกลุ่มและต้องการเส้นทางที่รวดเร็วจากการแทรกไปยังโหมดปกติโดยใช้ "jk" (หรือการผสม 2 จังหวะอื่น ๆ ) วิธีที่ดีที่สุดคือคัดลอกข้อความจากhttp://www.emacswiki.org/ emacs / download / key-chord.elแล้ววางลงใน ~ / .emacs.d / key-chord.el ของคุณ จากนั้นเพิ่มสิ่งต่อไปนี้ใน. emac ของคุณ:

;load a file named key-chord.el from some directory in the load-path (e.g. "~/.emacs.d")
(require 'key-chord)
(key-chord-mode 1)
(key-chord-define-global "jk" 'evil-normal-state)

นอกจากนี้หากคุณมาจากกลุ่มและคุณคิดว่าการคัดลอกไปยังคลิปบอร์ดใน emacs นั้นไม่ดีคุณอาจพูดถูก อย่างไรก็ตามคุณอาจพบว่ามีประโยชน์ต่อไปนี้หลังจากเรียกใช้ sudo apt-get install xsel:

(defun copy-to-clipboard ()
  (interactive)
  (if (display-graphic-p)
      (progn
        (message "Yanked region to x-clipboard!")
        (call-interactively 'clipboard-kill-ring-save)
        )
    (if (region-active-p)
        (progn
          (shell-command-on-region (region-beginning) (region-end) "xsel -i -b")
          (message "Yanked region to clipboard!")
          (deactivate-mark))
      (message "No region active; can't yank to clipboard!")))
  )

(evil-define-command paste-from-clipboard()
  (if (display-graphic-p)
      (progn
        (clipboard-yank)
        (message "graphics active")
        )
    (insert (shell-command-to-string "xsel -o -b"))
    )
  )

(global-set-key [f8] 'copy-to-clipboard)
(global-set-key [f9] 'paste-from-clipboard)

เห็นได้ชัดว่าคุณจะต้องตัดสินใจด้วยตัวเองว่าการเปลี่ยนแปลงที่ขัดแย้งเหล่านี้คุ้มค่าหรือไม่ แต่บางทีการเปลี่ยนแปลงพื้นฐานเหล่านี้อาจเป็นแรงบันดาลใจให้คุณ

สำหรับการใช้งานฟังก์ชั่นที่ยอดเยี่ยมอื่น ๆ เช่นลบและวางลบโดยไม่ต้องคัดลอกไปยังคลิปบอร์ดการเคลื่อนไหว 4x / 16x ที่มีประสิทธิภาพการใช้การนับเพื่อวางข้อกำหนดการลงทะเบียนการตั้งค่าแท็บที่ใช้งานได้จริงสำหรับ c / c ++ และอื่น ๆ คุณสามารถตรวจสอบได้ ใช้. emacs, init.el, my-keymaps.el และ my-functions.el แบบเต็มบน git ของฉันได้ที่https://github.com/Russell91/emacs


2
ทั้งหมดนี้ยอดเยี่ยมมากฉันได้เพิ่มบางส่วนใน wikemacs: wikemacs.org/index.php/Evil#Configuration
Ehvince

ฉันเข้าใจความประสงค์ของคุณที่จะนำนิสัยของคุณกลับมาใช้ใหม่จากอีแมค สำหรับการทำงานใน Firefox ฉันขอแนะนำให้ลองใช้ Vimperator addon ซึ่งจะนำฟังก์ชั่นการใช้งานมากมายมาสู่การท่องเว็บของคุณ อย่างไรก็ตามมันกำลังใช้คำสั่ง vim movement ตามค่าเริ่มต้น (ตามกรณีของlesscommand และอื่น ๆ )
ม.ค. Vlcinsky

เช่นเดียวกับคุณฉันไม่ชอบการผูกความชั่วร้ายในโหมดแทรกสถานะดังนั้นฉันเพียงแค่เชื่อมต่อ "i" ในแผนที่สถานะปกติเป็น "evil-emacs-state
user49117

แทนที่จะแทนที่แป้นพิมพ์ของevilฉันฉันลบมันออกดังนั้นมันจึงกลับไปที่การตั้งค่าแป้นพิมพ์ของ(dolist (m (list evil-normal-state-map evil-motion-state-map evil-insert-state-map)) (define-key m "\C-e" 'nil))
Bach Lien

30

ฉันยังเคยเป็น Viper / ผู้ใช้ Vimpulse มีขนาดใหญ่ปริมาณของการกำหนดค่า จากนั้นฉันก็พบโหมด Evil

ประสบการณ์ / เคล็ดลับที่ควรค่าแก่การแบ่งปันของคุณในหัวข้อนี้คืออะไร?

นี่คือการกำหนดค่าโหมดชั่วร้ายทั้งหมดของฉันและใช้งานได้ดีสำหรับฉัน:

(require 'evil)
(evil-mode 1)

;; Remap org-mode meta keys for convenience
(mapcar (lambda (state)
    (evil-declare-key state org-mode-map
      (kbd "M-l") 'org-metaright
      (kbd "M-h") 'org-metaleft
      (kbd "M-k") 'org-metaup
      (kbd "M-j") 'org-metadown
      (kbd "M-L") 'org-shiftmetaright
      (kbd "M-H") 'org-shiftmetaleft
      (kbd "M-K") 'org-shiftmetaup
      (kbd "M-J") 'org-shiftmetadown))
  '(normal insert))

คุณพบความขัดแย้งระหว่างโหมดนี้กับโหมดอื่น ๆ หรือไม่?

ไม่ตรงกันข้ามกับ Viper / Vimpulse ซึ่งก่อให้เกิดปัญหาในหลายโหมด


ฉันได้รับข้อผิดพลาดนี้: progn: Symbol's value as variable is void: state Where is state?
justingordon

คุณสามารถลองevil-emacs-state
Kenny Meyer

2
คุณช่วยชี้แจงได้ไหมว่าคุณวางไว้ตรงไหน?
justingordon

1
มันยอดเยี่ยมมากฉันมองหาสิ่งนี้ อัพโหวตเพียบ!
jplindstrom

1
ลองดูที่github.com/edwtjo/evil-org-mode
avendael

17

ฉันเริ่มใช้ Evil เมื่อเดือนที่แล้ว ก่อนหน้านี้ฉันพยายามใช้ viper / vimpulse โดยไม่ประสบความสำเร็จมากนัก บอกตามตรงว่า vimpulse ค่อนข้างดี แต่การใช้งานกับโหมดต่างๆนั้นค่อนข้างลำบาก (เช่นโหมดคอมไพล์ที่ vimpulse บ้าอยู่ตลอดเวลา) ปล่อยให้ emac อยู่ในโหมดระหว่าง vi-emacs-something

เมื่อฉันเปลี่ยนเป็น Evil ในที่สุดฉันก็เริ่มสำรวจพลังของ Emacs เต็มรูปแบบและเชื่อฉันเถอะว่าฉันไม่เสียใจ Evil ทำงานได้ดีในทุกโหมดที่ฉันใช้ (ส่วนใหญ่แก้ไข, รวบรวม, เกาและปิด) และแม้แต่การอ่านข้อมูล / ชาย / ความช่วยเหลือก็ทำงานได้โดยไม่มีปัญหาใด ๆ

ยกเว้นว่าฉันพบเฉพาะการสลับบัฟเฟอร์แปลก ๆ ตามที่ฉันเคยทำ: b <0-9> แทน: b-TAB-then-complete-name หรือ: bn อย่างไรก็ตามโปรดทราบว่าผู้พัฒนา Evil พยายาม (ในบางกรณี) เพื่อลดฟังก์ชันการทำงานที่ซ้ำกันดังนั้นแทนที่จะ:! (เพื่อ exec คำสั่งเชลล์) คุณควรใช้ M-!

หากคุณพบว่าต้องการเพิ่ม / กำหนดคำสั่ง ex ที่กำหนดเองใหม่เพียงแค่เปิด evil-maps.el แล้วแก้ไข (ลองเป็นกลุ่ม!)

Evil ยังคงเป็นโครงการที่อายุน้อย แต่มีแนวโน้มและฉันกำลังรอวันที่จะแทนที่ viper ในการจัดจำหน่าย Emacs อย่างเป็นทางการ


4
นี่ควรจะบอกเป็นนัยว่าไม่สามารถเพิ่ม / กำหนดคำสั่งใหม่ในกลุ่มได้หรือไม่?
John Tyree

1
@JohnTyree คำสั่งที่ผู้ใช้กำหนดจะต้องเริ่มต้นด้วยอักษรตัวพิมพ์ใหญ่ใน Vim ในขณะที่คำสั่งในตัวทั้งหมดเริ่มต้นด้วยตัวอักษรตัวพิมพ์เล็ก
Austin Taylor

10

ฉันต้องการบันทึกบัฟเฟอร์เมื่อฉันออกจากinsert-mode: (แก้ไข: อย่าขอให้บันทึกเมื่อไม่มีไฟล์ที่เกี่ยวข้องสำหรับบัฟเฟอร์นี้เช่นเมื่ออยู่ในรอยขีดข่วนหรือบัฟเฟอร์ magit)

(defun my-save ()
  (if (buffer-file-name)
    (evil-save))
)

   (add-hook 'evil-insert-state-exit-hook 'my-save)

สำหรับความเป็นไปได้เพิ่มเติม: ดูhttp://wikemacs.org/index.php/Evil

ยินดีต้อนรับความคิดเห็นสำหรับการปรับปรุง!


ขอบคุณ. BTW ลิงก์ของคุณเสีย
Amos

ขอบคุณเช่นกัน. Wikemacs จะกลับมา เว็บไซต์อยู่ระหว่างการบำรุงรักษาหวังว่าจะไม่นานเกินไปอีก
Ehvince

9
  1. ฉันใช้Evil-leaderและใช้ ", xm" เพื่อแทนที่ "Mx" ดังนั้นฉันจึงไม่ค่อยกดปุ่ม Alt นอกจากนี้ยังมีgeneral.elซึ่งรองรับปุ่มผู้นำหลายปุ่ม

  2. evil-matchitกด "%" เพื่อข้ามไปมาระหว่างคู่แท็ก

  3. evil-nerd-commenterกด "9, ci" เพื่อแสดงความคิดเห็น / ไม่ใส่ความคิดเห็น 9 บรรทัด

  4. หลีกเลี่ยงการใช้ปุ่ม ESC คุณสามารถกด "kj"แทนได้

  5. มีความเชื่อมั่นในซอฟต์แวร์ฟรี! ไม่มีอะไรที่เป็นไปไม่ได้กับ Evil ที่รวมพลังของ Vim และ Emacs ตัวอย่างเช่นหลายคนคิดว่าการเชื่อมโยงคีย์ Evil ขัดแย้งกับปลั๊กอินที่มีอยู่ Emacs โดยไม่ต้องเชื่อมโยงซ้ำ นั่นผิดจริง


0

มาจากด้าน emacs ฉันชอบ M- มาก เป็น go-to-definition แต่ฟังก์ชันที่ทำงานจะM-.แตกต่างกันไปตามโหมดต่างๆ ฉันสามารถแทนที่ด้วยวิธีปกติโดย(define-key evil-normal-state-map (kbd "M-.") 'foo)ที่fooตรวจสอบโหมดหลักปัจจุบันและเรียกใช้ฟังก์ชันที่เหมาะสม แต่ดูเหมือนว่าจะต้องใช้การเข้ารหัสจำนวนมาก วิธีแก้ปัญหาทั่วไปคือ:

(defun evil-emacs-key-binding (key)
  (evil-execute-in-emacs-state)
  (key-binding key))

(defmacro evil-revert-key-binding (state-map key)
  `(define-key ,state-map ,key (lambda ()
                                 (interactive)
                                 (call-interactively
                                  (evil-emacs-key-binding ,key)))))

(eval-after-load "evil-autoloads"
  '(add-hook 'evil-after-load-hook
        (lambda ()
          (evil-revert-key-binding evil-normal-state-map (kbd "M-."))
          ;; and so on
        )))

อื่น ๆ กว่าที่ฉันชอบปลั๊กอินชั่วเซอร์ราวด์ ( แต่ผมรู้สึก smartparens เป็นโซลูชั่นที่สมบูรณ์มากขึ้น) และความชั่วร้ายผู้นำ

ฉันเคยใช้คีย์คอร์ดเพื่อแมป jk กับ ESC เหมือนที่ฉันเรียนรู้ที่จะทำในกลุ่ม แต่มันยืนยันที่จะปฏิบัติต่อ kj เช่นเดียวกับ jk ดังนั้นฉันจึงใช้สิ่งต่อไปนี้แทน:

(defun evil-escape-if-next-char (trigger)
  "Watches the next letter. If `trigger', then switch to normal mode,
otherwise keep the previously inserted key and forward unpressed
key to `unread-command-events'."
  (self-insert-command 1)
  (let ((next-key (read-event)))
    (if (eq trigger next-key)
        (progn
          (delete-char -1)
          (evil-normal-state))
      (setq unread-command-events (cons next-key unread-command-events)))))

(defun evil-escape-if-next-char-is-k (arg)
  (interactive "p")
  (if (= arg 1)
      (evil-escape-if-next-char ?k)
    (self-insert-command arg)))

(eval-after-load "evil-autoloads"
  '(add-hook 'evil-after-load-hook
             (lambda ()
               ;; … other stuff …
               (define-key evil-insert-state-map (kbd "j") 'evil-escape-if-next-char-is-k))))

ฉันใช้(setq evil-move-cursor-back nil)สิ่งที่ไม่เป็นกลุ่มมาก (แม้ว่าคุณจะทำให้ vimrc ของคุณทำอย่างนั้นได้อย่างน่าตกใจ) แต่ฉันไม่เคยคุ้นเคยกับเคอร์เซอร์ที่เลื่อนกลับหลังจากออกจากส่วนแทรก

เคล็ดลับการปฏิบัติงาน: ใช้สำหรับสิ่งที่ชอบโหลดขี้เกียจชั่วเซอร์ราวด์โหมดมันจะไม่ช่วยที่จะนำมันในที่ราบevil-local-mode-hook evil-mode-hookดังนั้นหากคุณติดตั้งความชั่วร้ายและความชั่วร้ายรอบทิศทางด้วยการติดตั้งแพ็คเกจคุณสามารถเริ่มต้นได้เมื่อคุณM-x evil-modeทำ

(eval-after-load "evil-surround-autoloads"
  '(add-hook 'evil-local-mode-hook #'evil-surround-mode))

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.