博客 / 詳情

返回

Emacs 素顏淡妝

=> 上一篇:為 Emacs 配置字體,你可曾認真過?

前言

此刻,我在 Linux mint 桌面環境使用 Emacs 的圖形界面模式。我感覺它有些醜陋。美觀固然不必追求,但醜陋也不必容忍。其醜陋之處在於,文字行距過於緊密,且兩側邊界的顏色過淺,背景色較深,不倫不類。

我的 Emacs 原始外觀

行距

Emacs 緩衝區裏的文字行距是由變量 line-spacing 控制,其值默認為 nil

在 Elisp 中,可使用 setq 為變量賦值,例如

(setq a 1
      b 2
      c 3)

上述代碼為變量 abc 分別賦以 1,2 和 3,亦即 setq 表達式可為一組變量賦值。

setq 可將 line-spacing 值設為 4 個像素,如下

(setq line-spacing 4)

不過,line-spacing 是緩衝區局部變量(Buffer-local variable),若對上述表達式求值,只有當前緩衝區的文字行距會發生變化,其他緩衝區則不受影響。

倘若你不想每次開啓緩衝區,都要設定一次 line-spacing 的值,對於此類緩衝區局部變量的賦值,一勞永逸的方法是使用 setq-default 直接為此類變量設定默認值。setq-default 的用法與 setq 相同。

(setq-default line-spacing 4)

縮進

若主要是用 Emacs 編寫代碼,可能會遇到製表符不一致而導致的代碼縮進混亂,原因是製表符的寬度並不固定,有的軟件將其設為 4 個空格寬度,有的則設為 8 個空格寬度。故而,你在 Emacs 裏編寫的代碼,在其他軟件裏打開,可能會出現縮進混亂的情況。為了避免這種情況,建議禁用製表符,讓 Emacs 自動以空格作為代替,亦即在 init.el 中添加以下設定:

(setq-default indent-tabs-mode nil) ;; 用空格代替 Tab

由於 indent-tabs-mode 是緩衝區局部變量,倘若用 Emacs 編輯諸如 Makefile 之類必須使用製表符的文件,對應的編輯模式會主動將這個變量設為 t,從而啓用製表符。

練習:執行 C-h v tab-width RET,查看緩衝區局部變量 tab-width 的説明。

顏值

Emacs 的 set-face-attribute 函數能夠修改緩衝區背景、邊框以及模式行的顏色,所謂模式行即緩衝區與微緩衝區之間的工具條,用於顯示緩衝區的名字、文字行號、編輯模式等信息。若在圖形界面模式下,模式行提供了可與鼠標交互的菜單功能。

Emacs 默認的緩衝區背景色較深,可以使用以下代碼將其修改為銀色:

(set-face-attribute 'default nil :background "#f0f0f0")

set-face-attribute 的第一個參數表示要修改的顏面(Face)類型,若該參數為 'default,表示默認的顏面,或者最大的顏面,不妨將其理解為主顏面,即框架的外觀。第二個參數是顏面所在的框架,若其值為 nil 則表示當前框架。其餘參數皆為鍵值對,例如 :background 是鍵,表示顏面的背景,#f0f0f0 是值,是銀白色。

接下來,繼續用 set-face-attribute 設置框架兩側邊框的顏色:

(set-face-attribute 'fringe nil :background "#f0f0f0")

框架兩側的邊框叫作 'fringe,其背景色與 'default 顏面相同,亦即邊框顏色與框架背景色相同。

以下代碼設置模式行的背景,並將其邊框線寬設為 2 個像素,邊框顏色設為藍灰色。

(set-face-attribute 'mode-line nil
                    :background "#e0e0e0"
                    :box `(:line-width 2 :color "#a1afc9"))

當 Emacs 存在多個窗口時,每個都會有一個模式行,但是隻有輸入焦點所在的窗口,其模式行是激活狀態,其他窗口的模式行皆為非激活態。Emacs 也允許定製非激活態的模式行外觀,如下:

(set-face-attribute 'mode-line-inactive nil
                    :background "#f0f0f0"
                    :box `(:line-width 1 :color "#a1afc9"))

這一切應該不難理解,動手一試,便知其意。

set-face-attribute 能修改 Emacs 中的一切顏面,前提是你需要知道它們的名字。M-x list-faces-display 可以查看全部顏面的名字。

函數

上文對框架外觀的設定,有幾處使用了相同的顏色值 #f0f0f0,即框架的背景、框架兩側邊框的背景以及非激活態模式行的背景,所用顏色相同,激活態模式行的背景色是 #e0e0e0,較 #f0f0f0 略深一些。模式行的邊框顏色相同,只是線寬有差異。我們可以將整個外觀設定過程定義為一個函數,將顏色值作為函數的參數傳入,不僅是的外觀定製過程更為集中,也便於以後修改外觀顏色。

Elisp 函數定義形式如下

(defun 函數名 (參數表)
    函數體)

將上文對 Emacs 外觀的所有設定封裝為函數 my-theme

(defun my-theme (bg-color mode-line-bg-color)
    (setq-default line-spacing 4)
    (set-face-attribute 'default nil :background bg-color)
    (set-face-attribute 'fringe nil :background bg-color)
    (set-face-attribute 'mode-line nil
                        :background mode-line-bg-color
                        :box '(:line-width 2 :color "#a1afc9"))
    (set-face-attribute 'mode-line-inactive nil
                        :background bg-color
                        :box '(:line-width 1 :color "#a1afc9")))

需要注意的是,函數的定義也是一個表達式,Emacs 對其求值結果是函數名,你不妨在函數定義後面 C-x C-e 一試。my-theme 的用法如下:

(my-theme "#f0f0f0" "#e0e0e0")

Emacs 對上述代碼求值,便可完成外觀設定。

新顏

上文所作的一切設定,只對 Emacs 的圖形界面模式有效,故而相關代碼應當放在 init.el 文件裏的 when 表達式中。希望你沒有忘記,我們已在 when 表達式裏設定了字體。現在若加入文字行距與框架組件背景色的設定,代碼應當如下:

(when window-system
    ;;配置中英文字體
    (set-frame-font (font-spec :name "Monaco" :size 12))
    (dolist (script '(han cjk-misc bopomofo))
        (set-fontset-font 
            (frame-parameter nil 'font) 
            script
            (font-spec :name "Microsoft YaHei" :size 12)))
    ;;配置 Emacs 框架外觀
    (my-theme "#f0f0f0" "#e0e0e0"))

上述代碼中的分號,是 Elisp 語言的註釋符。每行註釋,只需以一個分號作為開頭即可。我習慣寫兩個分號,是為了讓註釋更醒目一些。現在,我的 Emacs 外觀變成了如下圖所示的樣子,我已對它已基本滿意。

換了新顏

總結

許多人的 Emacs 外觀配置得遠比我的精美,這意味着他們的 (when window-system ...) 表達式中增加的代碼會多一些,故而他們的 init.el 的可維護性會差一些,於是他們的 Emacs 啓動速度會慢一些,應變的能力也會弱一些。

也許任何事物,其外觀和性能本質上是混而為一的,即所謂的,色不異空,空不異色;色即是空,空即是色;受想行識,亦復如是。倘若你需要將 Emacs 作為禮器,可執着於色相。倘若你需要將 Emacs 作為工具甚至武器,需守着它的空性。

=> 下一篇:Emacs 的一些本能
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.