刚刚我又重新看了一遍新版的代码,之前理解有误,如果专门设置了org-table字体为更纱,那么还是使用旧版的 org--string-width-1 好,如果不专门指定org-table字体,新版本org体验会比旧版本好一点
新版 org-string-width 在一个temp buffer中分别插入了需要计算的string以及字符a,得到它们像素宽度,以字符a为单位,计算string是多宽,比如需要得到“我的”像素宽度是14,字符a的像素宽度是7,那么这个“我的”宽度是2
这里通过像素获取更精细的宽度,解决表格对齐的问题,但是这里存在的问题是
- 插入字符串的时候是并没有带字体属性的,所以计算的string以及字符a是按默认字体来的,而
org-table中的字体和默认字体是不一样的,最终计算是有偏差的 - 即使按照像素级别获取,如果字体不是刚好二倍的话,最终table还是对不齐的。不过相比旧版本还是会好很多,宽度上差的不会特别多
下面是新版的 org-string-width 源码,我把重点摘出来了
(defun org-string-width (string &optional pixels)
(if (and (version< emacs-version "28") (not pixels))
(org--string-width-1 string) ; 降级使用旧版本的,新版本会走下面
(remove-text-properties 0 (length string)
'(wrap-prefix t line-prefix t)
string)
(unless pixels
(remove-text-properties 0 (length string) '(face t) string))
(let (
;; ...
)
(with-temp-buffer
(let (pixel-width symbol-width)
(with-silent-modifications
(erase-buffer) ; temp buffer 中插入需要计算长度的string,算出pixel width
(insert string)
(setq pixel-width
(car (window-text-pixel-size
nil (line-beginning-position) (point-max))))
(unless pixels
(erase-buffer)
(insert "a")
(setq symbol-width ; temp buffer 中插入需要字符a,算出一个字符的pixel width
(car (window-text-pixel-size
nil (line-beginning-position) (point-max))))))
(if pixels
pixel-width
(/ pixel-width symbol-width))))))) ; org-table-align中pixels参数是nil,走这里