42.10 显示文本尺寸

由于并非所有字符宽度相同,下列函数可用于检查字符宽度。相关函数参见 See 基础缩进函数按屏幕行移动

Function: char-width char

该函数返回字符 char 在当前缓冲区中显示时的列宽(即考虑缓冲区的显示表,如有;see 显示表)。 制表符的宽度通常为 tab-width(see 常规显示规则)。

Function: char-uppercase-p char

char 按 Unicode 标准为大写字符,则返回非 nil

Function: string-width string &optional from to

该函数返回字符串 string 在当前缓冲区与选中窗口中显示时的列宽。 可选参数 fromto 指定要计算的子串,其解释方式与 substring 相同(see 创建字符串)。

返回值为近似值:仅依据各字符的 char-width 计算,始终将制表符视为占用 tab-width 列, 忽略显示属性与字体等。出于这些原因,建议改用下文介绍的 window-text-pixel-sizestring-pixel-width

Function: truncate-string-to-width string width &optional start-column padding ellipsis ellipsis-text-property

该函数返回一个新字符串,它是 string 截断后适配显示宽度 width 列的结果。

string 窄于 width,结果与原串相同;否则从结果中省略多余字符。 若 string 中的多列字符超出目标宽度 width,该字符会被省略。因此结果有时会短于 width, 但绝不会超出。

可选参数 start-column 指定起始列,默认为 0。若该参数非 nil,字符串前 start-column 列 会从结果中省略。若 string 中的某个多列字符跨越 start-column 列,则该字符会被省略。

可选参数 paddingnil 时,为填充字符,添加在结果串首尾,使其恰好占满 width 列。 若结果长度不足 width,会在末尾追加填充字符,直至达到宽度要求。若 string 中的多列字符 跨越 start-column 列,也会在开头前置填充字符。

ellipsisnil,它应为一个字符串,用于在截断时替换 string 的末尾部分。 此时会从 string 中移除更多字符,为省略号留出足够空间以适配 width 列。 但若 string 的显示宽度小于省略号的显示宽度,则不会追加省略号。 若 ellipsisnil 且非字符串,则代表函数 truncate-string-ellipsis 的返回值,详见下文。

可选参数 ellipsis-text-propertynil 时,表示不实际截断字符串,而是用带有省略号的 display 文本属性(see display 属性)隐藏 string 的多余部分。

(truncate-string-to-width "\tab\t" 12 4)
     ⇒ "ab"
(truncate-string-to-width "\tab\t" 12 4 ?\s)
     ⇒ "    ab  "

该函数在字符串过宽时使用 string-widthchar-width 确定合适的截断点, 因此存在与 string-width 相同的基础问题。特别地,当 string 内发生字符组合时, 字符串的显示宽度可能小于各字符宽度之和,该函数可能返回不准确结果。

Function: truncate-string-ellipsis

该函数返回在 truncate-string-to-width 及其他类似场景中使用的省略号字符串。 若变量 truncate-string-ellipsisnil,则使用其值;若选中框架可显示 Unicode 字符 U+2026 水平省略号(U+2026 HORIZONTAL ELLIPSIS),则使用该单字符字符串,否则使用字符串 ‘...’。

下列函数返回文本在指定窗口中显示时的像素尺寸。该函数被 fit-window-to-bufferfit-frame-to-buffer(see 调整窗口大小)用于将窗口调整为恰好容纳其包含文本的大小。

Function: window-text-pixel-size &optional window from to x-limit y-limit mode-lines ignore-line-at-end

该函数以像素为单位返回 window 缓冲区中文本的尺寸。window 必须为活动窗口,默认为当前选中窗口。 返回值为一个 cons 对,包含任意文本行的最大像素宽度与所有文本行的最大像素高度。 该函数用于让 Lisp 程序根据需显示的缓冲区文本调整 window 尺寸,以及其他类似场景。

返回值还可(见下文)可选包含首个被测量尺寸行的缓冲区位置。

可选参数 fromnil 时指定要考虑的首个文本位置,默认为缓冲区最小可访问位置。 若 fromt,则代表非换行符的最小可访问位置。若 from 为 cons 对, 其 car 指定缓冲区位置,cdr 指定从该位置到待测量文本首屏行的垂直像素偏移。 (测量将从该行的视觉起始位置开始。)此时返回值为列表,包含像素宽度、像素高度与被测量首行的缓冲区位置。 可选参数 tonil 时指定最后一个待考虑的文本位置,默认为缓冲区最大可访问位置。 若 tot,则代表非换行符的最大可访问位置。

可选参数 x-limitnil 时指定忽略文本的最大 X 坐标;因此也是函数可返回的最大像素宽度。 若 x-limitnil 或省略,则使用 window 主体的像素宽度(see 窗口尺寸); 该默认值表示会忽略宽于窗口的截断行文本。当调用者不打算更改 window 宽度时,此默认值很有用。 否则调用者应在此指定 window 主体可能的最大宽度;特别地,若预期存在截断行且需计入其文本, 应将 x-limit 设为较大值。由于计算长行宽度会耗时,尽可能减小该参数值是明智的; 尤其当缓冲区可能包含无论如何都会被截断的长行时。

可选参数 y-limitnil 时指定忽略文本的最大 Y 坐标;因此也是函数可返回的最大像素高度。 若 y-limitnil 或省略,则考虑直至 to 指定缓冲区位置的所有文本行。 由于计算大缓冲区的像素高度耗时,指定该参数很有意义;尤其当调用者未知缓冲区大小时。

可选参数 mode-linesnil 或省略时,返回值不包含 window 的模式行、制表行或标题行高度。 若为符号 mode-linetab-lineheader-line,则仅在返回值中计入对应行(若存在)的高度。 若为 t,则在返回值中计入所有这些行(若存在)的高度。

可选参数 ignore-line-at-end 控制是否将 to 所在屏行的文本高度计入返回的像素高度。 若 Lisp 程序仅关心直至 to 所在屏行视觉起始位置(不含该行)的文本尺寸,此参数很有用。

window-text-pixel-size 将窗口中显示的文本视为整体,不关心单行尺寸。下列函数则关注单行。

Function: window-lines-pixel-dimensions &optional window first last body inverse left

该函数计算指定 window 中显示的每一行的像素尺寸。它通过遍历 window 当前的字形矩阵 ——存储当前窗口中显示的每个缓冲区字符的字形(see 字形)的矩阵——实现。 若执行成功,返回一组 cons 对列表,表示每行最后一个字符右下角的 X 与 Y 坐标。 坐标以像素为单位,原点 (0,0) 位于 window 左上角。window 必须为活动窗口,默认为当前选中窗口。

若可选参数 first 为整数,表示待返回的 window 字形矩阵首行索引(从 0 开始)。 注意若 window 有标题行,索引 0 行为标题行。若 firstnil, 待考虑首行由可选参数 body 决定:若 bodynil,则从 window 主体首行开始, 跳过标题行(若存在)。否则从 window 字形矩阵首行开始,可能为标题行。

若可选参数 last 为整数,表示待返回的 window 字形矩阵末行索引。 若 lastnil,待考虑末行由 body 决定:若 bodynil, 则使用 window 主体末行,省略模式行(若存在)。否则使用 window 末行,可能为模式行。

可选参数 inversenil 时,每行返回的 Y 像素值表示从 window 左边缘 (若 bodynil 则为主体边缘)到该行最后一个字形右边缘的像素距离。 inversenil 时,每行返回的 Y 像素值表示从该行最后一个字形右边缘到 window 右边缘(若 bodynil 则为主体边缘)的像素距离。 这对计算每行末尾的空余空间很有用。

可选参数 leftnil 时,返回每行最左侧字符左下角的 X 与 Y 坐标。 该值适用于主要显示从右至左文本的窗口。

leftnilinversenil, 则每行返回的 Y 像素值表示从该行最后(最左)字形左边缘到 window 右边缘 (若 bodynil 则为主体边缘)的像素距离。若 leftinverse 均非 nil, 则每行返回的 Y 像素值表示从 window 左边缘(若 bodynil 则为主体边缘) 到该行最后(最左)字形左边缘的像素距离。

window 当前字形矩阵未更新(通常发生在 Emacs 繁忙时,例如处理命令时),该函数返回 nil。 不过在零秒延迟的空闲计时器中运行此函数时,应可获取有效值。

Function: buffer-text-pixel-size &optional buffer-or-name window x-limit y-limit

该函数与 window-text-pixel-size 类似,但可在缓冲区未显示在窗口中时使用。 (缓冲区已显示时 window-text-pixel-size 更快,因此该场景不应使用本函数。)

buffer-or-name 必须指定活动缓冲区或其名称,默认为当前缓冲区。window 必须为活动窗口, 默认为选中窗口;函数会按缓冲区在 window 中显示的方式计算文本尺寸。 返回值为一个 cons 对,包含 buffer-or-name 指定缓冲区可访问部分中任意文本行的最大像素宽度 与所有文本行的像素高度。

可选参数 x-limity-limit 含义与 window-text-pixel-size 相同。

若需测量缓冲区部分文本的尺寸,可在调用本函数前将缓冲区缩窄至该部分(see 范围限制)。

Function: string-pixel-width string

这是一个便捷函数,使用 window-text-pixel-size 计算 string 的像素宽度。 注意:若调用该函数测量含内嵌换行符的字符串宽度,它将返回不含换行符的最宽子串宽度。 该结果表示字符串插入缓冲区后所占用的最宽行宽度。

Function: line-pixel-height

该函数返回选中窗口中点所在行的像素高度。该值包含该行的行间距(see 行高)。

Function: string-glyph-split string

当启用字符组合时,一系列字符可组合显示为 字形簇(grapheme clusters),例如显示重音字符、连字、Emoji, 或复杂文本塑形要求某些书写系统如此处理时。此时字符与显示列不再是简单映射关系, 对这类字符串进行布局决策(如截断过宽字符串)会变得复杂。该函数可协助完成此类工作: 它将参数 string 拆分为子串列表,每个子串生成一个应作为整体显示的单个字形簇。 Lisp 程序可使用该列表构造视觉上合法、显示正常的 string 子串, 或通过累加返回列表中各组成部分的宽度计算任意子串宽度等。

例如,若想显示去掉首个字形的字符串,可使用:

(apply #'insert (cdr (string-glyph-split string))))

当缓冲区带行号显示时(see Display Custom in The GNU Emacs Manual), 有时需要知道行号占用的宽度。下列函数供需要此信息进行布局计算的 Lisp 程序使用。

Function: line-number-display-width &optional pixelwise

该函数返回选中窗口中行号显示所用宽度。若可选参数 pixelwise 为符号 columns, 返回值为框架标准列的浮点数;若 pixelwiset 或其他非 nil 值, 返回值为整数且以像素为单位。若 pixelwise 省略或为 nil, 返回值为 line-number 面孔所定义字体的整数列数,不含显示时用于填充行号的 2 列。 若选中窗口未显示行号,无论 pixelwise 取值如何,返回值均为 0。 若需获取其他窗口的该信息,可使用 with-selected-window(see 选中窗口)。