33.19.2 修改文本属性

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

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

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

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

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

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

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

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

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

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

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

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

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

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

若要移除某段文本的所有文本属性,可使用 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

该函数完全替换字符串或缓冲区 objectstartend 范围内文本的属性列表。 若 objectnil,默认使用当前缓冲区。

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

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

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

(set-text-properties start end nil)

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

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

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

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

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

(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 为字符串,则 startend 为基于 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 缓冲区修改