你可以通过 invisible 属性让字符变为 不可见(invisible),使其不在屏幕上显示。该属性可以是文本属性(see 文本属性)或覆盖层属性(see 覆盖层)。光标移动也会在一定程度上忽略这些字符;如果命令循环在某条命令执行后发现点位于不可见文本范围内,会将点重新定位到该段文本的另一侧。
在最简单的情况下,任何非 nil 的 invisible 属性都会使字符不可见。这是默认行为——在不修改 buffer-invisibility-spec 默认值的前提下,invisible 属性就是这样工作的。如果你不打算自行设置 buffer-invisibility-spec,通常应将 invisible 属性的值设为 t。
更通用地,你可以使用变量 buffer-invisibility-spec 控制哪些 invisible 属性值会使文本不可见。这样可以预先将文本分为不同子集,为它们赋予不同的 invisible 值,之后通过修改 buffer-invisibility-spec 让不同子集可见或不可见。
在显示数据库条目的程序中,使用 buffer-invisibility-spec 控制可见性尤其有用。它可以方便地实现过滤命令,只查看数据库中的部分条目。设置该变量速度极快,远快于遍历缓冲区所有文本修改属性。
该变量指定哪种 invisible 属性会真正使字符不可见。设置该变量会自动变为缓冲区局部变量。
t如果字符的 invisible 属性非 nil,则该字符不可见。这是默认值。
列表中的每个元素指定一个不可见判定条件;如果字符的 invisible 属性满足任一条件,则该字符不可见。列表可以包含两种元素:
atom如果字符的 invisible 属性值为 atom,或是包含 atom 的列表,则该字符不可见;比较使用 eq。
(atom . t)判定规则同上。此外,这样的一段连续字符会显示为省略号。
专门提供了两个函数用于向 buffer-invisibility-spec 添加和移除元素。
该函数将元素 element 添加到 buffer-invisibility-spec。如果原先 buffer-invisibility-spec 为 t,会变为列表 (t),以保证 invisible 属性为 t 的文本保持不可见。
从 buffer-invisibility-spec 中移除元素 element。如果列表中不存在该元素,则不执行任何操作。
使用 buffer-invisibility-spec 的一个惯例是:主模式应使用模式自身的名称作为 buffer-invisibility-spec 的元素,同时也作为 invisible 属性的值:
;; 若希望显示省略号: (add-to-invisibility-spec '(my-symbol . t)) ;; 若不希望显示省略号: (add-to-invisibility-spec 'my-symbol) (overlay-put (make-overlay beginning end) 'invisible 'my-symbol) ;; 不需要不可见效果时: (remove-from-invisibility-spec '(my-symbol . t)) ;; 或者对应地: (remove-from-invisibility-spec 'my-symbol)
可以使用下面的函数检查不可见性:
如果 pos-or-prop 是标记或数字,该函数在该位置文本当前不可见时返回非 nil。
如果 pos-or-prop 是其他类型的 Lisp 对象,则视为 invisible 文本属性或覆盖层属性的可能取值。此时函数会根据当前 buffer-invisibility-spec 的值,判断该值是否会使文本不可见,若是则返回非 nil。
如果文本会被完全隐藏,函数返回 t;如果文本会被替换为省略号,则返回非 nil 且非 t 的值。
通常,处理文本或移动点的函数并不关心文本是否可见,对不可见字符与可见字符一视同仁。用户级的行移动命令(如 next-line、previous-line)在 line-move-ignore-invisible 为非 nil(默认值)时,会忽略不可见的换行符,即表现为这些换行符在缓冲区中并不存在—但这只是因为这些命令显式地如此实现。
如果某条命令结束时点位于不可见文本内部或边界上,主编辑循环会将点重新定位到不可见文本的某一端。Emacs 会按照命令整体的移动方向选择重定位方向;如有不确定,则优先选择插入字符不会继承 invisible 属性的位置。此外,如果文本未被替换为省略号,且命令仅在不可见文本内部移动,点会额外多移动一个字符,以便通过光标的可见移动反映命令的移动效果。
因此,如果命令将点往回移动到不可见区域(带有通常的粘性),Emacs 会将点移回该区域起点。如果命令将点向前移入不可见区域,Emacs 会将点向前移到不可见文本之后的第一个可见字符,再额外前移一个字符。
将 disable-point-adjustment 设置为非 nil 可以禁用上述将点移入不可见文本后的调整(adjustments)行为。See 命令执行后的光标位置调整。
当匹配内容包含不可见文本时,增量搜索可以临时或永久地让不可见覆盖层变为可见。要启用该功能,覆盖层应设置非 nil 的 isearch-open-invisible 属性。属性值应为一个以覆盖层为参数的函数。该函数应永久地让覆盖层可见;在搜索结束时,若匹配内容与该覆盖层重叠,就会调用此函数。
在搜索过程中,这类覆盖层会通过临时修改其 invisible 和 intangible 属性变为可见。如果你希望某个覆盖层的处理方式不同,可以为其设置 isearch-open-invisible-temporary 属性,值为一个函数。该函数接收两个参数:第一个是覆盖层,第二个为 nil 时使覆盖层可见,为 t 时恢复不可见。
被替换型(replacing) display 属性覆盖的文本会忽略 invisible 属性,因为这类 display 属性会直接跳过文本而不处理其属性。See 替换文本的显示规范.