(注意:Emacs 24 以上限定)
在 Emacs 裡 propertizing text (例如:給文字上色) 的大小事,不論是自己自訂 syntax highlight,或者要自己寫 mode 時都需要用到。分成兩個部份:
- 定義新的 face。
- 把 face 套用到文字上。
defface:定義 face
要給文字上色或加粗,你可以直接拿內建已經有的那些 font-faces 來用(可使用 M-x list-faces-display
查看整個目前環境可用的 font-faces 列表),也可以自己使用 defface
定義自己的 font-faces。
- (defface FACE SPEC DOC &rest ARGS)
1 | (defface test-face |
來看看複雜的例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16(defface highlight ;FACE
'( ;SPEC
(((class color) (min-colors 88) (background light))
:background "darkseagreen2")
(((class color) (min-colors 88) (background dark))
:background "darkolivegreen")
(((class color) (min-colors 16) (background light))
:background "darkseagreen2")
(((class color) (min-colors 16) (background dark))
:background "darkolivegreen")
(((class color) (min-colors 8))
:background "green" :foreground "black")
(t :inverse-video t)
)
"Basic face for highlighting." ;DOC
:group 'basic-faces)
一般是不用到那麼複雜。
麻煩的 SPEC
SPEC 的格式是:1
((DISPLAY . ATTS)...)
DISPLAY
用來定義終端機內有限顏色時如何顯示。有三種可能:default, t 或一個 list(上面的例子就是 list),我覺得這太麻煩了就沒理他,有興趣的可以看 C-h f defface
與 Defining Faces - GNU Emacs Lisp Reference Manual。
ATTS
真正用來定義 text properties 的部份,截至 Emacs 24.3 為止,可用的 ATTS 有 :width
, :height
, :weight
, :slant
, :underline
, :overline
, :strike-through
, :box
, :foreground
, :background
, :stipple
, :inverse-video
, :inherit
。關於各項 ATTS 詳細說明請看 Face Attributes - GNU Emacs Lisp Reference Manual。
:inherit
可以使用 :inherit
直接抓現有的 face 來套用。例如 markdown-italic-face
就直接抓了 font-lock-variable-name-face
套用上去,然後再自己加上 italic:
1 | (defface markdown-italic-face |
給 text 加上 property
定義完 face 後,給 text 加上 property 有幾種作法:
- put-text-property
- add-text-properties
- set-text-properties
- propertize (有回傳值,最簡單)
以及移除 property 用的
- remove-text-properties
以下所有的測試,請注意要在
fundamental-mode
(純文字)下,不然輸出的顏色可能會被目前的 mode 蓋過去而無效。
名子很像的三個 function
(put-text-property START END PROPERTY VALUE &optional OBJECT)
給 text 賦予單一屬性(PROPERTY)。PROPERTY
和VALUE
,前者為屬性,後者為值。 如'bold t
或'face 'font-lock-preprocessor-face
START 和 END 為 position,如果輸入的 OBJECT 是 variable,position 會從 0 開始算,
如果缺乏 OBJECT 或者是 nil,會抓目前 buffer 作為 OBJECT。(add-text-properties START END PROPERTIES &optional OBJECT)
給 text 同時賦予多種屬性(PROPERTIES)。
用 list 來表示多項目,如'(bold t italic t)
。
其餘事項同put-text-property
。
1 | ;; GNU 文件的範例 |
- (set-text-properties START END PROPERTIES &optional OBJECT)
把 text 的屬性完整的覆蓋掉。PROPERTIES 方法同上,只是當它的值為 nil 時,意義即為「移除文字所有屬性」。
Examples:
注意兩者的 prop 用法差別:1
2
3
4
5
6
7
8
9;; add-text-properties
(let ((s "Shirohime Kanata"))
(add-text-properties 0 (length s) '(face font-lock-preprocessor-face) s)
(insert s))
;; put-text-property
(let ((s "Shirohime Kanata"))
(put-text-property 0 (length s) 'face 'font-lock-preprocessor-face s)
(insert s))
- 以上兩者的回傳值皆只有
t
或nil
:「成功加上了」和「沒加」兩種意義。- 是直接改 variable 的值(所以輸入必須是 variable 不能是 string,不然會爆掉),是有副作用的 function。
還有一種方法是 propertize
:
- (propertize STRING &rest PROPERTIES)
1 | (propertize "String" |
- 這種方法最簡單,可以用直接用 string 作為輸入,不需要 variable。(因此他也不會改 variable 的值)。
- 直接吐給你上好了顏色的字。
- 可以同時放一堆屬性。