Лучшие практики Evil Mode? [закрыто]

104

Я много лет использую Vim в качестве основного редактора и несколько раз пробовал Emacs за это время. Затем я открыл для себя Evil и решил, что оно достаточно хорошо удовлетворяет мои потребности в быстром перемещении, и я наконец могу перейти к Emacs.

Итак, для всех вас, злых пользователей, как вы интегрируете его с обычными функциями Emacs? Сталкивались ли вы с конфликтами между этим режимом и другими? Какие у вас есть полезные впечатления / советы по этой теме?

Даниэль Дуан
источник

Ответы:

71

Я использовал сильно настроенный vim, а теперь использую еще более настроенный emacs. Я думаю, вы найдете каждый экземпляр сопоставления клавиш в моем файле конфигурации сопоставления клавиш https://github.com/mbriggs/.emacs.d-oldv2/blob/master/init/init-keymaps.el

Имейте в виду, я перепрошиваю вещи, которые настоящие пользователи emacs сочли бы ересью, так что YMMV, если вы когда-нибудь захотите изучить «настоящие» emacs (я действительно не хочу).

Одна вещь, которую я бы порекомендовал любому бывшему виммеру, - это

;;; 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
Адам Белл,
1
@Adam, извините за это>.> У меня установлено много чего, иногда я использую функцию, которая, как мне кажется, встроена, но на самом деле исходит из другого места
Мэтт Бриггс
3
Я считаю, что у меня это не работает. Я использую последнюю версию Emacs 24.4, испытывал ли кто-нибудь то же самое?
Джунг Нгуен
1
Ссылка не работает. Я считаю, что это новый: github.com/mbriggs/.emacs.d/blob/master/config/keybinds.el
Sean Leather
1
@SeanLeather Обновлен ответ на рабочую ссылку.
Кристофер Боттомс
34

Как человек, пришедший из emacs, попробовавший vim и осознавший, что можно получить огромное количество вещей, я много экспериментировал, когда впервые начал использовать зло. Хотя нижеследующее является спорным, я хотел сохранить ключи emacs, которые используются более универсально в терминале, firefox, какао и т. Д., Но не хотел терять возможности редактирования 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» (или любой другой комбинации двух штрихов), лучший способ - скопировать текст с 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 ++, и многое другое, вы можете проверить из полных версий .emacs, init.el, my-keymaps.el и my-functions.el на моем git по адресу https://github.com/Russell91/emacs

РасселСтьюарт
источник
2
все это замечательно, я добавил кое-что в wikemacs: wikemacs.org/index.php/Evil#Configuration
Ehvince
Я понимаю ваше желание повторно использовать свои привычки из emacs. Для работы в Firefox я настоятельно рекомендую попробовать надстройку Vimperator, которая привносит в ваш браузер множество функций, подобных vim. Однако по умолчанию он использует команды перемещения vim (как в случае с lesscommand и другими).
Jan Vlcinsky 05
Как и вам, мне не нравится связывание зла в режиме вставки-состояния, поэтому я просто повторно привязываю «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))
Бах Лиен
30

Раньше я также был пользователем Viper / Vimpulse с огромным количеством настроек. Потом я нашел Evil-mode.

Какие у вас есть полезные впечатления / советы по этой теме?

Это вся моя конфигурация злого режима, и она отлично мне подходит:

(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: Значение символа как переменной недействительно: состояние Где определено состояние?
Justingordon
Вы можете попробоватьevil-emacs-state
Кенни Мейер
2
Вы можете уточнить, где вы это положили?
justingordon
1
Это фантастика, я искал именно это. Множество голосов за!
jplindstrom
1
Взгляните на этот github.com/edwtjo/evil-org-mode
avendael
17

Я начал пользоваться Evil месяц назад; до этого я без особого успеха пытался использовать viper / vimpulse. Если честно, vimpulse довольно хорош, но использование его с различными режимами было немного проблематичным (например, режим компиляции, где vimpulse всегда сходил с ума), оставляя emacs в каком-то режиме между vi-emacs-something.

Когда я переключился на Evil, я наконец начал исследовать всю мощь Emacs и, поверьте мне, я не пожалел. Evil прекрасно работает во всех используемых мною режимах (в основном редактирование, компиляция, скретчинг и eshell), и даже чтение info / man / help работает без проблем.

Кроме того, я обнаружил только переключение буфера странным, как и раньше: b <0-9> вместо: b-TAB-then-complete-name или: bn. Обратите внимание, однако, что разработчики Evil пытаются (в некоторых случаях) уменьшить повторяющиеся функции, поэтому вместо этого:! (чтобы выполнить команду оболочки), вы должны использовать собственный M- !.

Если вы чувствуете желание добавить / переопределить некоторые пользовательские команды ex, просто откройте evil-maps.el и отредактируйте его (попробуйте это в vim!).

Evil еще молодой, но многообещающий проект, и я жду того дня, когда заменит viper в официальном дистрибутиве Emacs.

Деннис
источник
4
Это должно означать, что в vim нельзя добавлять / переопределять команды?
Джон Тайри
1
@JohnTyree Пользовательские команды должны начинаться с заглавной буквы в Vim, тогда как все встроенные команды начинаются с строчной буквы.
Остин Тейлор
10

Мне нравится сохранять буфер, когда я выхожу из insert-mode: (отредактировано: не запрашивать сохранение, если для этого буфера нет связанного файла, например, когда в царапине или буфере магит)

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

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

для дополнительных возможностей: см. http://wikemacs.org/index.php/Evil

Комментарии приветствуются для улучшений!

Эхвинс
источник
Спасибо. Кстати, ваша ссылка не работает.
Amos
Тоже спасибо. Wikemacs вернется. Сайт находится на обслуживании, надеюсь, не надолго.
Ehvince
9
  1. Я использую злой лидер и использую ", 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-. чтобы перейти к определению, но функция, выполняемая в 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 .

Раньше я использовал ключевой аккорд для сопоставления jk с ESC, как я научился делать в vim, но он настаивал на том, чтобы рассматривать 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-Surround-Mode, это не поможет выразить это просто 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.)

отбойный молоток
источник