Emacs configuration with support for Chinese input
使用 Emacs 三年多了,当时受了 一年成为 Emacs 高手 的蛊惑,且贪图便利,使用了 Purcell 的配置。正如 Purcell 所说,此配置相当 reasonable,用来入门确实让我受益匪浅,少走了很多弯路。三年使用下来,我需要添加的插件只有 org-ref
和 ob-smiles
,配置更新也仅须 git pull
外加 M-x package-list-packages U x 即可,非常方便。
然而过去三年来,我主要是使用 Emacs 中的 org-mode 来记 Science 与 Tech 方面笔记,基于 Latex 的长文章 / 代码我更喜欢用 Atoms + Vim-mode 来写,基于 Markdown 的博客则用 MWeb 来写,中文笔记喜欢使用 Bears,最后却还是回到了苹果自带的免费 Notes。其他零零碎碎的场景则使用更为零碎的 app,餐馆用 DayGram + Workflowy,记账用随手记。非常不统一。
也就是说,我并不是一个“running my life with Emacs”的重症者,Purcell 配置的 Emacs 中也有大量我用不到,或者需要使用却不甚了解的插件。所以失业在家这个契机恰好也是让我重新审视 Emacs,看看我能否最大化地使用 Emacs。
对我而言,使用 Atoms 来写代码与 Latex,是由于我对使用 Emacs 调试还不甚熟练。所以这几天我花了一点时间重新阅读了 Emacs 手册。
使用 MWeb 来写博客与使用 Notes 来记笔记的原因则比较可笑,因为我基本上都是使用英文记录 Science & Tech 方面的笔记,我并没有配置 Emacs 的中文环境。所以需要使用中文来写东西时,我自然就得换用其他工具。这段时间准备面试,将 org-mode 的使用范围扩大到记录面试适宜,由于一亩三分地是一个主要资料来源,不免需要粘贴许多中文帖子进来。这时再将 Emacs 视为一个纯英文环境未免有些麻烦。而将 Emacs 中文化了,自然也不需要 MWeb 和 Notes 或者 Bear 什么事了。
而记录餐馆和消费的需求比较麻烦,本文暂且搁置,今后有空再来研究。
Emacs 中文输入法
Emacs 窗口左下角显示的是 character set 与 editing state,其中 character set 默认值为 U,即没有 input-mode 且使用 unicode 的 coding system,通过 C-\ ,可以非常方便地设置输入法并进行切换。
Emacs 有一些自带的中文输入法,比如拼音(chinese-py)、自然码(chinese-ziranma),还有一些四声(chinese-sisheng)、英汉(chinese-ecdict)等输入法。我将简体编码的一些输入法列于下表,详见 leim-lisp.el
(可通过 M-x find-library 迅速查看)。
input mode | 输入法 |
---|---|
chinese-ccdospy | 缩写拼音 |
chinese-ctlau | 刘锡祥式粤音 |
chinese-punct | 标点符号 |
chinese-py | 拼音 |
chinese-qj | 全角 |
chinese-sw | 首尾 |
chinese-tonepy | 带调拼音 |
chinese-ziranma | 自然码 |
由于我习惯用微软双拼,故另外安装 pyim,配置如下:
(require 'pyim)
(require 'pyim-basedict)
(pyim-basedict-enable)
(setq default-input-method "pyim")
(setq pyim-default-scheme 'microsoft-shuangpin)
(setq pyim-page-tooltip 'popup)
(setq pyim-page-length 5)
Emacs 中文字体
Emacs 中默认的中文字体是 Arial Unicode MS,看着总觉得哪哪不顺眼,所以下一步就是更换个顺眼的中文字体。
此处我先参考了 zhuoqiang 的做法,将中英文字体设为等宽的:
;; Setting English Font
(set-face-attribute 'default nil :font "DejaVu Sans Mono 14")
;; Chinese Font
(dolist (charset '(kana han symbol cjk-misc bopomofo))
(set-fontset-font (frame-parameter nil 'font)
charset (font-spec :family "PingFang SC"
:size 16)))
并将他写的更为通用的设置字体的函数:
(defun qiang-set-font (english-fonts
english-font-size
chinese-fonts
&optional chinese-font-size))
略加修改为:
(defun qiang-set-font (english-fonts
english-font-size
chinese-fonts
&optional chinese-font-scale)
...
:size (* chinese-font-scale english-font-size))
然而当我用 C-x C-+ 动态调整字体大小时,发现只有英文字体会缩放,中文则仍然蠢蠢地处于初始大小。查手册得可通过 face-font-rescale-alist
来设定特定字体缩放值。简单来说就是这样:
(setq face-font-rescale-alist '(("PingFang SC" . chinese-font-scale))
但是这样只能对苹方字体起效,如果一个一个对 font-list 中的字体修改 scale-factor 看起来又不简洁。于是我想到两种较为简便的设定方式:
;; First method
(setq face-font-rescale-alist
(loop for x in zh-font-list
collect (cons x chinese-font-scale)))
;; Second method
(setq face-font-rescale-alist
(pairlis zh-font-list
(make-list (list-length zh-font-list)
chinese-font-scale)))
效果拔群。
详细配置如下:
(defun qiang-font-existsp (font)
(if (null (x-list-fonts font))
nil
t))
(defvar zh-font-list '("PingFang SC" "Hiragino Sans GB" "Microsoft Yahei" "Source Han Sans Normal" "STHeiti" "黑体" "新宋体" "宋体"))
(defvar en-font-list '("DejaVu Sans Mono" "Monaco" "Consolas" "Monospace" "Courier New"))
(defun qiang-make-font-string (font-name font-size)
(if (and (stringp font-size)
(equal ":" (string (elt font-size 0))))
(format "%s%s" font-name font-size)
(format "%s %s" font-name font-size)))
(defun qiang-set-font (english-fonts
english-font-size
chinese-fonts
&optional chinese-font-scale)
(setq chinese-font-scale (or chinese-font-scale 1.2))
(setq face-font-rescale-alist
(loop for x in zh-font-list
collect (cons x chinese-font-scale)))
"english-font-size could be set to \":pixelsize=18\" or a integer.
If set/leave chinese-font-scale to nil, it will follow english-font-size"
(require 'cl) ; for find if
(let ((en-font (qiang-make-font-string
(find-if #'qiang-font-existsp english-fonts)
english-font-size))
(zh-font (font-spec :family (find-if #'qiang-font-existsp chinese-fonts))))
;; Set the default English font
(message "Set English Font to %s" en-font)
(set-face-attribute 'default nil :font en-font)
;; Set Chinese font
;; Do not use 'unicode charset, it will cause the English font setting invalid
(message "Set Chinese Font to %s" zh-font)
(dolist (charset '(kana han symbol cjk-misc bopomofo))
(set-fontset-font (frame-parameter nil 'font)
charset zh-font))))
(qiang-set-font en-font-list 14 zh-font-list)