42.9.2 覆盖层属性

覆盖层属性与文本属性类似,改变字符显示方式的属性可以来自其中任意一种来源。但二者在大多数方面存在差异。对比说明参见 See 文本属性

文本属性被视为文本的一部分;而覆盖层及其属性明确不被视为文本的一部分。因此,在不同缓冲区与字符串间复制文本会保留文本属性,但不会保留覆盖层。修改缓冲区的文本属性会将缓冲区标记为已修改,而移动覆盖层或修改其属性则不会。与文本属性修改不同,覆盖层属性的变更不会记录在缓冲区的撤销列表中。

由于多个覆盖层可以为同一字符指定同一属性的不同值,Emacs 允许你为每个覆盖层指定优先级值。优先级值用于决定重叠覆盖层中哪一个 “生效(win)”。

以下函数用于读取与设置覆盖层的属性:

Function: overlay-get overlay prop

该函数返回 overlay 中记录的属性 prop 的值(若存在)。若覆盖层未记录该属性值,但拥有 category 属性且为符号,则使用该符号的 prop 属性。否则值为 nil

Function: overlay-put overlay prop value

该函数将 overlay 中记录的属性 prop 的值设为 value,并返回 value

Function: overlay-properties overlay

返回 overlay 属性列表的副本。

另请参见函数 get-char-property,它会同时检查给定字符的覆盖层属性与文本属性。See 查看文本属性

许多覆盖层属性具有特殊含义,下表列出这些属性:

priority

该属性的值决定覆盖层的优先级。若要指定优先级,可使用 nil(或 0)、正整数或由两个值组成的 cons。其他值会导致未定义行为。

当两个或多个覆盖层覆盖同一字符且为同一属性指定不同值时,优先级起作用:priority 值更高的覆盖层会覆盖另一个。(对于 face 属性,高优先级覆盖层的值不会完全覆盖低优先级,而是其单个外观属性覆盖对应低优先级外观属性。)若两个覆盖层优先级相同,且一个嵌套在另一个内部(即覆盖更少的缓冲区或字符串位置),则内部覆盖层优先于外部。若二者互不嵌套,则不应假定哪一个会生效。

当 Lisp 程序为可能存在无优先级覆盖层的文本添加带优先级的覆盖层时,可能产生不理想结果,因为任何带正优先级的覆盖层都会覆盖所有无优先级覆盖层。由于大多数使用覆盖层的 Emacs 功能不会为覆盖层指定优先级,整数优先级应谨慎使用。你可以使用形如 (primary . secondary) 的优先级值,而非使用整数优先级并冒险覆盖其他覆盖层,其中 primary 按上述规则使用,secondary 为当 primary 与嵌套规则无法决定覆盖层优先级时的备用值。特别地,优先级值 (nil . n)n 为正整数)可让你在必要时按优先级排序覆盖层,而不会完全覆盖其他覆盖层。

目前,所有覆盖层优先级都高于文本属性。

若需要按优先级对覆盖层排序,可使用 overlays-atsorted 参数。See 搜索覆盖层

window

window 属性非 nil,则该覆盖层仅作用于指定框架。

category

若覆盖层拥有 category 属性,我们称之为该覆盖层的 类别。它应当是一个符号。该符号的属性作为覆盖层属性的默认值。

face

该属性控制文本的显示外观(see 文本的视觉样式(Faces))。属性值可以是以下类型:

  • 外观名称(符号或字符串)。
  • 匿名外观:形如 (keyword value …) 的属性列表,其中每个 keyword 为外观属性名,value 为对应属性值。
  • 外观列表。列表中的每个元素为外观名称或匿名外观。这指定一个由列表中各外观属性聚合而成的外观,列表中靠前的外观优先级更高。
  • 形如 (foreground-color . color-name)(background-color . color-name) 的 cons 单元格。用于指定前景或背景色,作用类似于 (:foreground color-name)(:background color-name)。该格式仅为兼容旧版而保留,应避免使用。
mouse-face

当鼠标位于覆盖层范围内时,使用该属性替代 face。但 Emacs 会忽略该属性中所有改变文本尺寸的外观属性(如 :height:weight:slant);这些属性始终与未高亮文本一致。

display

该属性启用多种改变文本显示方式的功能。例如,它可以让文本显示得更高、更低、更宽、更窄,或替换为图像。See display 属性。注意,若 display 属性为替换型(replacing)(see 替换文本的显示规范),同一覆盖层的 invisible 属性会被忽略。

help-echo

若覆盖层拥有 help-echo 属性,当鼠标移动到覆盖层内的文本上时,Emacs 会在回显区或工具提示中显示帮助字符串。详情参见 Text help-echo

field

拥有相同 field 属性的连续字符构成一个字段。包括 forward-wordbeginning-of-line 在内的部分移动命令会在字段边界处停止。See 定义与使用域

modification-hooks

该属性的值为一个函数列表,当覆盖层内任意字符被修改,或在覆盖层内部严格插入文本时,这些函数会被调用。

钩子函数在每次修改前后都会被调用。若函数保存收到的信息并在调用间对比,即可精确确定缓冲区文本发生的改动。

修改前调用时,每个函数接收四个参数:覆盖层、nil、待修改文本范围的起始与结束位置。

修改后调用时,每个函数接收五个参数:覆盖层、t、刚修改文本范围的起始与结束位置,以及该范围替换的修改前文本长度。(插入操作的修改前长度为 0;删除操作的该长度为被删除字符数,且修改后的起止位置相同。)

调用这些函数时,inhibit-modification-hooks 被绑定为非 nil。若函数需要修改缓冲区,你可能需要将 inhibit-modification-hooks 绑定为 nil,以使这些修改触发变更钩子。但这样做可能递归调用你的变更钩子,因此需要做好相应处理。See 变更钩子

文本属性同样支持 modification-hooks 属性,但细节略有不同(see 具有特殊含义的文本属性)。

insert-in-front-hooks

该属性的值为一个函数列表,在覆盖层起始位置正前方插入文本前后会被调用。调用规则与 modification-hooks 函数相同。

insert-behind-hooks

该属性的值为一个函数列表,在覆盖层结束位置正后方插入文本前后会被调用。调用规则与 modification-hooks 函数相同。

invisible

invisible 属性可使覆盖层内的文本不可见,即不在屏幕上显示。但是,若覆盖层所覆盖的文本拥有替换型(replacing) display 属性,则 invisible 属性会被忽略,因为替换型显示属性会跳过文本而不检查其属性。See 不可见文本,查看详情。

intangible

覆盖层上的 intangible 属性作用与文本属性 intangible 完全相同。该属性已过时。See 具有特殊含义的文本属性,查看详情。

isearch-open-invisible

该属性告知增量搜索(see Incremental Search in The GNU Emacs Manual),若最终匹配内容与不可见覆盖层重叠,如何永久使其可见。See 不可见文本

isearch-open-invisible-temporary

该属性告知增量搜索在搜索过程中如何临时显示不可见覆盖层。See 不可见文本

before-string

该属性的值为一个字符串,会在覆盖层起始位置添加到显示中。该字符串不会出现在缓冲区中,仅显示在屏幕上。注意,若覆盖层起始位置的文本被设为不可见,则该字符串不会显示。

after-string

该属性的值为一个字符串,会在覆盖层结束位置添加到显示中。该字符串不会出现在缓冲区中,仅显示在屏幕上。注意,若覆盖层结束位置的文本被设为不可见,则该字符串不会显示。

line-prefix

该属性指定一个显示规格,在显示时添加到每一个非续行的行首。See 截断显示

wrap-prefix

该属性指定一个显示规格,在显示时添加到每一个续行的行首。See 截断显示

evaporate

若该属性非 nil,覆盖层变为空(即长度为 0)时会自动删除。若为一个空覆盖层(see empty overlay)设置非 nilevaporate 属性,会立即删除该覆盖层。注意,除非覆盖层拥有该属性,否则当其起止位置间的文本从缓冲区删除时,覆盖层不会被删除。

display-line-numbers-disable

该属性会阻止对拥有此属性的覆盖层内文本显示行号(see display-line-numbers in The GNU Emacs Manual)。使用带该属性的覆盖层的一个典型场景是在缓冲区末尾的空覆盖层,否则无法阻止该处显示行号。

keymap

若该属性非 nil,则为文本的一部分指定一个键盘映射。该键盘映射优先级高于大多数其他键盘映射(see 活跃按键映射表),并在光标位于覆盖层内时生效,其中 front-advance 与 rear-advance 属性决定边界是否被视为 内部

local-map

local-map 属性与 keymap 类似,但会替换缓冲区的局部映射而非补充现有键盘映射,这也意味着其优先级低于次要模式键盘映射。

keymaplocal-map 属性不会影响由 before-stringafter-stringdisplay 属性显示的字符串。这仅与落在该字符串上的鼠标点击及其他鼠标事件相关,因为光标永远不会位于该字符串上。若要为该字符串绑定特殊鼠标事件,可为其设置 keymaplocal-map 文本属性。See 具有特殊含义的文本属性