33.19.2 修改文本属性

修改属性的基础函数适用于缓冲区或字符串中指定范围的文本。 函数 set-text-properties(见本节末尾)会设置该范围内文本的完整属性列表; 更常见的用法是仅添加、修改或删除指定名称的特定属性。

由于文本属性被视为缓冲区(或字符串)内容的一部分,且会影响缓冲区在屏幕上的显示效果, 因此对缓冲区文本属性的任何修改都会将缓冲区标记为已修改。 缓冲区文本属性的修改同样支持撤销操作(see 撤销)。 字符串中的位置从 0 开始计数,而缓冲区中的位置从 1 开始。

Function: put-text-property start end prop value &optional object

该函数为字符串或缓冲区 object 中 start 至 end 范围内的文本, 将 prop 属性设置为 value。若 object 为 nil,默认使用当前缓冲区。

Function: add-text-properties start end props &optional object

该函数为字符串或缓冲区 object 中 start 至 end 范围内的文本, 添加或覆盖指定的文本属性。若 object 为 nil,默认使用当前缓冲区。

参数 props 指定要添加的属性,其格式应为属性列表(see 属性列表): 一个由属性名和对应值交替组成的列表。

若函数实际修改了某个属性的值,返回值为 t;否则返回 nil(例如 props 为 nil, 或其值与文本中现有值一致时)。

例如,以下代码演示如何为一段文本设置 comment 和 face 属性:

(add-text-properties start end
                     '(comment t face highlight))
Function: remove-text-properties start end props &optional object

该函数从字符串或缓冲区 object 中 start 至 end 范围内的文本中, 删除指定的文本属性。若 object 为 nil,默认使用当前缓冲区。

参数 props 指定要删除的属性,其格式应为属性列表(see 属性列表): 一个由属性名和对应值交替组成的列表。但只有属性名起作用—与之伴随的值会被忽略。 例如,以下代码演示如何删除 face 属性:

(remove-text-properties start end '(face nil))

若函数实际修改了某个属性的值,返回值为 t;否则返回 nil(例如 props 为 nil, 或指定文本中无任何待删除属性时)。

若要移除某段文本的所有文本属性,可使用 set-text-properties,并将新属性列表指定为 nil。

Function: remove-list-of-text-properties start end list-of-properties &optional object

该函数与 remove-text-properties 类似,区别在于 list-of-properties 仅为属性名列表, 而非属性名与值交替组成的列表。

Function: set-text-properties start end props &optional object

该函数完全替换字符串或缓冲区 object 中 start 至 end 范围内文本的属性列表。 若 object 为 nil,默认使用当前缓冲区。

参数 props 为新的属性列表,其格式应为属性名和对应值交替组成的列表。

set-text-properties 返回后,指定范围内的所有字符均拥有完全相同的属性。

若 props 为 nil,效果是移除指定文本范围内的所有属性。示例如下:

(set-text-properties start end nil)

请勿依赖该函数的返回值。

Function: add-face-text-property start end face &optional appendp object

该函数作用于 start 至 end 范围内的文本,将外观样式 face 添加到 face 文本属性中。 face 应为 face 属性的有效值(see 具有特殊含义的文本属性),例如外观样式名或匿名外观样式(see 文本的视觉样式(Faces))。

若该区域内的文本已拥有非 nil 的 face 属性,原有外观样式会被保留。 该函数会将 face 属性设置为外观样式列表,其中 face 为第一个元素(默认), 原有外观样式为剩余元素。若可选参数 appendp 非 nil,则 face 会被追加到列表末尾。 注意在外观样式列表中,每个属性的首个值拥有最高优先级。

例如,以下代码会为 start 至 end 范围内的文本设置斜体绿色外观:

(add-face-text-property start end 'italic)
(add-face-text-property start end '(:foreground "red"))
(add-face-text-property start end '(:foreground "green"))

可选参数 object 若非 nil,则指定要操作的缓冲区或字符串(而非当前缓冲区)。 若 object 为字符串,则 start 和 end 为基于 0 的字符串索引。

创建带文本属性字符串最简便的方式是使用 propertize 函数:

Function: propertize string &rest properties

该函数返回 string 的副本,并为其添加文本属性 properties。 这些属性会应用于返回字符串中的所有字符。以下示例创建一个包含 face 属性和 mouse-face 属性的字符串:

(propertize "foo" 'face 'italic
            'mouse-face 'bold-italic)
     ⇒ #("foo" 0 3 (mouse-face bold-italic face italic))

若要为字符串不同部分设置不同属性,可先使用 propertize 构造各部分,再通过 concat 拼接:

(concat
 (propertize "foo" 'face 'italic
             'mouse-face 'bold-italic)
 " and "
 (propertize "bar" 'face 'italic
             'mouse-face 'bold-italic))
     ⇒ #("foo and bar"
                 0 3 (face italic mouse-face bold-italic)
                 3 8 nil
                 8 11 (face italic mouse-face bold-italic))

函数 buffer-substring-no-properties 可从缓冲区复制文本但不复制其属性,see 查看缓冲区内容。

若希望为缓冲区添加或移除文本属性但不将缓冲区标记为已修改,可将上述函数调用包裹在 with-silent-modifications 宏中。 See 缓冲区修改。