邪恶模式最佳做法?[关闭]


104

多年来,我一直使用Vim作为主要编辑器,并在这段时间内尝试了几次Emacs。然后,我发现了Evil,并决定它足以满足我对快速移动的需求,以至于我最终可以继续使用Emacs。

那么,对于所有Evil用户而言,您如何将其与常规Emacs功能集成?您是否在此模式和其他模式之间遇到任何冲突?您在此主题上值得分享的经验/技巧是什么?

Answers:


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实际上会退出几乎所有内容(例如minibuffer中的待处理提示)


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
@SeanLeather更新了工作链接的答案。
Christopher Bottoms

34

作为一个来自emacs的人,尝试了vim,并意识到有很多东西可以收获,所以当我第一次使用邪恶时,我做了很多试验。尽管以下内容引起争议,但我想保留在终端,firefox,可可等中更普遍使用的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上的git上列出完整的.emacs,init.el,my-keymaps.el和my-functions.el versons


2
这一切都很棒,我在wikemacs中添加了一些内容:wikemacs.org/index.php/Evil#Configuration
Ehvince 2013年

我了解您将重用emacs的习惯的意愿。为了在Firefox中工作,我强烈建议您尝试使用Vimperator插件,它会为您的浏览带来许多类似vim的功能。但是,默认情况下它使用vim移动命令(less命令和其他命令都是这种情况)。
Jan Vlcinsky

与您一样,我不喜欢在插入状态模式下进行邪恶绑定,因此我只是将正常状态图中的“ 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 Lien19年

30

我也曾经是一个蝰蛇/ 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:符号的变量值无效:state在哪里定义状态?
justingordon 2012年

您可以尝试evil-emacs-state
肯尼·梅耶

2
您能澄清一下该放在哪里吗?
justingordon

1
太好了,我正是在寻找这个。赞美嘉豪!
jplindstrom


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开发人员尝试(在某些情况下)减少重复的功能,所以:: (对于exec shell命令),您应该使用本机M-!。

如果您想添加/重新定义一些自定义的ex命令,只需打开evil-maps.el并对其进行编辑(请在vim中尝试!)。

Evil仍处于年轻阶段,但项目前景可观,我正在等待这一天,它将在Emacs官方发行版中取代蛇蝎。


4
这是否意味着不可能在vim中添加/重新定义命令?
约翰·泰瑞

1
@JohnTyree在Vim中,用户定义的命令必须以大写字母开头,而所有内置命令均以小写字母开头。
奥斯丁·泰勒

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

欢迎评论改进!


谢谢。顺便说一句,您的链接已断开。
阿摩斯(Amos)

也谢谢你。Wikemacs将回来。该站点正在维护中,希望不会再过长。
Ehvince

9
  1. 我使用邪恶领导者,并使用“,xm”替换“ Mx”,因此我很少按Alt键。还有general.el支持多个领导者钥匙。

  2. 邪恶匹配,按“%”在标记对之间跳转。

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

除此之外,我喜欢插件邪恶环绕(尽管我觉得smartparens是一个更完整的解决方案)和邪恶领袖

我曾经使用key-chord将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-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))

(当然,如果您始终运行evil-mode并始终安装evil,则不需要该自动加载的东西,但是我希望.emacs具有足够的通用性,以便可以在装有旧emacsen的计算机上使用它,也可以不安装任何东西。 elpa软件包已安装。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.