Najlepsza praktyka w Evil Mode? [Zamknięte]

104

Od lat używam Vima jako mojego głównego edytora i kilka razy próbowałem w tym czasie Emacsa. Potem odkryłem Zło i zdecydowałem, że spełnia ono moje wymagania dotyczące szybkiego ruchu na tyle dobrze, że w końcu mogę przejść do Emacsa.

A więc do wszystkich złych użytkowników, jak zintegrujesz to z normalnymi funkcjami Emacsa? Czy napotkałeś jakieś konflikty między tym trybem a innymi? Jakie są Twoje warte podzielenia się doświadczenia / wskazówki na ten temat?

Daniel Duan
źródło

Odpowiedzi:

71

Użyłem wysoce dostosowanego vima, a teraz używam jeszcze bardziej dostosowanego emacsa. Myślę, że każdy przypadek mapowania klawiszy znajdziesz w moim pliku konfiguracyjnym mapowania klawiszy https://github.com/mbriggs/.emacs.d-oldv2/blob/master/init/init-keymaps.el

Pamiętaj, że rebinduję rzeczy, które prawdziwi użytkownicy emacsa uznaliby za herezję, więc YMMV, jeśli kiedykolwiek zechcesz nauczyć się "prawdziwego" emacsa (naprawdę tego nie robię).

Jedną rzeczą, którą poleciłbym każdemu byłemu vimmerowi, jest to

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

tak, że esc faktycznie zamyka prawie wszystko (np. oczekujące monity w minibuforze)

Matt Briggs
źródło
7
Definicję rezygnacji z minibufora-klawiatury można znaleźć tutaj: github.com/davvil/.emacs.d/blob/master/init.el
Adam Bell
1
@Adam przepraszam za to>.> Mam wiele zainstalowanych rzeczy, czasami używam funkcji, która moim zdaniem jest wbudowana, ale w rzeczywistości pochodzi z innego miejsca
Matt Briggs
3
Uważam, że to nie działa dla mnie. Używam najnowszego Emacsa 24.4, czy ktoś doświadcza tego samego?
Dzung Nguyen
1
Link jest uszkodzony. Myślę, że to jest nowy: github.com/mbriggs/.emacs.d/blob/master/config/keybinds.el
Sean Leather
1
@SeanLeather Zaktualizowana odpowiedź na działający link.
Christopher Bottoms
34

Jako ktoś, kto pochodzi z emacsa, wypróbował vim i zdał sobie sprawę, że jest wiele rzeczy do zyskania, dużo eksperymentowałem, kiedy zacząłem używać zła. Chociaż poniższe kwestie są kontrowersyjne, chciałem zachować klawisze emacsa, które są powszechnie używane w terminalu, firefoxie, kakao itp., Ale nie chciałem stracić możliwości edycji vima. W końcu zdecydowałem się na ponowne powiązanie następujących kluczy w moim .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)))))

Niestety nakładają się one na operacje vima „przesuń jeden ekran w górę lub w dół”. Jednak przyzwyczaiłem się do tego, używając zamiast tego:

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

Ponadto, jeśli pochodzisz z vima i chcesz uzyskać szybką ścieżkę z trybu wstawiania do normalnego trybu przy użyciu "jk" (lub dowolnej innej kombinacji 2-suwowej), najlepszym sposobem jest skopiowanie tekstu z http://www.emacswiki.org/ emacs / download / key-chord.el i wklej go do swojego ~ / .emacs.d / key-chord.el. Następnie dodaj do swojego .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)

Ponadto, jeśli pochodzisz z vima i uważasz, że kopiowanie do schowka w emacsie nie jest dobre, prawdopodobnie masz rację. Jednak po uruchomieniu sudo apt-get install xsel mogą okazać się przydatne następujące elementy:

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

Oczywiście będziesz musiał sam zdecydować, czy którakolwiek z tych kontrowersyjnych zmian jest tego warta, ale być może te podstawowe zmiany Cię zainspirują.

W przypadku innych naprawdę fajnych implementacji funkcji, takich jak usuwanie i wklejanie, usuwanie bez kopiowania do schowka, wydajny ruch 4x / 16x, użycie liczników do specyfikacji rejestru wklejania, ustawienia kart, które faktycznie działają dla c / c ++ i więcej, możesz sprawdzić pełne wersje .emacs, init.el, my-keymaps.el i my-functions.el na moim git pod adresem https://github.com/Russell91/emacs

RussellStewart
źródło
2
wszystko jest świetne, dodałem trochę w wikemacs: wikemacs.org/index.php/Evil#Configuration
Ehvince
Rozumiem twoją wolę ponownego wykorzystania nawyków z emacsa. Do pracy w Firefoksie bardzo polecam wypróbowanie dodatku Vimperator, który zapewnia wiele funkcji Vima do przeglądania. Jednak domyślnie używa poleceń ruchu vima (tak jak w przypadku lesscommand i innych).
Jan Vlcinsky
Tak samo jak ty, nie lubię złego wiązania w trybie wstawiania stanu, więc po prostu zmieniam wiązanie „i” z mapy stanu normalnego na stan „zły-emacs”.
user49117
Zamiast nadpisywać klawiaturę evil, wyjmuję ją, więc wraca do ustawień klawiatury normalnego emacsa, przykład(dolist (m (list evil-normal-state-map evil-motion-state-map evil-insert-state-map)) (define-key m "\C-e" 'nil))
Bach Lien
30

Byłem też użytkownikiem Vipera / Vimpulse, z ogromną ilością konfiguracji. Potem znalazłem tryb zła.

Jakie są Twoje warte podzielenia się doświadczenia / wskazówki na ten temat?

To jest cała moja konfiguracja trybu złego i działa świetnie dla mnie:

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

Czy napotkałeś jakieś konflikty między tym trybem a innymi?

Nie, w przeciwieństwie do Viper / Vimpulse, który powodował problemy w kilku trybach.

Kenny Meyer
źródło
Otrzymuję ten błąd: progn: Wartość symbolu jako zmiennej jest nieważna: stan Gdzie jest zdefiniowany stan?
justingordon
Możesz spróbowaćevil-emacs-state
Kenny Meyer
2
Czy możesz wyjaśnić, gdzie to umieściłeś?
justingordon
1
To jest fantastyczne, szukałem dokładnie tego. Mnóstwo głosów poparcia!
jplindstrom
1
Spójrz na ten github.com/edwtjo/evil-org-mode
avendael
17

Zacząłem używać Evil miesiąc temu; przedtem próbowałem użyć viper / vimpulse bez większego sukcesu. Szczerze mówiąc, vimpulse jest całkiem fajne, ale używanie go z różnymi trybami było trochę kłopotliwe (np. Tryb kompilacji, w którym vimpulse zawsze szalał) pozostawiając emacsa w jakimś trybie pomiędzy vi-emacs-coś.

Kiedy przeszedłem na Zło, w końcu zacząłem odkrywać pełną moc Emacsa i wierz mi, nie żałowałem. Zło działa ładnie we wszystkich trybach, których używałem (głównie edycji, kompilacji, scratchu i eshellu), a nawet czytanie info / man / help działa bez żadnych problemów.

Tyle tylko, że znalazłem tylko dziwne przełączanie buforów, jak to robiłem: zamiast tego b <0-9>: b-TAB-then-complete-name lub: bn. Zauważ jednak, że deweloperzy Evil próbują (w niektórych przypadkach) ograniczyć zduplikowane funkcje, więc zamiast tego:! (aby wykonać polecenie powłoki), powinieneś użyć natywnego M- !.

Jeśli masz ochotę dodać / przedefiniować niektóre niestandardowe polecenia ex, po prostu otwórz evil-maps.el i edytuj go (spróbuj tego w vimie!).

Evil to wciąż młody, ale obiecujący projekt i czekam na dzień, kiedy zastąpi vipera w oficjalnej dystrybucji Emacsa.

dennis
źródło
4
Czy to ma oznaczać, że nie można dodawać / redefiniować poleceń w vimie?
John Tyree,
1
@JohnTyree Polecenia zdefiniowane przez użytkownika muszą zaczynać się od dużej litery w Vimie, podczas gdy wszystkie wbudowane polecenia zaczynają się od małej litery.
Austin Taylor
10

Lubię zapisywać bufor, gdy wychodzę z insert-mode: (edytowane: nie pytaj o zapisanie, gdy nie ma skojarzonego pliku dla tego bufora, na przykład w buforze scratch lub magit)

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

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

aby uzyskać więcej możliwości: zobacz http://wikemacs.org/index.php/Evil

Mile widziane komentarze dotyczące ulepszeń!

Ehvince
źródło
Dzięki. Przy okazji, twój link jest uszkodzony.
Amos
Również dziękuję. Wikemacs wróci. Witryna jest w trakcie konserwacji, miejmy nadzieję, że już niedługo.
Ehvince
9
  1. Używam złego przywódcy i używam ", xm" zamiast "Mx", więc rzadko wciskam klawisz Alt. Istnieje również general.el, który obsługuje wiele klawiszy liderów.

  2. evil-matchit , naciśnij "%", aby przeskoczyć między parą tagów.

  3. evil-nerd-commenter , naciśnij "9, ci", aby skomentować / odkomentować 9 linii

  4. unikaj używania klawisza ESC, możesz zamiast tego nacisnąć "kj" .

  5. Miej wiarę w wolne oprogramowanie! Nie ma rzeczy niemożliwych z Złem, które łączy w sobie moc Vima i Emacsa. Na przykład, wiele osób zakłada, że ​​złe skróty klawiszowe kolidują z istniejącymi wtyczkami Emacs bez konieczności ponownego wiązania. Właściwie to źle

chen bin
źródło
0

Jeśli chodzi o stronę emacsa, bardzo wolę M-. aby przejść do definicji, ale funkcja, która działa, M-.różni się w zależności od trybu. Mogę zastąpić go w regularny sposób, z (define-key evil-normal-state-map (kbd "M-.") 'foo)którym foosprawdza aktualny tryb dur i uruchamia odpowiednią funkcję, ale to brzmi jak to, że wymagają dużo hardcoding. Bardziej ogólne rozwiązanie jest następujące:

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

Poza tym lubię wtyczki evil-surround (choć uważam, że smartparens to bardziej kompletne rozwiązanie) i evil-leader .

Kiedyś używałem key-chord do mapowania jk na ESC, tak jak nauczyłem się robić w vimie, ale nalegałem na traktowanie kj tak samo jak jk, więc zamiast tego używam następującego:

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

używam (setq evil-move-cursor-back nil) który nie jest zbyt vimmy (chociaż najwyraźniej możesz sprawić, że vimrc też to zrobi), po prostu nigdy nie przyzwyczaiłem się do cofania kursora po wyjściu z insert.

Praktyczna wskazówka: użyj evil-local-mode-hookdo rzeczy takich jak leniwe ładowanie trybu złego dźwięku przestrzennego, nie pomoże to wyjaśnić evil-mode-hook. W przypadku zainstalowania złego i zła Surround z tak pakietu instalacji, można mieć go uruchomić, gdy robisz M-x evil-modewykonując

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

(Oczywiście, jeśli zawsze korzystasz z trybu złego i zawsze masz zainstalowane zło, nie ma potrzeby tego automatycznego ładowania, ale wolę, aby moje .emacs były na tyle ogólne, że mogę go używać na maszynach ze starym emacsenem lub bez zainstalowane pakiety elpa).

unhammer
źródło