이블 모드 모범 사례? [닫은]


104

저는 수년간 Vim을 기본 편집기로 사용해 왔으며 그 기간 동안 Emacs를 여러 번 사용해 보았습니다. 그러다가 Evil을 발견 하고 마침내 Emacs로 넘어갈 수있을만큼 빠른 움직임에 대한 나의 요구를 충족 시키기로 결정했습니다.

그렇다면 모든 Evil 사용자에게 일반 Emacs 기능과 어떻게 통합합니까? 이 모드와 다른 모드간에 충돌이 발생 했습니까? 이 주제에 대해 공유 할 가치가있는 경험 / 팁은 무엇입니까?

답변:


71

나는 고도로 맞춤화 된 vim을 사용했고 이제는 더욱 맞춤화 된 emacs를 사용합니다. 내 키 매핑 구성 파일 https://github.com/mbriggs/.emacs.d-oldv2/blob/master/init/init-keymaps.el 에서 모든 키 매핑 인스턴스를 찾을 수 있다고 생각합니다.

명심하세요, 저는 실제 emacs 사용자들이 이단이라고 생각하는 것들을 리 바인딩하고 있습니다. 그래서 만약 당신이 "진짜"emacs를 배우고 싶다면 YMMV (정말 그렇지 않습니다).

제가 전직 비머에게 추천하고 싶은 것은

;;; 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
minibuffer-keyboard-quit에 대한 정의는 여기에서 찾을 수 있습니다 : github.com/davvil/.emacs.d/blob/master/init.el
Adam Bell

1
@Adam 그것에 대해 죄송합니다>.> 저는 많은 것들이 설치되어 있습니다. 때로는 제가 내장되어 있다고 생각하는 기능을 사용하지만 실제로는 다른 곳에서 오는 기능을 사용합니다
Matt Briggs

3
나는 이것이 나를 위해 작동하지 않는다는 것을 알았습니다. 최신 Emacs 24.4를 사용하고 있는데, 누구도 같은 경험을하나요?
Dzung Nguyen 2014 년

1
링크가 끊어졌습니다. 나는 이것이 새로운 것이라고 믿는다 : github.com/mbriggs/.emacs.d/blob/master/config/keybinds.el
Sean Leather

1
@SeanLeather 작동중인 링크에 대한 답변을 업데이트했습니다.
Christopher Bottoms

34

emacs에서 왔고, vim을 사용 해보고, 얻을 것이 엄청나게 많다는 것을 깨달은 사람으로서, 저는 처음 악을 사용하기 시작할 때 많은 실험을했습니다. 다음은 논란의 여지가 있지만 터미널, 파이어 폭스, 코코아 등에서 더 보편적으로 사용되는 emacs 키를 유지하고 싶었지만 vim 편집 기능을 잃고 싶지 않았습니다. 내 .emacs에서 다음 키를 리 바인드하기로 결정했습니다.

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

안타깝게도 이러한 기능은 vim "한 화면 위로 또는 아래로 이동"작업과 겹칩니다. 그러나 대신 다음을 사용하는 것이 편해졌습니다.

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

또한 vim에서 왔고 "jk"(또는 다른 2 개의 스트로크 조합)를 사용하여 삽입에서 일반 모드로 빠른 경로를 원할 경우 가장 좋은 방법은 http://www.emacswiki.org/ 에서 텍스트를 복사하는 것입니다 . emacs / download / key-chord.el 및 ~ / .emacs.d / key-chord.el에 붙여 넣습니다. 그런 다음 .emacs에 다음을 추가합니다.

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

또한 vim에서 왔고 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 ++에서 작동하는 탭 설정 등과 같은 다른 정말 멋진 기능 구현의 경우 확인할 수 있습니다. https://github.com/Russell91/emacs 에서 내 자식의 전체 .emacs, init.el, my-keymaps.el 및 my-functions.el 버전을 확인하십시오.


2
:이 모든 중대하다, 나는 wikemacs에서 일부 추가 wikemacs.org/index.php/Evil#Configuration
Ehvince

나는 이맥스에서 당신의 습관을 재사용하려는 당신의 의지를 이해합니다. Firefox에서 작업하려면 Vimperator 애드온을 사용하는 것이 좋습니다. Vimperator 애드온은 검색에 많은 vim과 같은 기능을 제공합니다. 그러나 기본적으로 vim 이동 명령을 사용합니다 ( less명령 및 기타의 경우).
Jan Vlcinsky 2013

당신과 마찬가지로, 저는 삽입 상태 모드의 악한 바인딩을 좋아하지 않습니다. 그래서 그냥 정상 상태 맵의 "i"를 'evil-emacs-state'로 리 바인드했습니다.
user49117

의 키보드를 재정의하는 대신 evil제거하여 일반 emacs의 키보드 설정으로 돌아갑니다. 예(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 사용자 였습니다. 그런 다음 악 모드를 찾았습니다.

이 주제에 대해 공유 할 가치가있는 경험 / 팁은 무엇입니까?

이것은 내 모든 악한 모드 구성이며 나에게 잘 작동합니다.

(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의 값이 void입니다. state 상태는 어디에 정의되어 있습니까?
justingordon

당신이 시도 할 수evil-emacs-state
케니 마이어에게

2
어디에 넣었는지 명확히 할 수 있습니까?
justingordon

1
이것은 환상적입니다. 정확히 이것을 찾았습니다. 많은 찬성 투표!
jplindstrom


17

저는 한 달 전에 Evil을 사용하기 시작했습니다. 그 전에는 많은 성공없이 바이퍼 / 빔 펄스를 사용해 보았습니다. 솔직히 말해서 vimpulse는 꽤 좋지만 다양한 모드와 함께 사용하는 것은 약간 번거로 웠습니다 (예 : vimpulse가 항상 미쳤던 컴파일 모드).

Evil으로 전환했을 때 마침내 완전한 Emacs 파워를 탐구하기 시작했고 저를 믿었지만 후회하지 않았습니다. Evil은 내가 사용한 모든 모드 (주로 편집, 컴파일, 스크래치 및 eshell)에서 잘 작동하며 info / man / help를 읽는 것도 문제없이 작동합니다.

그 점을 제외하고는 : b <0-9> 대신 : b-TAB-then-complete-name 또는 : bn을 사용했던 것처럼 버퍼 스위칭이 홀수임을 발견했습니다. 그러나 Evil 개발자는 중복 기능을 줄이려고 (경우에 따라) 시도하므로 대신 :! (셸 명령을 실행하려면) 기본 M-!를 사용해야합니다.

사용자 지정 ex 명령을 추가 / 정의하고 싶은 충동을 느끼면 evil-maps.el을 열고 편집하십시오 (vim에서 시도하십시오!).

Evil은 아직 어리지만 유망한 프로젝트이며 공식 Emacs 배포판에서 바이퍼를 대체 할 날을 기다리고 있습니다.


4
이것은 vim에서 명령을 추가 / 정의 할 수 없다는 것을 의미합니까?
John Tyree 2013 년

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, 링크가 끊어졌습니다.
아모스

감사합니다. Wikemacs가 돌아올 것입니다. 이 사이트는 유지 관리 중입니다.
Ehvince

9
  1. 내가 사용 악한 지도자 , "MX"를 대체 할 그래서 드물게하려면 Alt 키를 사용 ", XM을". 여러 리더 키를 지원하는 general.el 도 있습니다 .

  2. evil-matchit , "%"를 눌러 태그 쌍 사이를 이동하십시오.

  3. evil-nerd-commenter , "9, ci"를 눌러 9 줄에 대한 주석 / 주석 제거

  4. ESC 키 사용을 피하고 대신 "kj"누를 수 있습니다 .

  5. 자유 소프트웨어를 믿으십시오! Vim과 Emacs의 힘을 결합한 Evil은 불가능한 것이 없습니다. 예를 들어, 많은 사람들은 Evil 키 바인딩이 무거운 리 바인딩없이 기존 플러그인 Emacs와 충돌한다고 가정합니다. 사실은 틀렸어


0

emacs 쪽에서 나는 M-를 매우 선호합니다. 정의로 이동하지만 실행되는 기능은 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
        )))

그 외에는 플러그인 evil-surround (smartparens가 더 완벽한 솔루션이라고 생각하지만) 및 evil-leader를 좋아합니다 .

나는 vim에서 배운 것처럼 jk를 ESC에 매핑하기 위해 key-chord를 사용했지만 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)그다지 vimmy가 아닌 것을 사용합니다 (비록 당신의 vimrc도 그렇게 할 수는 있지만), 삽입을 종료 한 후 커서가 뒤로 이동하는 데 익숙하지 않았습니다.

실용적인 팁 : evil-local-mode-hook지연 로딩 악의 서라운드 모드와 같은 작업에 사용 하면 평범하게 두는 데 도움이되지 않습니다 evil-mode-hook. 따라서 package-install로 사악하고 사악한 서라운드를 설치하면 다음을 수행 M-x evil-mode하여 시작할 때 시작할 수 있습니다.

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

(물론, 항상 이블 모드를 실행하고 항상 이블이 설치되어있는 경우 자동로드 항목이 필요하지 않지만, .emacs가 오래된 emacsen이 있거나없는 시스템에서 사용할 수있을만큼 충분히 일반적으로 사용하는 것이 좋습니다. elpa 패키지가 설치되었습니다.)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.