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

我的 emacs 版本是 28.2. 初步判定对不齐是 org 版本的原因

  • emacs -Q 情况下, 加载更纱黑体, 可以对齐 (此时用 emacs 内置 org 9.5.5)
  • emacs 空白 init 文件的情况下, 加载更纱黑体, 对不齐 (此时用的是 melpa 下载的 org 9.6.5)
  • emacs 空白 init 文件的情况下, 将 elpa/org-9.6.5/ 路径从 load-path 中删除后, 加载更纱黑体, 可以对齐 (此时用的是 emacs 内置的 org 9.5.5)

在用空白 init 配置的情况下,我没有额外的 early-init 配置.

所谓的“对不齐”, 实际上也不是真正的对不齐, 而是按 tab 以后, 中文所在的 cell 都会奇怪地多出几个空格, 如下图所示. 如果手动将这些空格删除掉以后, 是可以对齐的.

现在问题是,如果我要用最新的 org,就要面对这种“对不齐”的情况,不知道如何解决.

不妨把你的 emacs -Q 配置帖出来。

我没有任何 emacs -Q 配置。就是直接的 emacs -Q. 然后在 scratch 里手动执行了一个设置 org table 字体的 sexp,也就是图中顶部的 sexp

试试从这个修改一下,来源是Org维护者Ihor。之前在doom那个帖子里发过一次。

(setf (alist-get "Sarasa UI SC" face-font-rescale-alist
                 nil nil #'equal)
      (/ 16.0 13.0))

这里,把sarasa换成你要的字体,然后把底下的(/ 16.0 13.0)换成其他的算式试试。

这个问题的根本原因是此字体的中文与英文的字宽比不是2。

谢谢回复. 但是我的字体应该是严格2:1的

我和你用的几乎同样的字体 (Sarasa Fixed SC Nerd Font),org-version 9.6.1,对齐没有问题。

我也出现过这样的问题,新版本的没有对齐,解决方式是暂时使用旧版的字符宽度

(advice-add #'org-string-width :override #'org--string-width-1)
1 个赞

这个完美解决了, 谢谢!

刚刚我又重新看了一遍新版的代码,之前理解有误,如果专门设置了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 个赞

如果remove下面是新版本代码(无修改),可以考虑用advice-add :around

用代码才能确保别人也能准确复现问题。用文字描述,别人看不到(/不确定)你言语之外的动作。

另外,我用谷歌搜索 Sarasa Nerd Font 第一个链接下载的字体[1]的名字是 Sarasa Term SC Nerd Font,末尾多一个 “Font”。

$ /path/to/emacs-29/emacs -Q --eval "\
  (progn
    (switch-to-buffer \"*.org\")
    (org-mode)
    (set-face-attribute 'org-table nil :font \"Sarasa Term SC Nerd Font\")
    (insert \"\
  |hello word|
  |-|
  |aligment|
  |中文对齐|\")
    (goto-char 18)
    (execute-kbd-macro (kbd \"TAB\")))"

[1] https://github.com/jonz94/Sarasa-Gothic-Nerd-Fonts/releases/download/v0.40.7-0/sarasa-term-sc-nerd-font.zip

谢谢你的回复. 在 emacs -Q 情况下我没有需要复现的问题, 中英是可以对齐的. 我的字体名称应该是全名, 后面不能加 Font, 否则找不到这个字体. 我的字体来源于链接

Should be fixed on Org side: emacs/org-mode.git - Emacs Org mode

2 个赞