测试发现,face / text-property 在 batch 模式下不起作用了,例如以下代码:
⋊> /Applications/Emacs-26.1.app/Contents/MacOS/Emacs --batch --eval \
'(with-current-buffer (generate-new-buffer "*test*")
(insert "(defun hello (name)
\\"Greet a per|son.\\"
(message \\"hello, %s\\" name))")
(emacs-lisp-mode)
(eval-buffer)
(hello "foo") ;; ensure hello function
(goto-char (point-min))
(re-search-forward "|") ;; move cursor to |
(message "%S"
(list :point (point)
:char (char-to-string (char-before))
:props (text-properties-at (point)))))'
期望结果是这样的:
hello, foo
(:point 36 :char "|" :props (face font-lock-doc-face fontified t))
实际结果是这样的:
hello, foo
(:point 40 :char "|" :props nil)
那么应该如何测试 face / text-property 相关的代码?
UPDATE
加入:
(let ((noninteractive nil))
(font-lock-mode 1))
得到:
hello, foo
(:point 36 :char "|" :props (fontified nil))
有点接近了
;; play.el
(with-temp-buffer
(insert "(defun foo ())")
(emacs-lisp-mode)
(let ((noninteractive nil))
(font-lock-mode)
(font-lock-ensure))
(message "%S" (buffer-string)))
效果:
~ $ emacs -Q --batch -l play.el
#("(defun foo ())" 1 6 (face font-lock-keyword-face) 7 10 (face font-lock-function-name-face))
~ $
跟这个话题相关的,有个用 Emacs 实现的带语法高亮的 Pager,感觉很酷:
1 个赞
Emacs 25 才开始有 font-lock-ensure
函数,如需兼容更早的版本:
(let ((noninteractive nil))
(font-lock-mode 1)
- (font-lock-ensure))
+ (font-lock-set-defaults)
+ (jit-lock-fontify-now (point-min) (point-max)))
我的 shr-tag-pre-highlight.el
用过下面的代码,不记得从哪里抄来的了。
(if (fboundp 'font-lock-ensure)
(font-lock-ensure)
(with-no-warnings
(font-lock-fontify-buffer)))
(with-no-warnings
(font-lock-fontify-buffer))
在 24.4 下无效。
从定义看,font-lock-fontify-buffer
和 font-lock-ensure
几乎是一样的,差别在于是否 interactive:
(defun font-lock-fontify-buffer (&optional interactively)
"Fontify the current buffer the way the function `font-lock-mode' would."
(declare
(interactive-only "use `font-lock-ensure' or `font-lock-flush' instead."))
(interactive "p")
(font-lock-set-defaults)
(let ((font-lock-verbose (or font-lock-verbose interactively)))
(funcall font-lock-fontify-buffer-function)))
(defun font-lock-ensure (&optional beg end)
"Make sure the region BEG...END has been fontified.
If the region is not specified, it defaults to the entire accessible
portion of the buffer."
(font-lock-set-defaults)
(funcall font-lock-ensure-function
(or beg (point-min)) (or end (point-max))))
关键在于变量 font-lock-ensure-function
所指的函数 jit-lock-fontify-now
。24.4 没有这个变量,也就没有调用到 jit-lock-fontify-now
。
另外,再补充一点。直接在 (with-temp-buffer ...)
中调用 font-lock-ensure
也是无效的,这点在 e2ansi 中也有提到:
(defun e2ansi-batch-convert-file (file &optional mode dest)
(if (file-exists-p file)
(let ((large-file-warning-threshold nil))
(with-temp-buffer
;; Font-lock isn't activated on temporary buffers, i.e.
;; buffers whose name start with a space.
(rename-buffer "*e2ansi*" 'unique)
(insert-file-contents file 'visit)
(normal-mode)
(e2ansi-batch-convert-buffer (current-buffer) mode dest)))
(e2ansi-user-error "File not found: %s" file)))
必须要进行一些特别处理,或者简单点,用 (with-current-buffer ...)
避开问题。
最近写测试的时候遇到一个问题,font-lock-ensure
在 Emacs 25.1 上莫名的锁死:
⋊> emacs-25.1 --batch --eval "(with-temp-buffer
(python-mode)
(insert \" '''dosctring'''\")
(font-lock-mode 1)
(font-lock-ensure))"
把 docstring 前面的空格取掉就能过了,我也不清楚为啥那个几空格是有什么魔法,能吃掉 100% 的CPU。
类似的问题在 27.0 仍然发生:https://lists.gnu.org/archive/html/bug-gnu-emacs/2018-12/msg00602.html
twlz0ne:
不清楚为啥那个几空格是有什么魔法
原因是 python-info-docstring-p
函数里的 while 死循环了:
到 emacs-mirror/emacs@3ef4ee8
才修复。
1 个赞