Praktik terbaik Mode Jahat? [Tutup]

104

Saya telah menggunakan Vim sebagai editor utama saya selama bertahun-tahun dan mencoba Emacs beberapa kali selama itu. Kemudian saya menemukan Evil dan memutuskan bahwa itu memenuhi permintaan saya untuk gerakan cepat dengan cukup baik sehingga saya akhirnya dapat beralih ke Emacs.

Jadi, untuk Anda semua pengguna Evil, bagaimana Anda mengintegrasikannya dengan fungsi Emacs normal? Apakah Anda pernah mengalami konflik antara mode ini dan mode lainnya? Apa pengalaman / tip Anda yang layak dibagikan tentang topik ini?

Daniel Duan
sumber

Jawaban:

71

Saya menggunakan vim yang sangat disesuaikan, dan sekarang menggunakan emacs yang lebih disesuaikan. Saya pikir Anda akan menemukan setiap contoh keymapping di file konfigurasi keymapping saya https://github.com/mbriggs/.emacs.d-oldv2/blob/master/init/init-keymaps.el

Perlu diingat, saya me-rebinding hal-hal yang akan dianggap oleh pengguna emacs nyata sebagai bid'ah, jadi YMMV jika Anda ingin mempelajari emacs "asli" (saya benar-benar tidak melakukannya).

Satu hal yang saya rekomendasikan kepada mantan vimmer adalah ini

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

sehingga esc benar-benar berhenti dari apa pun (seperti perintah tertunda di minibuffer)

Matt Briggs
sumber
7
Definisi minibuffer-keyboard-berhenti dapat ditemukan di sini: github.com/davvil/.emacs.d/blob/master/init.el
Adam Bell
1
@Adam maaf tentang itu>.> Saya memiliki banyak hal yang diinstal, terkadang saya menggunakan fungsi yang menurut saya sudah ada di dalamnya, tetapi sebenarnya berasal dari tempat lain
Matt Briggs
3
Saya menemukan bahwa ini tidak berhasil untuk saya. Saya menggunakan Emacs 24.4 terbaru, apakah ada yang mengalami hal yang sama?
Dzung Nguyen
1
Tautannya rusak. Saya yakin ini yang baru: github.com/mbriggs/.emacs.d/blob/master/config/keybinds.el
Sean Leather
1
@SeanLeather Memperbarui jawaban ke tautan yang berfungsi.
Christopher Bottoms
34

Sebagai seseorang yang berasal dari emacs, mencoba vim, dan menyadari bahwa ada banyak hal yang dapat diperoleh, saya melakukan banyak percobaan ketika saya mulai menggunakan kejahatan. Meskipun hal berikut ini kontroversial, saya ingin menyimpan kunci emacs yang digunakan secara lebih universal di terminal, firefox, cocoa, dll ..., tetapi tidak ingin kehilangan kemampuan pengeditan vim. Saya akhirnya memutuskan untuk memasang kembali kunci berikut di .emacs saya:

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

Sayangnya, ini tumpang tindih dengan operasi vim "pindah satu layar ke atas atau ke bawah". Namun, saya menjadi nyaman menggunakan yang berikut ini:

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

Selain itu, jika Anda berasal dari vim dan ingin jalur cepat dari penyisipan ke mode normal menggunakan "jk" (atau kombinasi 2 guratan lainnya), cara terbaik adalah menyalin teks dari http://www.emacswiki.org/ emacs / download / key-chord.el dan paste ke ~ / .emacs.d / key-chord.el Anda. Kemudian tambahkan yang berikut ini ke .emacs Anda:

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

Juga, jika Anda berasal dari vim dan menurut Anda copy-to-clipboard di emacs tidak bagus, Anda mungkin benar. Namun, Anda mungkin menemukan yang berikut berguna setelah menjalankan 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)

Jelas, Anda harus memutuskan sendiri apakah salah satu perubahan kontroversial ini layak dilakukan, tetapi mungkin perubahan dasar ini akan menginspirasi Anda.

Untuk beberapa implementasi fungsi yang sangat keren lainnya, seperti hapus dan tempel, hapus tanpa menyalin ke clipboard, gerakan 4x / 16x yang efisien, penggunaan hitungan untuk spesifikasi register tempel, pengaturan tab yang benar-benar berfungsi untuk c / c ++, dan banyak lagi, Anda dapat memeriksa keluar versi lengkap .emacs, init.el, my-keymaps.el, dan my-functions.el di git saya di https://github.com/Russell91/emacs

RussellStewart
sumber
2
semua ini bagus, saya menambahkan beberapa di wikemacs: wikemacs.org/index.php/Evil#Configuration
Ehvince
Saya memahami keinginan Anda untuk menggunakan kembali kebiasaan Anda dari emacs. Untuk bekerja di Firefox, saya sangat menyarankan untuk mencoba addon Vimperator, yang menghadirkan banyak fungsionalitas mirip vim ke penjelajahan Anda. Namun, ini menggunakan perintah gerakan vim secara default (seperti halnya lessperintah dan lainnya).
Jan Vlcinsky
Sama seperti Anda, saya tidak suka pengikatan jahat dalam mode-negara bagian, jadi saya hanya memasang kembali "i" di peta-keadaan-normal menjadi 'keadaan-emacs-jahat.
pengguna49117
Alih-alih menimpa keyboard evil, saya menghapusnya, sehingga kembali ke pengaturan keyboard emacs normal, misalnya(dolist (m (list evil-normal-state-map evil-motion-state-map evil-insert-state-map)) (define-key m "\C-e" 'nil))
Bach Lien
30

Saya juga pernah menjadi pengguna Viper / Vimpulse, dengan konfigurasi yang sangat besar . Kemudian saya menemukan mode-Jahat.

Apa pengalaman / tip Anda yang layak dibagikan tentang topik ini?

Ini adalah seluruh konfigurasi mode jahat saya, dan ini berfungsi dengan baik untuk saya:

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

Apakah Anda pernah mengalami konflik antara mode ini dan mode lainnya?

Tidak, berbeda dengan Viper / Vimpulse yang menyebabkan masalah di beberapa mode.

Kenny Meyer
sumber
Saya mendapatkan error ini: progn: Nilai simbol sebagai variabel adalah void: state Di mana state didefinisikan?
justingordon
Anda dapat mencobaevil-emacs-state
Kenny Meyer
2
Bisakah Anda menjelaskan di mana Anda meletakkannya?
justingord
1
Ini luar biasa, saya mencari persis seperti ini. Suara positif berlimpah!
jplindstrom
17

Saya mulai menggunakan Evil sebulan yang lalu; sebelumnya, saya mencoba menggunakan viper / vimpulse tanpa banyak hasil. Sejujurnya, vimpulse cukup bagus, tetapi menggunakannya dengan berbagai mode agak merepotkan (misalnya mode kompilasi di mana vimpulse selalu gila) meninggalkan emacs dalam beberapa mode antara vi-emacs-sesuatu.

Ketika saya beralih ke Evil, saya akhirnya mulai mengeksplorasi kekuatan Emacs penuh, dan percayalah, saya tidak menyesal. Kejahatan bekerja dengan baik di semua mode yang saya gunakan (kebanyakan mengedit, kompilasi, goresan dan eshell) dan bahkan membaca info / man / help bekerja tanpa masalah.

Kecuali itu, saya hanya menemukan buffer switching yang aneh seperti yang biasa saya lakukan: b <0-9> sebagai gantinya: b-TAB-then-complete-name or: bn. Namun perlu dicatat bahwa pengembang jahat mencoba (dalam beberapa kasus) untuk mengurangi fungsi duplikat, jadi sebagai gantinya:! (untuk perintah exec shell), Anda harus menggunakan native M- !.

Jika Anda merasa ingin menambahkan / mendefinisikan ulang beberapa perintah ex khusus, cukup buka evil-maps.el dan edit (coba di vim!).

Evil masih muda tetapi proyek menjanjikan dan saya menunggu hari kapan akan menggantikan viper dalam distribusi resmi Emacs.

dennis
sumber
4
Apakah ini seharusnya menyiratkan bahwa tidak mungkin menambahkan / mendefinisikan ulang perintah di vim?
John Tyree
1
@JohnTyree Perintah yang ditentukan pengguna diperlukan untuk memulai dengan huruf besar di Vim, sedangkan semua perintah bawaan dimulai dengan huruf kecil.
Austin Taylor
10

Saya suka menyimpan buffer ketika saya keluar dari insert-mode: (diedit: jangan minta untuk menyimpan ketika tidak ada file terkait untuk buffer ini, seperti ketika di awal atau buffer magit)

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

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

untuk kemungkinan lainnya: lihat http://wikemacs.org/index.php/Evil

Komentar diterima untuk perbaikan!

Ehvince
sumber
Terima kasih. BTW, tautan Anda rusak.
Amos
Terimakasih juga. Wikemacs akan kembali. Situsnya sedang dalam pemeliharaan, semoga tidak terlalu lama lagi.
Ehvince
9
  1. Saya menggunakan pemimpin jahat dan menggunakan ", xm" untuk menggantikan "Mx", jadi saya jarang menekan tombol Alt. Ada juga general.el yang mendukung beberapa kunci pemimpin.

  2. evil-matchit , tekan "%" untuk beralih di antara pasangan tag.

  3. evil-nerd-commenter , tekan "9, ci" untuk mengomentari / menghapus komentar 9 baris

  4. hindari menggunakan tombol ESC, Anda dapat menekan "kj" sebagai gantinya.

  5. Percayalah pada perangkat lunak gratis! Tidak ada yang mustahil dengan Evil yang menggabungkan kekuatan Vim dan Emacs. Misalnya, banyak orang beranggapan bahwa keybindings Evil bertentangan dengan plugin Emacs yang ada tanpa pengikatan ulang yang berat. Sebenarnya itu salah

chen bin
sumber
0

Dari sisi emacs, saya sangat menyukai M-. menjadi go-to-definition, tetapi fungsi yang berjalan pada M-.mode berbeda-beda. Aku bisa menimpa dalam cara biasa dengan (define-key evil-normal-state-map (kbd "M-.") 'foo)mana foocek modus utama saat ini dan menjalankan fungsi yang sesuai, tapi itu suara seperti itu akan membutuhkan banyak hardcoding. Solusi yang lebih umum adalah ini:

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

Selain itu, saya suka plugin evil-surround (meskipun saya merasa smartparens adalah solusi yang lebih lengkap) dan pemimpin jahat .

Saya dulu menggunakan key-chord untuk memetakan jk ke ESC seperti yang telah saya pelajari di vim, tetapi bersikeras memperlakukan kj sama dengan jk, jadi saya menggunakan yang berikut ini:

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

saya menggunakan (setq evil-move-cursor-back nil) yang tidak terlalu jelas (meskipun tampaknya Anda dapat membuat vimrc Anda melakukan itu juga), saya tidak pernah terbiasa dengan kursor yang bergerak kembali setelah keluar dari penyisipan.

Tip praktis: gunakan evil-local-mode-hookuntuk hal-hal seperti malas memuat mode surround-jahat, itu tidak akan membantu untuk menjelaskannya evil-mode-hook. Jadi jika Anda menginstal evil dan evil-surround dengan paket-instal, Anda dapat memulainya saat M-x evil-modemelakukannya

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

(Tentu saja, jika Anda selalu menjalankan mode jahat dan selalu menginstal jahat, hal itu tidak perlu dimuat otomatis, tetapi saya lebih suka agar .emacs saya cukup umum sehingga saya dapat menggunakannya pada mesin dengan emacsen lama atau tanpa memiliki paket elpa diinstal.)

palu
sumber