如何改变中文字符宽度

emacs中算第几列时,一个中文字符等于两个英文占的列数,怎么把它改成一对一呢? 我找到这个:

谁能写个函数,运行一遍把所有字符都变成一列,然后还可以切换回去。 这个主要是用artist-mode画ditaa流程图时对齐用(中英文等宽)。

1 个赞

没发现什么好办法,Emacs 计算列号好像也不容易改,或许你可以报告个 Bug,因为很可能得要上游改代码。作为临时的方法,你可以自己计算个「列号」,比如:

(define-minor-mode your-column-number-mode
  "显示至行首的字符数目."
  :lighter (:eval (format " [%d]" (length (buffer-substring
                                           (line-beginning-position)
                                           (point))))))

注意启用这个 Minor Mode 会有时(比如移动光标)会减慢 Emacs,所以只在你需要的 Buffer 启用它,它是个 buffer-local 的 Minor Mode。

问题不是计算列号,而是artist-mode画方框的坐标是列号(中文占俩宽度),而ditaa所有字符等宽,所以中英字符不等宽,方框没法对齐(封口)。另外,在org-table也无法实现对齐。

主题引用连接好像实现了改变字符宽度,如果默认用unicode,所有unicode等宽,应该就解决了,要是有个函数在两种状态下切换就好了。

https://gist.github.com/jj1bdx/4e5b0b92c2a05281d7b68188568a0763

https://github.com/hamano/locale-eaw/blob/master/EastAsianWidth.txt

https://raw.githubusercontent.com/hamano/locale-eaw/master/eaw.el

(defun unicode-char-range ()
'((#x00 . #xFFFF)))

(defvar default-char-width-table)

(setq default-char-width-table char-width-table)

; for over 23 (checked work in emacs 24)
(defun ditaa-set-char-width ()
(interactive)
(while (char-table-parent char-width-table)
        (setq char-width-table (char-table-parent char-width-table)))
(let ((table (make-char-table nil))
        (width 1))
    (dolist (range (unicode-char-range))
    (set-char-table-range table range width))
    (optimize-char-table table)
    (set-char-table-parent table char-width-table)
    (setq char-width-table table)))

(defun ditaa-unset-char-width ()
(interactive)
(setq char-width-table default-char-width-table))

有个疑问

现在英文也和中文一样占两格字符么,还是都占一格字符,你是如何设置的?

应当改进 ditaa 吧,即使在 Emacs 中能用了,用其它编辑器打开时还是不能对齐。

其他我不管,中文和英文等宽,都是一个字符可以这样设置(抄别人的)

(set-font emacs-english-font emacs-cjk-font '(20 . 12))

这个给 ob-ditaa 添加一个前处理 hook,估计也可以, 就是这个hook函数不太好写

原来你们两位已经讨论过这个问题了,才发现论坛也有一帖 ditaa 绘图中显示中文的问题

按这种方法设置,中文会不会太小了? 根本问题还是 ditaa 的功能过于简单了。


另外,看到你另一个 issue,org-table 用的是 string-width 来对齐表格的,不需要再另外设置 char-width-table 。所以 set-font 的方案行不通,使用默认的设置就可以对齐了。

发现行的通,绕了一个圈子 :wink: