标签:emacs

上古编辑器,神的编辑器

spacemacs workflow

Spacemacs 的优势在于预装了很多有用的 package, 整合到一起,无冲突。并在此基础上定义了一套方便的快捷键。使用 spacemacs 之前,担心快捷键太多记不住。实际上,使用几次后,发现快捷键定义还是很有规律的,而且有按键提示,不需要太多记忆。熟悉几个主要操作后,可以提高 emacs 的使用效率。

打开文件

一般情况下,我们经常操作的文件不会太多,都在最近文件列表里,列出最近使用 buffer 的快捷键是 SPC b b 。另外一个比较有用的是 SPC TAB ,在最近使用的两个 buffer 中切换。

如果要找的文件不在最近列表中,可以使用 SPC f L ,调用全盘快速搜索程序,windows 上默认使用 es.exe ,linux 上默认使用 locate ,快速定位到目标文件。

跳到函数定义

在编辑配置文件,或查看 emacs-lisp 文件时, SPC s j 可以在 minibuffer 中列出所有函数列表,选中后司跳到定义处。

搜索字符串

搜索功能有几个常见场景

  • 搜索光标下字符串

    使用 vim 的 superstar 功能就,只要按一下 * 就能快速搜索。

  • 搜索输入的字符串

    SPC s s 是 helm-swoop 的快捷键,类似于 multi-occur 的功能,输入字符串,在 minibuffer 中列出该字符串出现的所有列,选择后跳转。

写作 blog

打开 blog.org 文件后, C-z 退出 evil 模式,个人感觉在 evim 模式下,使用中文输入法不太方便。

M-> 跳转到文件最后,输入 blog-drawer ,这是我自定义的一个 snippet,用于创建 blog 标题和 drawer。

* $1
:PROPERTIES:
:BLOG: www.litchisoftware.com
:CATEGORY: ${2:代码}
:END:
$3

写完文章后, M-x org2blog/wp-post-subtree-and-publish 发布 blog。这个命令是个自定义函数

;;;###autoload
(defun org2blog/wp-post-subtree-and-publish ()
  "Publish the current subtree as a page."
  (interactive)
  (org2blog/wp-post-subtree t))

spacemacs 配置方法

这两天摸索了 spacemacs 的配置方法。定制的指导思想,除了 .spacemacs 文件,不改动 spacemacs 的其它任何文件。以后升级或迁移配置时,直接从 github 下载最新 spacemacs 代码即可,不用做任何改动。在 .spacemacs 配置中,重定义私有配置目录为 ~/.spacemacs.private ,自定义 layer 和 snippets 都放在此目录中。在 emacs 裸奔的机器上,下载并安装完 spacemacs,再下载私有配置,就能使用了。配置过程中的几个主要修改点:

  • 自定义私有目录

    .spacemacs 文件中,修改以下配置

    dotspacemacs-configuration-layer-path '("~/.spacemacs.private/")
    
  • 修改已有 layer 的配置

    spacemacs 中,部分 layer 会有 config.el 配置文件,该文件中保存 layer 的定制修改,但我并不想对 spacemacs 原始文件做任何改动。因为一旦修改了 spacemacs 的 layer 文件,就要把 spacemacs 代码也纳入私有 repo 管理 ,而我希望私有 repo 尽可能小,只有自已的配置,没有第三方代码。办法是有的,在 .spacemacs 中,选择加载包时,可以直接定制配置。

    (auto-completion
     :variables
     ;; auto-completion-front-end 'auto-complete
     auto-completion-return-key-behavior 'complete
     auto-completion-tab-key-behavior 'cycle
     auto-completion-enable-snippets-in-popup t
     auto-completion-complete-with-key-sequence nil
     auto-completion-complete-with-key-sequence-delay 0.1
     auto-completion-private-snippets-directory  (concat (car dotspacemacs-configuration-layer-path) "snippets/")
     auto-completion-enable-sort-by-usage t
     )
    
  • 添加一个 package

    自已原来一直用 org2blog 写博客,但 spacemacs 中没有集成这个包,怎么办?先用下面命令添加一个 layer,根据提示一步步完成。

    M-x configuration-layer/create-layer
    

    完成后,得到 README.orgpackage.el 。在 package.el 中,有详细的说明,怎么定义此 package 的引用和初始化函数。在定义过程中要用到 use-package 这个包,可以去 github 看下使用方法,简单来说,初始化 init 部分在包加载前调用, config 部分在包加载后调用。

  • 修改基本配置

    如果不需要用到其它 package,只是修改基本配置,直接在 .spacemacs 文件的 dotspacemacs/user-config 函数中修改就可以了。

修改完后,不一定需要重新启动 emacs,使用快捷键 SPC f e R 可以重装加载配置。但有些配置是添加到配置列表中的,重新加载配置不启作用,这种情况就需要重启 emacs 了。

迁移到 spacemacs

spacemacs 是 emacs 社区最近比较火的话题,水木上有不少相关讨论。我目前使用的 emacs 配置是几年积累下来的结果,本不想折腾,要迁移过去,想想都麻烦。

禁不住好奇,还是从 github 上下载了安装包试一试,前几次安装并不顺利,没能顺利用起来。有这样几个问题:

  • 提示找不到某个 package。查看了包目录,此包已经下载,但个别文件大小为 0。解决方法是把此包删除,重新启动 emacs 下载安装。
  • 下载包时提示找不到,这是网络问题,挂上 vpn 就行。

解决这两个小问题后,就能用上了。启用有点慢,在我 i5 的 PC 上,大约十多秒。我原来的 emacs 配置启动较快,大约在两秒左右。默认仅加载很少几个包,但使用 orgmode 编辑时,lazy 加载 helm 会比较慢,也需要 6 秒左右。 Spacemacs 优点还是很多的,我觉得这几点做得不错:

  • 快捷键归类不错,提示也很好。快捷键设计成三键式,第一键又叫 leader 键,是空格键。第二键是功能归类键,比如:file 相关的快捷键在 f 键下, buffer 相关的在 b 键下,搜索相关的在 s 键下。第三键是具体功能健,比如删除 buffer 是 d。每次按键后,mini-buffer 中有详细的按键提示,告诉你下一步按什么键是什么对应的功能。基本不用专门记忆,用几次就熟悉了。
  • 即插即用式的安装,多平台支持,方便迁移。在远程 vps 服务器上,下载安装包后,安装 spacemacs-base 就可以使用了。快捷键和基本编辑方式不用重新学习,比 emacs 裸奔强太多了,也不用把自已的配置文件全部搬过来,还没那么多平台差异问题。
  • 最小化个人配置。自带的包配置非常全面,个人只要做些微小的定制修改就能直接使用。版本管理时, .emacs.d 直接使用 github 上 spacemacs 的 develop 分支,不做任何改动。自已的配置修改提交到私人 repo,比起原来 50 多兆的配置文件,这样迷你多了。

目前已经把 orgmode 和 org2blog 配置完成,写博客是没有问题了。c-c++模式也启动了,但还没有详细定制,有时间再看看。

orgmode 导出 html 的换行处理

我之前还奇怪,在 org2blog 中设置保留换行符时,为什么可以正确处理中文的自动换行 ,今天查看了 orgmode 配置,才发现有个 advice

;;;###autoload
(defadvice org-html-paragraph (before fsh-org-html-paragraph-advice
                                      (paragraph contents info) activate)
  "Join consecutive Chinese lines into a single long line without
unwanted space when exporting org-mode to html."
  (let*
      ((orig-contents (ad-get-arg 1))
       (reg-han "[[:multibyte:]]")
       (fixed-contents (replace-regexp-in-string
                        (concat "\\(" reg-han "\\) *\n *\\(" reg-han "\\)")
                        "\\1\\2" orig-contents)))
    (ad-set-arg 1 fixed-contents)))

这段代码是从 水木 emacs 版 抄过来的,作用是修改 html 导出函数 org-html-paragraph 的第一个参数,将两个汉字中间的换行符去掉。

org2blog 的使用

当初建立这个博客就是为了试一试 org2blog ,使用一段时间后,建立了一套使用方法。把所有博客写在文件 blog.org 中,级别 1 用于区分文章,级别 1 标题是文章标题,属性是文章属性。从级别 2 开始,是文章的子标题。下面列出了一些功能点需要花时间配置的。

自动登陆

每次启动 emacs 后,需要执行一次 org2blog/wp-login 命令登陆。登录信息在 emacs 关闭后不会记录,下次启动 emacs 后,还需要再次登录,次数多了会觉得不方便。org2blog 可以通过配置实现自动登陆,具体配置可参考官方网站。

subtree 的 post-and-publish 功能

不知道出于哪方面考虑,org2blog 不提供 subtree 的 post-and-publish 功能,只有 post 接口。在配置文件中加入下面函数,可实现 post-and-publish 功能。

;;;###autoload
(defun org2blog/wp-post-subtree-and-publish ()
  "Publish the current subtree as a page."
  (interactive)
  (org2blog/wp-post-subtree t))

多余窗口处理

每次发布文章后,org2blog 会弹出一个新窗口,可能是临时 buffer,没什么意义,总要手动关闭。下面这段代码可以在发布文章后取消弹出窗口。

(defadvice org2blog/wp-upload-files-replace-urls
    (after fj/org2blog/wp-upload-files-replace-urls (text) activate)
  (delete-window))

换行处理

使用 org2blog 过程中,发现对换行处理不太好:如果将 org2blog/wp-keep-new-lines 设置成 t ,中文换行处理基本没有问题,能识别自动换行还是硬换行,对于自动换行会在转换后连接成一行。而英文处理会有问题,所有的自动换行都被识别成了段硬换行。如果将 org2blog/wp-keep-new-lines 设置成 nil , 中文处理会有问题,列表中后必要的换行会被删除。

麻烦是的, org2blog/wp-keep-new-lines 是全局配置,无法根据一篇文章进行换行调整。我设计了一个解决方法,如果在属性中添加了 ENGLISH 描述,则不保留换行符,适用于英文文章。如果没有这个属性,则保留换行符,适用于中文文章。这需要通过写代码来实现,修改代码的方法不可取,因为库会经常升级,覆盖这些修改。较好的方法是用 defadvice

(defadvice org2blog/wp--parse-subtree-entry
    (before fj/org2blog/wp--parse-subtree-entry () activate)
  (let* ((keep-new-lines (org-entry-get (point) "ENGLISH")))
    (if keep-new-lines
  (setq keep-new-lines nil)
      (setq keep-new-lines org2blog/wp-keep-new-lines))
    (plist-put org2blog/wp-export-options :wp-keep-new-lines keep-new-lines)))