这应该算第三次使用Emacs了。第一次是在2009年,NOI 2009酱油后下决心好好学习Linux,Philip Xu前辈我指引了两天,发现Linux这个未知世界竟然有这么多好玩的软件。编辑器之神Vim用了一阵子了,NOIP 2009前若干天开始探索神的编辑器Emacs,使用Emacs Lisp配置,实现与Vim相似的设定效果需要多出好多代码,因此不久又回到Vim。大概2010下半年又用起Emacs,这次好好折腾了一把。当时Vim的插件生态还围绕vim.org(现在逐步转战GitHub了),Emacs倒是有个http://www.emacswiki.org,尝试了Mew、ERC、AUCTeX、haskell-mode、org-mode等好多东西。很多文件类型的解析、自动缩进支持比Vim对应物好不少,插件质量感觉也稍高。
Emacs有时被人诟病为一个缺乏好的编辑器的操作系统。诚然,收邮件、上IRC、内置终端模拟器、各种网站客户端,网上能找到很多插件赋予它做各式各样任务的能力。我2012年第二次弃用Emacs是因为我认为作为“操作系统”的Emacs扮演了很多窗口管理器的角色,我已经配置好了xmonad,这些任务应该交给xmonad。Emacs扮演的窗口管理器提供了不错的REPL能力,buffer间通信的方便程度不是不同进程间通信可比的。
Emacs的很多major mode会与外部程序通信,提供快捷键把代码传递给inferior process执行,再把结果传输回来,并用适当形式在Emacs中显示。如haskell-mode、tuareg-mode、erlang-mode等,这些major mode往往都提供REPL功能,而且词法高亮、缩进也都优于Vim下的对应物。另外minor mode的设计着实高明,功能模块可以方便地载入和卸载,比Vim使用autocommand和filetype检测方便。Emacs能作为操作系统的竞争力来自于它是个优秀的Lisp交互式编程环境,活着的Lisp Machine。求值光标前的代码、查询快捷键绑定、查阅函数文档,有相当多功能通过Vim的插件很难做好。
下图是j-mode,使用快捷键把当前行传输给inferior process (jconsole)并获取执行结果。
下图是Proof General,theorem prover的界面,录色底色部分为已经执行过的命令,阶段性结果显示在下方buffer中。Proof General提供了快捷键执行下一条命令或者撤销上一条命令。
web-mode可以在一个buffer中同时支持HTML、CSS、JavaScript等多种词法高亮,根据当前major mode提供的菜单也非常方便。
感谢最近的awesome-*系列项目,全方位介绍各种领域的插件,通过https://github.com/emacs-tw/awesome-emacs,发现Emacs的插件生态还挺好的。这是再次皈依Emacs的重要原因,另一方面是感觉Emacs固有的设计优于Vim。GTK+的Emacs是个富文本编辑器,每个字符都可以有不同的样式,而GVim的字符大小是统一的,在UI表现能力上弱于Emacs。AUCTeX就充分利用了Emacs的这个优势,解析TeX中粗体、斜体、大字号、小字号等标记,用相应的样式显示,一目了然。Google Images中搜索AUCTeX有很多图片例子。另外Emacs也可以内嵌图片,公式片段作为图片渲染,这可是个杀手级特性。再譬如prettify-symbols-mode,Vim也有conceal,但是由于字体显示的缺陷,不能很好发挥。
自package.el诞生以来Emacs的包管理生态也逐渐好转。第二次放弃Emacs时还有很多插件散落在网上各地,如今逐步被ELPA等仓库收纳。现在包管理的选择太多,el-get、cask、quelpa……选择太多有些时候不是好事。
Evil
Vim的modal
editing非常方便,我认为Vim胜过Emacs的最主要的地方在于normal
mode下的一些操作,特别是光标移动和operator-pending
mode。Emacs默认的光标移动快捷键主要有C-f
、C-b
、C-p
、C-n
、M-f
、M-b
等,使用频率很高,但却需要两个键,令人恼火。优于缺少模式,Emacs默认提供的很多快捷键使用了很长的key
sequence,比如C-x r j
映射为jump-to-register
,后面跟字符a
就类似于Vim的`a
,但是太不方便了。
所幸插件evil-mode可以在Emacs里模拟Vim,使Emacs具备modal editing的功能。为了更好的一致性,我不使用insert mode中的Vim特有快捷键,只用Emacs默认的:
1 | (setcdr evil-insert-state-map nil) |
Evil另外附带了一些Vim中以插件形式提供的功能。下图是Evil整合的ace-jump(Vim的easymotion),跳转到指定字符或以指定字符开头的单词、行等:
Helm
和Vim的Unite类似但强大得多的必备插件,参见http://tuhdo.github.io/helm-intro.html。
helm-ag,在当前目录下用ag搜索,显示匹配项。
helm-imenu,Imenu的增量搜索版:
helm-swoop,增量搜索匹配行,类似于helm-occur
,但会即时显示匹配的部分。
Global的前端helm-gtags
helm-gtags,Global的前端。helm-gtags-dwim
、helm-gtags-find-rtag
很有用,值得为之绑定简单的快捷键。
Org-mode
一款日程安排、项目管理、literate programming、笔记软件,神器。参考http://doc.norang.ca/org-mode.html。
键绑定与冲突
fcitx默认以C-SPC
为输入法切换键,与Emacs默认的set-mark-command
冲突,我把切换键改为C-S-SPC
。
fcitx默认绑定了C-M-h
用于拼写检查,与Emacs默认的mark-defun
冲突,我删除了fcitx的绑定:Configure-Input
Method,双击Keyboard,点击Toggle to word hint,按ESC。
其他
M-x winner-mode
,内置,global minor mode。可以用C-c left
和C-c right
在撤销或重做对窗格布局的变更。M-x ansi-term
,内置,可显示颜色的终端模拟器。- dired,内置的文件管理器。
- expand-region,基于语义单位增量式选择区域。视频http://emacsrocks.com/e09.html。
- neotree,树状文件管理器,类似Vim的NERD Tree。
- flycheck,即时语法检查,类似Vim的syntastic。
- projectile,提供一些以项目为单位的实用功能。
- smartparens,处理广义括号的minor mode。
- which-key-mode,在弹出的buffer中显示当前按下的前缀键的所有可能绑定。
目前采用的GIF录制方法:
xwininfo
获取Emacs窗口位置大小信息,用byzanz-record -x 1 -y 33 -w 960 -h 640 -d 10 a.gif
录制GIF动画,再用gifsicle --scale 0.75 --delete '#33-' a.gif > b.gif
裁剪开头部分。
我的配置
https://github.com/MaskRay/Config/tree/master/home/.emacs.d
进一步了解
Vim到Emacs的迁移:
- http://juanjoalvarez.net/es/detail/2014/sep/19/vim-emacsevil-chaotic-migration-guide/
- http://ceyes.github.io/2015-01/from-Vim-to-Emacs/
聚合、Wiki:
一些配置: