邪恶模式的最佳实践?

时间:2011-12-13 01:15:02

标签: emacs editor emacs23 evil-mode

我多年来一直使用Vim作为我的主编,并在此期间多次尝试使用Emacs。然后我发现Evil并且认为它足以满足我对快速运动的要求,以至于我最终可以转向Emacs。

那么,对于所有邪恶的用户,如何将其与普通的Emacs功能集成?您是否在此模式与其他模式之间遇到过任何冲突?您对这个主题有什么分享经验/提示?

7 个答案:

答案 0 :(得分: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实际上几乎可以退出任何东西(比如迷你缓冲区中的待处理提示)

答案 1 :(得分:34)

作为一个来自emacs的人,尝试了vim,并意识到有很多东西可以获得,我在第一次开始使用邪恶时做了很多实验。虽然以下是有争议的,但我想保留在终端,firefox,cocoa等中更普遍使用的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 ++的选项卡设置等等,你可以在我的git https://github.com/Russell91/emacs

上查看完整的.emacs,init.el,my-keymaps.el和my-functions.el。

答案 2 :(得分: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相比,这在几种模式下造成了麻烦。

答案 3 :(得分:17)

一个月前我开始使用邪恶;在它之前,我尝试使用viper / vimpulse而没有太大的成功。老实说,vimpulse是相当不错的,但使用各种模式有点麻烦(例如vimpulse总是疯狂的编译模式)在某些模式下将emacs留在vi-emacs之间。

当我转向邪恶时,我终于开始探索完整的Emacs力量,相信我,我并不后悔。 Evil在我使用的所有模式中都能很好地工作(主要是编辑,编译,刮擦和eshell),甚至阅读信息/ man / help也没有任何问题。

除此之外,我只发现像以前那样奇数缓冲切换:b< 0-9>相反:b-TAB-then-complete-name或:bn。但请注意,邪恶的开发人员尝试(在某些情况下)减少重复的功能,所以改为:! (对于exec shell命令),你应该使用原生M - !。

如果你发现添加/重新定义一些自定义ex命令的冲动,只需打开evil-maps.el并编辑它(在vim中试试!)。

邪恶仍然是年轻但充满希望的项目,我等待将在官方Emacs发行版中取代v蛇的那一天。

答案 4 :(得分: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

欢迎评论改进!

答案 5 :(得分:9)

  1. 我使用evil-leader并使用“,xm”替换“M-x”,所以我很少按Alt键。还有general.el支持多个领导者密钥。

  2. evil-matchit,按“%”可在标记对之间跳转。

  3. evil-nerd-commenter,按“9,ci”评论/取消注释9行

  4. 避免使用ESC键,您可以改为press "kj"

  5. 对自由软件有信心!结合Vim和Emacs的力量,Evil没有什么是不可能的。例如,许多人认为Evil键绑定与现有插件Emacs冲突而没有大量重新绑定。 That's wrong actually

答案 6 :(得分: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)并不是非常强大的(虽然你可以让你的vimrc做到这一点),我从来没有习惯在退出插入后向后移动光标。

实用提示:使用evil-local-mode-hook来处理延迟加载邪恶环绕模式等内容,它无法帮助将其置于普通evil-mode-hook中。因此,如果您使用package-install安装evil and evil-surround,则可以在执行M-x evil-mode时启动

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

(当然,如果你总是运行邪恶模式并且总是安装了邪恶,那么就不需要那种自动加载的东西了,但我更喜欢让我的.emacs足够通用以便我可以在机器上使用它使用旧的emacsen或没有安装任何elpa软件包。)