我打算用 Emacs 导出代码块到 HTML,并添加语法高亮。
比如 Emacs Lisp Mode 下的这样一句代码:
(defun foo () "A Function." 42)
Emacs 高亮之后会给出这样的 String,但是有没有现成的办法获得后面的全部的 Text Properties?
#("(defun foo () \"A Function.\" 42)" 0 1
(fontified t)
1 6
(fontified t face font-lock-keyword-face)
6 7
(fontified t)
7 10
(fontified t face font-lock-function-name-face)
10 11
(fontified t)
11 12
(fontified t)
12 13
(fontified t)
13 14
(fontified t)
14 26
(fontified t face font-lock-doc-face)
26 27
(fontified t face font-lock-doc-face)
27 28
(fontified t)
28 30
(fontified t)
30 31
(fontified t))
我暂时用 next-property-change
,但当初实现起来有些痛苦,一开始就先上面的思路应该会轻松不少。
我也有这样的疑惑,明明 buffer-string
/buffer-substring
返回值携带了所有的信息,为什么不能好好利用呢?
在 EmacsWiki: mon-text-property-utils.el 的 mon-get-text-properties-region
函数看到一种不走寻常路的操作:
(setq mgtpr-bfr-str (substring (format "%S" (buffer-substring start end)) 1))
(setq mgtpr-bfr-str (car (read-from-string mgtpr-bfr-str)))
把 buffer-string
/buffer-substring
返回的内容再次 format。然后去掉前面的 #
号,再读回来变成一般的 list。
2 个赞
刚刚想到这个帖子。
顺便测试了一下,打印再读取的效率比 format 更高:
(defun propertized-text-to-list (text)
"Convert propertized TEXT to list."
(with-temp-buffer
(prin1 text (current-buffer))
(goto-char (point-min))
(when (looking-at "#(")
(forward-char 1)
(read (current-buffer)))))
(with-temp-buffer
(emacs-lisp-mode)
(insert "(defun foo () \"A Function.\" 42)")
(list (benchmark-run 1000
(propertized-text-to-list (buffer-string)))
(benchmark-run 1000
(mon-get-text-properties-region (point-min) (point-max)))))
;; => ((0.076705 0 0.0)
;; (0.305013 1 0.2189820000000111))
4 个赞