在 X 下使用 emacs 時,如果字型配置不好,emacs 就會顯得十分醜陋。而作為
emacs 的使用者,每天相當長的時間都在盯着這個編輯器,如果字型不好看,對眼
睛是一種嚴重的傷害。除非有嚴重的自虐傾向,沒有人會喜歡這種感覺。
我在這篇短文中總結了 emacs 的字型設定方法,由于 linux 的字型設定本身就
是一個很複雜的問題,本文如有疏漏,希望大家指正。
* 兩種字型系統
實際上 XFree86/Xorg 包括了兩種字型系統:核心字型系統和xft字型系統。核心
字型系統曆史悠久,傳統的 X 程式使用的都是核心字型系統。但是随着人們對字
體的顯示要求越來越高,核心字型系統漸漸地有些落伍了。為了更好地支援矢量
字型,實作抗鋸齒、子像素光栅化等進階特性,xft字型系統開始浮出水面。
由于 xft 字型系統所具有的種種優良特性,現代的 X 程式開始普遍采用 xft
字型系統繪制文字,逐漸開始取代核心字型系統。例如,基于 Qt/Gtk2 的程式
采用的都是 xft 字型系統。
但是核心字型系統并沒有完全退出曆史舞台,很多老的 X 程式仍然采用的是核心
字型系統,要把這些程式全部遷移到 xft 字型系統還要做許多工作。很不幸
emacs 就是這樣一個程式。有一個正在開發中的 emacs 分支(XFT_JHD_BRANCH),
就是試圖讓 emacs 支援 xft 字型系統,可惜這個分支還很不成熟。也許下一個
代的 emacs 會支援 xft,但目前我們還隻能接受 emacs 不支援 xft 的現實。
* 字型的安裝
由于目前的狀況是兩種字型系統并存,我們安裝字型時就必須同時照顧到兩者。
有時候在網上我們會看到一些字型安裝經驗介紹,比如:“安裝字型太簡單了,
把字型丢到 ~/.fonts 下面,執行一下 fc-cache 指令,你就可以在 firefox 中
使用這個字型了。”實際上,這隻是為 xft 字型系統安裝字型的方法,按這種方
法安裝的字型,采用核心字型系統的程式無法使用,也就是說 emacs 無法使用這
樣安裝的字型。
下面我們介紹為核心字型系統安裝字型的方法,很多人對這種方法記憶猶新,因
為在幾年前,xft出現之前,為linux安裝字型采用的都是這種方法。
第一步,拷貝字型。選擇一個目錄,把想用的字型拷貝到這個目錄下。比如:
cp simsun.ttf /path/to/my/truetype/font/simsun.ttf
第二步,生成 fonts.scale 與 fonts.dir
在你的字型目錄下用 mkfontscale 指令生成 fonts.scale 檔案,用
mkfontdir 指令生成 fonts.dir 檔案,注意指令的順序不能颠倒,否則生成
的 fonts.dir 是空檔案。其實這兩個檔案的内容是一樣的,是以也可以直接
cp fonts.scale fonts.dir
不知道是什麼原因 mkfontscale/mkfontdir 指令生成的 fonts.scale 檔案中
缺少對 gbk 字型的支援,是以需要手工編輯 fonts.scale,添加一行:
simsun.ttf -misc-simsun-medium-r-normal--0-0-0-0-p-0-gbk-0
如果你用的是不同的字型,這一行的内容可能不太一樣,但需要注意的是必須要
加上一個以 gbk-0 結尾的行。同時,檔案第一行的那個數字要加1。
fonts.dir檔案也要進行相應的修改,使這兩個檔案保持一緻。如果不進行這
一步,就無法使用 gbk 字型。
第三步,修改 /etc/X11/xorg.conf (如果你在用 XFree86, 那就修改
XF86Config-4):
找到 Section "Module", 加載 freetype 子產品:
Section "Module"
......
Load "freetype"
......
EndSection
找到 Section "Files", 添加你的字型路徑:
Section "Files"
......
FontPath "/path/to/my/truetype/font"
......
EndSection
最後重新啟動 X,這時候用 xlsfonts 指令應該能看到你安裝的字型。注意,隻
有 xlsfonts 列出的字型,emacs 才能使用。
* emacs的字型設定
由于 emacs 是個支援多語言的程式,它支援很多種字元集,而一種字型一般隻覆
蓋一個或幾個字元集,是以隻用一種字型是無法顯示 emacs 支援的所有文字的。
是以在emacs中需要設定 fontset,也就是多種字型的集合,或者叫做字型集。
如果我們不指定 fontset, 那麼 emacs 會使用預設的 fontset-default 來顯示
字型。如果你覺得這種字型不好看,就需要自己定義 fontset。定義 fontset 有
兩種方式,一種是在 ~/.emacs 中使用 create-fontset-from-fontset-spec 函
數,令一種是在 ~/.Xdefaults 中定義資源。我們分别介紹這兩種方法。
** 使用 create-fontset-from-fontset-spec
每個 fontset 都有一個很長的正規名稱,例如:
-*-courier-medium-r-normal--14-*-*-*-*-*-fontset-courier
為了友善起見也可以使用短名稱,就是最後兩段:fontset-courier
那麼這個名稱是怎麼生成的呢?首先我們用 xlsfonts 指令找到自己滿意的字型,
比如:
-adobe-courier-medium-r-normal--14-100-100-100-m-90-iso8859-1
然後把最後兩段去掉,也就是把 iso8859-1 去掉,換上自己起的字型集名稱,
比如 fontset-courier,最後把我們不關心的部分用 `*' 号取代就可以了,
注意,用 xlsfonts 列出來的字型名稱中,有些字段為 0,這些是可縮放的矢量
字型,這些 0 不能保留,必須用數字或 `*' 号取代,例如,
-adobe-courier-medium-r-normal--0-0-0-0-p-0-iso8859-1
要改為:
-adobe-courier-medium-r-normal--14-*-*-*-p-*-fontset-courier
還有一點需要注意,盡量不要選用可縮放的矢量字型,因為 emacs 不支援 xft,
是以無法打開抗鋸齒,這些字型會顯得很毛糙,不好看。
標明了字型就可以用 create-fontset-from-fontset-spec 函數定義 fontset
了,這個函數很簡單,它的參數是個字元串:
(create-fontset-from-fontset-spec
(concat
"-*-courier-medium-r-normal-*-14-*-*-*-*-*-fontset-courier,"
"chinese-gb2312:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gb2312*-*,"
"mule-unicode-0100-24ff:-*-simsun-medium-r-*-*-14-*-*-*-c-*-iso10646*-*,"
"korean-ksc5601:-*-*-medium-r-*-*-14-*-*-*-*-*-ksc5601*-*,"
"chinese-cns11643-5:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gbk*-*,"
"chinese-cns11643-6:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gbk*-*,"
"chinese-cns11643-7:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gbk*-*,"
"sjis:-*-medium-r-normal--14-*-jisx0208*-*"))
這個字元串的第一段是 fontset 的名稱,實際上也指定了英文(ascii字元集)字
體,後面的各段格式都是“字元集:字型”,分别為不同的字元集指定字型,例如
上面的定義中,ascii采用courier字型,chinese-gb2312采用simsun字型,以此
類推。
定義好了 fontset 以後,我們就可以讓 emacs 使用這個fontset了:
(set-default-font "fontset-courier")
另外,為了讓 emacs 建立新的 frame 時 (C-x 5 系列指令) 采用我們指定的
fontset,還要進行下面的設定:
(setq default-frame-alist
(append
'((font . "fontset-courier")) default-frame-alist))
** 在 ~/.Xdefaults 中定義 fontset
第二種定義 fontset 的方法是在 ~/.Xdefualts 中定義資源字元串:
Emacs.Fontset-0:-*-courier-medium-r-normal-*-14-*-*-*-*-*-fontset-courier,/
chinese-gb2312:-*-simsun-medium-r-*-*-14-*-*-*-c-*-*-*,/
mule-unicode-0100-24ff:-*-simsun-medium-r-*-*-14-*-*-*-c-*-iso10646*-*,/
korean-ksc5601:-*-*-medium-r-*-*-14-*-*-*-*-*-ksc5601*-*,/
chinese-cns11643-5:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gbk*-*,/
chinese-cns11643-6:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gbk*-*,/
chinese-cns11643-7:-*-simsun-medium-r-*-*-14-*-*-*-c-*-gbk*-*,/
sjis:-*-medium-r-normal--14-*-jisx0208*-*
然後讓 emacs 使用這個 fontset:
Emacs.font: fontset-courier
更改了 ~/.Xdefaults 的内容以後要執行:
xrdb .Xdefaults
指令,這樣更改才能起作用。
上述兩種方法都可以實作同樣的效果。但是有一點細微的差别,采用第一種方法
時,fontset 的定義是寫在 ~/.emacs 中的,而 emacs 啟動過程中,是先建立了
第一個視窗,然後才讀取 ~/.emacs 的,建立第一個視窗時,因為還沒有讀到我
們定義的 fontset, 是以它會采用 fontset-default 建立第一個視窗,當讀到我
們定義的 fontset 時,再進行調整,如果我們定義的 fontset 與預設的
fontset-default 字型差别比較大,就會看到emacs進行了一個調整視窗大小的動
作,這個動作延緩了 emacs 的啟動過程。而采用第二種方法則不會出現這個問題,
是以推薦使用第二種方法。
* Emacs23 (emacs-unicode-2 分支) 的字型設定
Emacs23的字型設定與上述方法類似,但也有所不同。或許是因為emacs23的實作
比較獨特,或許是emacs23的bug,按上述方法指定的中文字型無法起作用。是以,
emacs23的字型設定采用下述方法:
仍然采用 create-fontset-from-fontset-spec 建立 fontset:
(create-fontset-from-fontset-spec
"-*-courier-medium-r-normal-*-14-*-*-*-*-*-fontset-courier")
(set-default-font "fontset-courier")
(setq default-frame-alist
(append
'((font . "fontset-courier")) default-frame-alist))
也可以在 ~/.Xdefaults 中這樣設定:
Emacs.Fontset-0:-*-courier-medium-r-normal-*-14-*-*-*-*-*-fontset-courier
Emacs.font:fontset-courier
兩種方法取其一即可。
但是設定中文字型時,采用 set-fontset-font 分别指定各種 script 的字型:
(set-fontset-font
"fontset-default" nil
"-*-simsun-*-*-*-*-14-*-*-*-*-*-gb2312.1980-*" nil 'prepend)
(set-fontset-font
"fontset-courier" 'kana
"-*-simsun-*-*-*-*-14-*-*-*-*-*-gbk-0" nil 'prepend)
(set-fontset-font
"fontset-courier" 'han
"-*-simsun-*-*-*-*-14-*-*-*-*-*-gbk-0" nil 'prepend)
(set-fontset-font
"fontset-courier" 'cjk-misc
"-*-simsun-*-*-*-*-14-*-*-*-*-*-gbk-0" nil 'prepend)
* Emacs for Windows 的字型設定
在 Windows 下設定 emacs 字型隻能在 ~/.emacs 中進行,因為 windows 下沒
有與 ~/.Xdefaults 等同的東西。除了所用字型不同以外,設定方式與linux基
本相同。下面分别給出 windows 下 Emacs22 和 Emacs 23 的參考設定:
** Emacs22 for windows 字型設定
(setq w32-charset-info-alist
(cons '("gbk" w32-charset-gb2312 . 936) w32-charset-info-alist))
(setq default-frame-alist
(append
'((font . "fontset-gbk")) default-frame-alist))
(create-fontset-from-fontset-spec
(concat
"-outline-Courier New-normal-r-normal-normal-13-97-96-96-c-*-fontset-gbk,"
"chinese-gb2312:-outline-新宋體-normal-r-normal-*-14-*-96-96-c-*-iso10646-1,"
"mule-unicode-0100-24ff:-*-新宋體-normal-r-*-*-14-*-96-96-c-*-iso10646-1,"
"chinese-cns11643-5:-*-新宋體-normal-r-normal-*-14-*-96-96-c-*-iso10646-1,"
"chinese-cns11643-6:-*-新宋體-normal-r-normal-*-14-*-96-96-c-*-iso10646-1,"
"chinese-cns11643-7:-*-新宋體-normal-r-normal-*-14-*-96-96-c-*-iso10646-1"))
(set-default-font "fontset-gbk")
** Emacs23 for windows 字型設定
(setq w32-charset-info-alist
(cons '("gbk" w32-charset-gb2312 . 936) w32-charset-info-alist))
(setq default-frame-alist
(append
'((font . "fontset-gbk")) default-frame-alist))
(create-fontset-from-fontset-spec
"-outline-Courier New-normal-r-normal-normal-13-97-96-96-c-*-fontset-gbk")
(set-fontset-font
"fontset-default" nil
"-outline-新宋體-normal-r-normal-*-14-*-96-96-c-*-iso10646-1" nil 'prepend)
(set-fontset-font
"fontset-gbk" 'kana
"-outline-新宋體-normal-r-normal-*-14-*-96-96-c-*-iso10646-1" nil 'prepend)
(set-fontset-font
"fontset-gbk" 'han
"-outline-新宋體-normal-r-normal-*-14-*-96-96-c-*-iso10646-1" nil 'prepend)
(set-fontset-font
"fontset-gbk" 'cjk-misc
"-outline-新宋體-normal-r-normal-*-14-*-96-96-c-*-iso10646-1" nil 'prepend)
(set-fontset-font
"fontset-gbk" 'symbol
"-outline-新宋體-normal-r-normal-*-14-*-96-96-c-*-iso10646-1" nil 'prepend)
(set-default-font "fontset-gbk")
* 一些字型設定技巧
** 幾個字型相關的指令
M-x describe-char
我們可以使用這個指令檢視光标所在的字元采用的是什麼字型。
M-x describe-fontset
這個指令用來檢視各個字元集分别采用了什麼字型。
這兩個指令可以用來檢驗我們的設定是否發揮了作用。
** 設定字型的技巧(Dieken提供):
(1)在*scratch* buffer中輸入
(frame-parameter nil 'font)
光标放在行末按C-x C-e就可以看到目前字型;
(2)Shift + MouseLeftClick可以出來字型選擇對話框;
(3)M-x describe-font可以檢視目前字型描述
(4)M-x set-default-font <RET><TAB>可以看到可以選擇的字型。