33.19.4 具有特殊含义的文本属性

下表列出了拥有内置特殊含义的文本属性名。后续小节会介绍另外几个用于控制自动换行与属性继承的特殊属性名。除此之外的其他属性名均无标准含义,可按需自由使用。

注意:每个 Emacs 命令执行完毕后,属性 compositiondisplayinvisibleintangible 也可能使光标移动到合适位置。See 命令执行后的光标位置调整

category

如果某个字符拥有 category 属性,我们称其为该字符的属性类别(property category)。它应当是一个符号。该符号的属性会作为该字符对应属性的默认值。

face

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

  • 一个外观名称(符号或字符串)。
  • 一个匿名外观:形如 (keyword value …) 的属性列表,其中每个 keyword 是外观属性名,value 是对应属性的值。
  • 一个外观列表。列表中的每个元素可以是外观名或匿名外观。这表示一个由列表中所有外观属性聚合而成的外观,列表中靠前的外观优先级更高。
  • 形如 (foreground-color . color-name)(background-color . color-name) 的序对。用于指定前景色或背景色,作用与 (:foreground color-name)(:background color-name) 类似。该格式仅为兼容旧版而保留,应当避免使用。
  • 形如 (:filtered filter face-spec) 的序对,表示仅当 filter 在显示时匹配成功,才应用 face-spec 指定的外观。face-spec 可使用上述任意格式。filter 应形如 (:window param value),用于匹配窗口参数 paramvalueeq 的窗口。若变量 face-filters-always-matchnil,则所有外观过滤器均视为匹配成功。

字体加亮模式(see Font Lock Mode)在多数缓冲区中会根据上下文动态更新字符的 face 属性。

函数 add-face-text-property 提供了便捷的方式来设置该文本属性。See 修改文本属性

font-lock-face

该属性为字体加亮模式指定应用于对应文本的 face 属性值。它是字体加亮模式使用的着色方式之一,常用于实现自定义高亮的特殊模式。See 预计算高亮。禁用字体加亮模式时,font-lock-face 无效。

mouse-face

当鼠标指针悬停在拥有该属性的文本上时,会使用此属性而非 face。悬停时,拥有相同 mouse-face 属性值的整段文本都会高亮,而非仅鼠标下的单个字符。

Emacs 会忽略 mouse-face 属性中所有会改变文本尺寸的外观属性,例如 :height:weight:slant。这些属性始终与未高亮文本保持一致。

cursor-face

该属性与 mouse-face 类似,但作用于光标(而非鼠标)位于拥有此属性的文本内部时。仅当启用 cursor-face-highlight-mode 模式时才会高亮。若变量 cursor-face-highlight-nonselected-windownil,即使窗口未被选中,该外观对应的文本也会高亮,与 highlight-nonselected-windows 对选区的作用类似(see The Mark and the Region in The GNU Emacs Manual

fontified

该属性标记文本是否已准备好显示。若为 nil,Emacs 的重绘机制会在显示前调用 fontification-functions 中的函数(see 自动分配文本视觉样式)预处理缓冲区的该部分内容。它由即时字体加亮代码内部使用。

display

该属性用于启用多种改变文本显示方式的功能。例如,可使文本显示得更高、更低、更宽、更窄,或替换为图片。See display 属性

help-echo

若文本的 help-echo 属性为字符串,当鼠标移至该文本时,Emacs 会在回显区或提示窗口(see 工具提示)中显示该字符串,显示前会经过 substitute-command-keys 处理。

help-echo 属性值为函数,则该函数会被调用,传入三个参数 windowobjectpos,并返回帮助字符串或 nil(无帮助信息)。第一个参数 window 是发现帮助信息的窗口;第二个参数 object 是拥有 help-echo 属性的缓冲区、覆盖层或字符串;pos 参数含义如下:

  • object 为缓冲区,则 pos 为缓冲区中的位置。
  • object 为覆盖层,则该覆盖层拥有 help-echo 属性,pos 为覆盖层所在缓冲区的位置。
  • object 为字符串(覆盖层字符串或通过 display 属性显示的字符串),则 pos 为该字符串内的位置。

help-echo 属性值既非函数也非字符串,则会对其求值以获取帮助字符串。

可通过设置变量 show-help-function 改变帮助文本的显示方式(see Help display)。

该特性常用于模式行及其他可交互文本。

help-echo-inhibit-substitution

help-echo 字符串的首字符拥有非 nilhelp-echo-inhibit-substitution 属性,则 show-help-function 会原样显示该字符串,不经过 substitute-command-keys 处理。

left-fringe-help
right-fringe-help

若屏幕行中任意可见文本拥有值为字符串的 left-fringe-helpright-fringe-help 文本属性,则当鼠标悬停在对应行的边缘时,会通过 show-help-function 显示该字符串(see Help display)。常与边缘光标和位图配合使用(see 侧边栏)。

keymap

keymap 属性为命令指定附加按键映射。该映射生效时,会在次要模式按键映射与缓冲区局部映射之前用于按键查找。See 活跃按键映射表。若属性值为符号,则使用该符号的函数定义作为按键映射。

若光标前一字符的该属性非 nil 且为后粘性,则应用其值;若光标后一字符的该属性非 nil 且为前粘性,则应用其值。(鼠标点击时使用点击位置而非光标位置。)

local-map

该属性与 keymap 类似,但它指定的按键映射会替代缓冲区局部映射。几乎在所有场景下,都更推荐使用 keymap 属性。

syntax-table

syntax-table 属性会覆盖语法表对该特定字符的语法定义。See 语法属性

read-only

若字符拥有 read-only 属性,则不允许修改该字符。任何尝试修改的命令都会抛出 text-read-only 错误。若属性值为字符串,则该字符串会作为错误信息。

若在只读字符旁插入普通文本会因粘性继承 read-only 属性,则插入操作会报错。因此可通过控制粘性来决定是否允许在只读文本旁插入内容。See 文本属性的粘性

修改属性属于修改缓冲区操作,因此无法直接移除 read-only 属性,除非使用特殊方法:将 inhibit-read-only 绑定为非 nil 值后再移除该属性。See 只读缓冲区

inhibit-read-only

拥有 inhibit-read-only 属性的字符即使在只读缓冲区中也可编辑。See 只读缓冲区

invisible

nilinvisible 属性可使字符在屏幕上不可见。详见 See 不可见文本

inhibit-isearch

nilinhibit-isearch 属性会使增量搜索跳过该段文本。

intangible

若一组连续字符拥有相等且非 nilintangible 属性,则无法将光标置于它们之间。尝试向前移入该组时,光标会直接跳到组末尾;尝试向后移入时,光标会跳到组开头。

若连续字符的非 nil intangible 属性值互不相同,则它们分属不同组,每组按上述规则单独处理。

当变量 inhibit-point-motion-hooksnil 时(默认如此),intangible 属性会被忽略。

注意:该属性工作在底层,会以难以预料的方式影响大量代码,使用时需格外谨慎。常见误用是为不可见文本添加 intangible 属性,这其实并无必要,因为命令循环在每条命令结束时本就会将光标移到不可见文本之外。See 命令执行后的光标位置调整。出于以上原因,该属性已废弃,建议改用 cursor-intangible 属性。

cursor-intangible

启用次要模式 cursor-intangible-mode 后,在重绘前,光标会自动离开所有拥有非 nil cursor-intangible 属性的位置。注意计算允许光标位置时会考虑属性的 “粘性(stickiness)”(see 文本属性的粘性)。例如,要插入一段无法进入光标、包含五个字符 ‘x’ 的文本,可使用类似代码:

(insert
 (propertize "xxxx" 'cursor-intangible t)
 (propertize "x" 'cursor-intangible t 'rear-nonsticky t))

当变量 cursor-sensor-inhibitnil 时,cursor-intangible 属性与下文介绍的 cursor-sensor-functions 属性均会被忽略。

field

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

cursor

通常,光标会显示在“隐藏”当前缓冲区位置的覆盖层与文本属性字符串的开头或结尾。可为这些字符串中的某个字符设置非 nilcursor 文本属性,从而指定光标显示在该字符上。此外,若 cursor 属性值为整数,则表示从覆盖层或 display 属性起始位置开始,对应数量的缓冲区位置都会将光标显示在该字符上。具体来说,若某字符的 cursor 属性值为数字 n,则缓冲区位置在 [ovpos..ovpos+n) 范围内时,光标都会显示在该字符上,其中 ovposoverlay-start 返回的覆盖层起始位置(see 管理覆盖层),或缓冲区中 display 文本属性的起始位置。

简言之,当覆盖层或显示字符串使光标不可见时,拥有非 nil cursor 属性的字符串字符即为光标显示位置。属性值决定哪些缓冲区位置会在此处显示光标。若值为整数 n,则光标位于覆盖层或 display 属性起始位置后 n 个位置内时均在此显示;若为其他非 nil 值,则仅当光标位于 display 属性起始位置或 overlay-start 且该位置不可见时才在此显示。注意,整数类型的 cursor 属性可能导致光标在光标可见时仍显示在该字符上。

该属性有一个细节:不能将其设置在显示字符串或覆盖层字符串中的换行符上。因为换行符在屏幕上没有图形表现,Emacs 无法找到带有该 cursor 属性的显示字符。

当缓冲区存在大量隐藏文本的覆盖层字符串(如 see before-string)或字符串类型的 display 属性时,建议在这些字符串上使用 cursor 属性,告知 Emacs 显示引擎在遍历这些字符串时应将光标置于何处。这能直接向显示引擎指明 Lisp 程序希望或用户期望光标出现在的位置,当光标位于被显示或覆盖层字符串“遮盖”的缓冲区位置时。

pointer

指定鼠标指针悬停在该文本或图片上时的形状。可选指针形状见 See 指针形状

line-spacing

换行符可拥有 line-spacing 文本或覆盖层属性,用于控制以该换行符结尾的显示行高度。属性值会覆盖默认框架行间距与缓冲区局部变量 line-spacing。See 行高

line-height

换行符可拥有 line-height 文本或覆盖层属性,用于控制以该换行符结尾的显示行总高度。See 行高

wrap-prefix

若一段文本拥有 wrap-prefix 属性,则其定义的前缀会在显示时添加到因自动换行产生的每一行续行开头(若开启行截断则不会使用)。属性值可以是字符串、图片(see 其他显示规范),或由 :width:align-to 等显示属性指定的空白(see 指定空格)。注意,该属性需设置在整段文本上,从文本首行首字符到末行末字符,否则换行方式变化可能导致前缀无法显示,因为显示引擎仅在续行时检查该属性。

也可通过缓冲区局部变量 wrap-prefix 为整个缓冲区设置换行前缀(但文本属性 wrap-prefix 优先级高于变量值)。See 截断显示

line-prefix

若一段文本拥有 line-prefix 属性,则其定义的前缀会在显示时添加到每一行非续行的开头。属性值可以是字符串、图片(see 其他显示规范),或由 :width:align-to 等显示属性指定的空白(see 指定空格)。注意,该属性需设置在整段文本上,从文本首行首字符到末行末字符,否则换行方式变化可能导致前缀无法显示,因为显示引擎仅在新行开始时检查该属性。

也可通过缓冲区局部变量 line-prefix 为整个缓冲区设置行前缀(但文本属性 line-prefix 优先级高于变量值)。See 截断显示

modification-hooks

若字符拥有 modification-hooks 属性,其值应为函数列表;修改该字符时,会在实际修改前调用所有这些函数。每个函数接收两个参数:被修改缓冲区部分的起始与结束位置。注意,若单个原语操作修改的多个字符上存在同一个修改钩子函数,则无法预测该函数会被调用多少次。 此外,插入操作不会修改已有字符,因此该钩子仅在删除字符、替换字符或修改其文本属性时运行。

与其他类似钩子不同,Emacs 调用这些函数时不会将 inhibit-modification-hooks 绑定为非 nil。若这些函数会修改缓冲区,应考虑将该变量绑定为非 nil,避免缓冲区修改触发修改钩子,否则必须处理递归调用。See 变更钩子

覆盖层同样支持 modification-hooks 属性,但细节有所不同(see 覆盖层属性)。

insert-in-front-hooks
insert-behind-hooks

在缓冲区中插入文本时,会调用后一字符的 insert-in-front-hooks 属性与前一字符的 insert-behind-hooks 属性中的函数。这些函数接收两个参数:插入文本的起始与结束位置,且在实际插入完成调用。

调用这些函数时,inhibit-modification-hooks 被绑定为非 nil。若函数会修改缓冲区,可能需要将其绑定为 nil 以使修改钩子生效,但这可能导致自身钩子被递归调用,需提前处理。

另见 变更钩子,了解修改缓冲区文本时触发的其他钩子。

point-entered
point-left

特殊属性 point-enteredpoint-left 用于记录响应光标移动的钩子函数。每次光标移动时,Emacs 会比较两组属性值:

  • 原位置后一字符的 point-left 属性;
  • 新位置后一字符的 point-entered 属性。

若两者不同,则各自非 nil 的函数会被调用,传入两个参数:光标旧位置与新位置。

对原位置与新位置前一字符也会进行相同比较。结果可能执行两个 point-left 函数(可相同)和/或两个 point-entered 函数(可相同)。无论如何,所有 point-left 函数先执行,随后执行所有 point-entered 函数。

可使用 char-after 检查缓冲区各位置字符而不移动光标,只有光标实际位置变化才会触发这些钩子函数。

变量 inhibit-point-motion-hooks 默认禁止运行 point-leftpoint-entered 钩子,详见 Inhibit point motion hooks

这些属性已废弃,请改用 cursor-sensor-functions

cursor-sensor-functions

该特殊属性记录响应光标移动的函数列表。重绘前,列表中的每个函数会被调用,传入三个参数:受影响的窗口、光标上一位置,以及符号 enteredleft,表示光标是进入还是离开拥有该属性的文本。仅当启用次要模式 cursor-sensor-mode 时才会调用这些函数。

当变量 cursor-sensor-inhibitnil 时,cursor-sensor-functions 属性会被忽略。

composition

该文本属性用于将字符序列显示为由组件合成的单个字形。但其属性值完全属于 Emacs 内部数据,不应通过 put-text-property 等函数直接操作。

minibuffer-message

该文本属性用于指定在活动小缓冲中显示临时消息的位置。具体来说,小缓冲文本中第一个拥有该属性的字符前会显示临时消息。默认在小缓冲文本末尾显示。该属性由 set-message-function 默认值对应的函数使用(see 在回显区显示信息)。

display-line-numbers-disable

该文本属性会禁止为拥有此属性的文本显示行号(see display-line-numbers in The GNU Emacs Manual)。

Variable: inhibit-point-motion-hooks

当该已废弃变量非 nil 时,point-leftpoint-entered 钩子不会运行,且 intangible 属性无效。请勿全局设置该变量,应使用 let 绑定。由于相关属性已废弃,该变量默认值为 t,以彻底禁用它们。

Variable: show-help-function

若该变量非 nil,则指定一个用于显示帮助字符串的函数。这些字符串可能来自 help-echo 属性、菜单帮助字符串(see 简单菜单项、see 扩展菜单项)或工具栏帮助字符串(see 工具栏)。指定函数会接收一个参数,即待显示的帮助字符串;除非帮助字符串首字符拥有非 nilhelp-echo-inhibit-substitution 属性,否则会先经过 substitute-command-keys 处理再传入函数,详见 文档中的按键绑定替换。可参考提示框模式(see Tooltips in The GNU Emacs Manual)代码,了解使用 show-help-function 的示例。

Variable: face-filters-always-match

若该变量非 nil,则所有仅在满足特定条件时应用属性的外观过滤器均视为始终匹配。