org 9.6.5 用更纱黑体后, org 表格中文对不齐?

刚刚我又重新看了一遍新版的代码,之前理解有误,如果专门设置了org-table字体为更纱,那么还是使用旧版的 org--string-width-1 好,如果不专门指定org-table字体,新版本org体验会比旧版本好一点

新版 org-string-width 在一个temp buffer中分别插入了需要计算的string以及字符a,得到它们像素宽度,以字符a为单位,计算string是多宽,比如需要得到“我的”像素宽度是14,字符a的像素宽度是7,那么这个“我的”宽度是2

这里通过像素获取更精细的宽度,解决表格对齐的问题,但是这里存在的问题是

  1. 插入字符串的时候是并没有带字体属性的,所以计算的string以及字符a是按默认字体来的,而 org-table 中的字体和默认字体是不一样的,最终计算是有偏差的
  2. 即使按照像素级别获取,如果字体不是刚好二倍的话,最终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,走这里
4 个赞