Tianchi YU's Blog

Emacs 重塑计划 1 - 基本配置 + Markdown

已经从 vim 转到 emacs 有一段时间了,自觉深深喜欢上了 emacs 这款编辑器,且尝试了多种网络上流行的配置。但是,在处理大型 C++ 项目和使用 rtags 的过程中,感受到了一些局限性,因此我决定重塑一下它,充分发挥它的能力。

今天首先来重塑一下它的基本配置、自定义快捷键和 markdown 笔记。

我主要借鉴(抄袭)了ManateeLazyCat的部分代码,增加了一些个人的配置。另外,我再此特别声明,我真得非常崇拜这位Geek,他的代码能力和持续不断的热爱让我作为一个emacs爱好者望尘莫及。

Emacs 读取配置文件的地方有两个:

原理上,Emacs 在启动的时候会从系统目录读取 site-start.el, 然后再读取 ~/.emacs 文件的配置。可以理解 site-start.el 为系统级配置,是用于定制 Emacs 的版本用的,有防止用户级别配置文件干扰的作用。所以我们的个人配置是要存放到 ~/.emacs 中的。

1. 加载制定目录的 Elisp 插件,新加的配置和插件代码都按照目录方式分类存放

(defun add-subdirs-to-load-path (dir)
  "Recursive add directories to 'load-path'."
  (let ((default-directory (file-name-as-directory dir)))
    (add-to-list 'load-path dir)
   (normal-top-level-add-subdirs-to-load-path)))
(add-subdirs-to-load-path "/home/user/.emacs-config")

我们需要替换存放插件子目录的路径。然后每次可以直接把对应的插件存放到指定的目录下,每次Emacs重启时,会扫描路径下所有的插件并加载。如果出现问题,可以直接删除插件子目录即可。

而且对于emacs的插件安装,也可以直接下载放到对应的目录下的子目录中,并不需要通过melpa安装。

正如LazyCat所说,这的确是一种很好的习惯,每个初学者都应该培养。

2. 打印出错信息

emacs --debug-init  // 显示加载配置过程中的具体问题
emacs -Q            // 不加载任何配置,启动Emacs

3. init-generic

新建一个init-generic.el(在配置目录下),并通过(provide 'init-generic)支持被require调用。

重点功能

;; y或n来替代yes或no
(fset 'yes-or-no-p 'y-or-n-p)
;; 避免启动界面
(setq inhibit-startup-screen t)
;; 避免光标闪动
(blank-cursor-mode -1)
;; 避免emacs出错时发出声音
(setq ring-bell-function 'ignore)
;; 粘贴内容到文本光标处,而不是鼠标指针处
(setq mouse-yank-at-point t)
;; 强制分屏时使用上下分屏,而不考虑屏幕宽度变化 -- 这是LazyCat的个人习惯,我反而喜欢不同的分屏方式
(setq split-width-threshold nil)
;;避免默认自动选择
(setq completion-auto-select nil)
;;使用字体缓存,避免卡顿
(setq inhibit-compacting-font-caches t)
;; 对大文件或超长行提供性能优化
(setq-default bidi-display-reordering nil)
(setq bidi-inhibit-bpa t
      long-line-threshold 1000
      large-hscroll-threshold 1000
      syntax-wholeline-max 1000)

还可以增加一些其他对界面布局的配置

(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(tooltip-mode -1)
(set-fringe-mode 10)

还有很多其他配置是非常有用的,可以参考Lazycat的github

注意,经过测试,以下lisp代码会导致我的emacs进程无法正常被关闭,所以我选择在没有搞懂其原理之前,把它先注释掉:

(defadvice save-buffers-kill-emacs (around no-query-kill-emacs activate)
  "Prevent annoying \"Active processes exist\" query when you quit Emacs."
  (require 'noflet)
  (noflet ((process-list ())) ad-do-it))

很好,到这里,Emacs的初始配置就完成了,接下来,我重点配置一下Markdown在emacs中的功能。

4. init-markdown-mode

Reference

首先有两个插件markdownwraplish是需要安装的,在没有配置melpa的情况下,我把安装文件直接下载到load-path下的位置,emacs可以直接访问。

require ('markdown-mode)
require ('wraplish)

其中,wraplish 是LazyCat开发的一个在Unicode与英文之间加上空格的Emacs插件。

(defun fix-chinese-colons ()
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (let ((count 0))
      (while (re-search-forward "[\"“”]" nil t)
        (if (= (% count 2) 0)
            (replace-match "“" nil t)
          (replace-match "”" nil t))
        (setq count (1+ count)))))

  (save-excursion
    (goto-char (point-min))
    (let ((count 0))
      (while (re-search-forward "['‘’]" nil t)
        (if (= (% count 2) 0)
            (replace-match "‘" nil t)
          (replace-match "’" nil t))
        (setq count (1+ count)))))

  (message "Fix Chinese colons."))

(setq wraplish-add-space-after-chinese-punctuation t)

(dolist (hook (list
               'markdown-mode-hook
               ))
  (add-hook hook
            #'(lambda ()
                (wraplish-mode 1)
                )))

上面这段代码的功能是为 Emacs 中的 Markdown 编辑提供了一些辅助功能,包括修正中文标点和自动添加空格等。fix-chinese-colons 函数定义了一个交互式函数,用于修正中文标点,可以通过M+x调用。

到此,还有一个可选择性添加的配置是,mardown-mode的自动开启:

(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.mdown\\'" . markdown-mode))

重要的Emacs求助方式

Emacs是一个自由度极高,但配置过程也非常复杂、容易出错,学会有效求助是非常重要的。因此,我这里介绍一些重要的Emacs求助方式:EmacsWiki、Google 搜索、邮件列表和[IRC](t频道:#emacs 6667 irc.freenode.net,粘贴分享网站https://paste2.org/)。

具体的使用习惯,可以参考LazyCat的介绍

#emacs