Emacs 折腾记

2015/05/10 Emacs

作为一名在 Windows 下使用了多年 gVim 的少年,已然把它在我需要的地方都收拾得服服贴贴,可以说 Vim 经过配置配置,上得厅堂下得厨房,基本能满足我的所有幻想。

直到那天突然产生了新的需求——Lisp。我工作中倒并没有用得到 Lisp 的地方,但是最近眼前晃过的一些书,比如《计算机程序的构造和解释》、《码农》杂志第 13 期,都对这门古老的语言推崇备至,还有垠神也撰文《Lisp 已死,Lisp 万岁!》历数现代 Lisp 方言的先进性,再者我也一直有学习一门函数式编程语言的想法,看起来,Lisp 是不二之选。但是在用 Vim 配置 Lisp 开发环境时遇到些问题,虽然有 Slimv,可用起来还是感觉各种不便。

在搜索网友们对此的经验之谈的时候,自然而然地,目光逐渐聚集到 Emacs 这个使用 Emacs Lisp 作为扩展语言的神的编辑器上。作为一名 Vimer,对 Emacs 不是没动过心,也曾尝试着使用过两回,最大的印象就是快捷键相比 Vim 实在是太难按了。没有需求就没有驱动力,这回貌似有了,Let’s 折腾起。

给自己的忠告:

锤子再好,再牛逼,也只是个锤子,而不应该成为工匠的心魔。(from 知乎)

目录

文本编辑环境——Evil

从 Vim 转到 Emacs 最大的不适应就是以前那些用得飞起的编辑模式和简洁熟悉的快捷键不好使了,需要切换到频繁的 Ctrl+ Alt+ 各种组合键去,以前就听说过有 Evil 这么个东西,试了一下发现这货还真是强大,常用的编辑模式、快捷键、命令,甚至宏和正则表达式等等操作都模拟得很好,跟在 gVim 里感觉一模一样,平移编辑习惯的坡度一下没了。

  1. 安装 Evil。

    M-x list-packages <RET>
    

    找到 Evil 并安装。

  2. 在 ~/.emacs 文件里加上:

    (require 'evil)
    (evil-mode t)
    

    这样就能在大部分地方(除了 eshell 等外)默认进入 Evil 模式使用 Vim 的编辑习惯了。

Common Lisp 开发环境

学习 Common Lisp 是使用 Emacs 最主要的任务,配好了文本编辑,当然得先把 Common Lisp 开发环境配置好了。

本来什么也不用配置的情况下 M-x ielm 就能进入一个 Emacs Lisp 的 REPL,但是它与 Common Lisp 毕竟还是有区别,所以还是另配置一个。

我使用网友们力荐的 Emacs + slime + sbcl 的组合,配置步骤如下:

  1. http://www.sbcl.org/ 下载安装 sbcl 的最新版。

    在 Windows 下推荐安装到默认路径。我尝试过更改路径安装,比如安装到 D 盘,但是运行时会提示在 C 盘的某个路径下找不到 sbcl.core 文件。

    Update:

    后来经验证,发现实际上是 sbcl 在安装过程中写的环境变量没有生效导致的,sbcl 在安装过程中会设置两个环境变量,新建一个 SBCL_HOME 值为 sbcl 安装路径,在 PATH 中添加 sbcl 安装路径。这两个变量必须是生效的(即任意开启 CMD 运行 sbcl 命令能正常进入 REPL),不然到安装目录下 CMD 运行 sbcl 会提示

    can't find core file at C:Program Files (x86)/sbcl/lib/sbcl//sbcl.core
    

    而此时即使完成了后面的步骤,在 Emacs 中运行 slime 会提示

    apply: Searching for program: no such file or directory, sbcl
    
  2. 安装 slime 和 slime-company 插件。

    M-x list-packages <RET>
    

    找到 slime 和 slime-company 并安装。

  3. 在 ~/.emacs 文件里加上:

    (setq inferior-lisp-program "sbcl")
    (require 'slime-autoloads)
    (slime-setup '(slime-fancy))
    (slime-setup '(slime-company))
    
  4. M-x slime 就可以进入到 REPL 进行 Common Lisp 的学习了。

Python 开发环境

虽然是一名很业余的 Python 选手,但是既然切了编辑器,自然也得在里面配好 Python 的开发环境。在网上找到一段简洁有效的配置步骤:

  1. 安装 virtualenv 和 jedi 插件。
    • pip install virtualenv
    • M-x package-install jedi
    • M-x package-install exec-path-from-shell
    • restart emacs
    • M-x exec-path-from-shell-initialize
    • M-x jedi:install-server
  2. 在 ~/.emacs 文件里添加:

    (require 'jedi)
    (autoload 'jedi:setup "jedi" nil t)
    (setq jedi:setup-keys t)
    (add-hook 'python-mode-hook 'jedi:setup)
    (setq jedi:complete-on-dot t)
    

这样自动补全之类的就没有问题了。

然后在如何运行当前 py 文件这件事上遇到些问题。在 Vim 中我一直是用 :!python % 来运行的,但是在 Emacs 里,包括 Evil、eshell、shell 里,如果有等待用户输入的语句如 inputraw_input 等,因为 Emacs 只重定向了输出,无法重定向输入,会提示如下错误:

EOFError: EOF when reading a line

在网上寻觅良久未果后找到两种方法(其实都是利用 start 命令):

  1. 在 Evil 里 :!start python %

  2. 使用 Emacs 的运行外部命令的方法 M-! start python test.py

文件名、Buffer 和命令的渐进提示

编程环境下需要自动补全,在非编程环境下,比如切换 Buffer,打开文件,输入函数命令等,同样需要。

  1. 使用 ido-mode 和 projectile 自动定位/提示/补全文件名、Buffer 名。

    安装 projectile 插件,然后在 ~/.emacs 文件里添加:

    (ido-mode t)
    (require 'projectile)
    (projectile-global-mode)
    (setq projectile-require-project-root nil)
    

    这个两个货带给我太多惊喜了……个人感觉已经超越使用 Vim 时用得倍爽的 CtrlP 了,赶紧打开文件(C-x C-f)或打开工程里的文件(C-c p f)试试吧。

    • 自动显示匹配的文件名。
    • 不用输入全路径,输入文件名能自动定位到文件。
    • 切换 Buffer 终于可视化了。
    • ……
  2. 使用 smex 自动提示 M-x 后的内容。

    安装 smex 插件,然后在 ~/.emacs 文件里添加:

    (global-set-key [(meta x)] (lambda ()
                                (interactive)
                                (or (boundp 'smex-cache)
                                    (smex-initialize))
                                (global-set-key [(meta x)] 'smex)
                                (smex)))
    
    (global-set-key [(shift meta x)] (lambda ()
                                    (interactive)
                                    (or (boundp 'smex-cache)
                                        (smex-initialize))
                                    (global-set-key [(shift meta x)] 'smex-major-mode-commands)
                                    (smex-major-mode-commands)))
    

    这样就能在输入命令的时候享受和打开文件、切换 Buffer 同样的体验了。

Markdown 编辑环境

使用 Github Pages 来搭建博客,自然离不开 Markdown。

配置这个倒是简单,安装 Markdown-mode 插件,然后在 ~/.emacs 中添加:

(autoload 'markdown-mode "markdown-mode"
  "Major mode for editing Markdown files" t)
(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
(add-hook 'markdown-mode-hook '(lambda ()
                                 (local-set-key (kbd "RET") 'comment-indent-new-line)))

打开 .md 后缀名的文件时将自动使用 markdown-mode,在 markdown-mode 下回车时执行 comment-indent-new-line,采用与当前行相同注释标记和缩进的换行,主要为了插入代码时方便。

C/S 模式快速启动 Emacs

Emacs 的启动速度是相比 Vim 来说被诟病吐槽得很多的一个点,我们在 Windows 下可以利用 C/S 模式来实现 Emacs 快速打开文件。

  1. 在 ~/.emacs 里添加

    (server-start)
    

    这样 Emacs 将在打开时启动一个 Server。Server 启动后会读取和加载配置文件,使用 emacsclientw.exe 打开文件时就不用再读取加载配置文件了,而是直接作为 Client 连接到 Server,这样基本能实现文件秒开。

  2. 添加 Edit with Emacs 到系统右键菜单。

    将以下内容复制之后粘贴到一个 .reg 文件里,运行即可(将 exe 路径换为你自己的)。

    Windows Registry Editor Version 5.00
    
    [HKEY_CLASSES_ROOT\*\shell\Edit with Emacs]
    
    [HKEY_CLASSES_ROOT\*\shell\Edit with Emacs\command]
    @="\"D:\\emacs\\bin\\emacsclientw.exe\" -a \"D:\\emacs\\bin\\runemacs.exe\" \"%1\""
    

    -a 参数表示如果使用 emacsclientw.exe 打开失败,那么使用 -a 指定的替代的编辑器打开。如果没有 -a 参数,那么在 Server 没有启动的情况下,右键打开文件将弹框提示:

    emacsclientw.exe: No socket or alternate editor. Please use:
        --server-file (or environment varible EMACS_SERVER_FILE)
        --alternate-editor (or environment varible ALTERNATE_EDITOR)
    

参考:

平滑滚动

Emacs 默认的滚动方式和 Vim 不一样,是光标移到屏幕上或者下边缘时突然跳动半屏,比较不符合我目光跟着光标走的习惯,这个可以使用一个插件来解决。

  • 安装 smooth-scrolling 插件。
  • 在 ~/.emacs 文件中添加

     (require 'smooth-scrolling)
     (setq smooth-scroll-margin 3)
    

    这个 3 表示在距离屏幕上下边缘还有 3 行的时候再移动光标即自动滚屏,方便随时能看到当前编辑行的上下文,可以根据自己的使用习惯调整。

Search

    Table of Contents