某些类型的显示规范会指定显示其他内容,而非拥有该属性的文本。这类规范被称为 replacing(replacing) 显示规范。Emacs 不允许用户以交互方式将光标移动到以此方式被替换的缓冲区文本中间。
如果一个显示规范列表中包含多个替换型显示规范,第一个规范会覆盖其余规范。替换型显示规范会让大多数其他显示规范失效,因为这些规范不适用于替换内容。此外,被替换文本的所有 invisible 和 composition 属性都会被忽略,因为被替换的文本会被跳过,其属性不会被处理。
对于替换型显示规范,拥有该属性的文本(the text that has the property) 指所有连续的、其 display 属性为同一个 Lisp 对象的字符;这些字符会作为一个整体被替换。如果两个字符的 display 属性对应不同的 Lisp 对象(即对象不满足 eq 关系),则会被分别处理。
以下示例可说明这一点。字符串可作为替换型显示规范,用指定字符串替换拥有该属性的文本(see 其他显示规范)。参考以下函数:
(defun foo ()
(dotimes (i 5)
(let ((string (concat "A"))
(start (+ i i (point-min))))
(put-text-property start (1+ start) 'display string)
(put-text-property start (+ 2 start) 'display string))))
该函数为缓冲区中的前十个字符分别赋予值为字符串 "A" 的 display 属性,但这些字符不会获得同一个字符串对象。前两个字符获得同一个字符串对象,因此会被替换为一个 ‘A’;即便显示属性是通过两次独立的 put-text-property 调用赋值的,也不影响这一结果。同理,接下来的两个字符获得第二个字符串对象(concat 会创建新的字符串对象),因此会被替换为一个 ‘A’;依此类推。最终,十个字符会显示为五个 A。
注意:在替换型 display 字符串上使用 :box 文本的视觉样式属性(see 文本视觉样式属性),且该字符串与拥有相同 :box 样式的普通文本相邻时,在光标移动过带有该文本的视觉样式属性的文本时可能产生显示瑕疵。避免该问题的方法是将 :box 属性直接应用于被替换的文本,而非(或额外)应用于 display 字符串本身。示例如下:
;; 光标移动过文本时会产生显示瑕疵 (progn (put-text-property 1 2 'display (propertize " [" 'face '(:box t))) (put-text-property 2 3 'face '(:box t)) (put-text-property 3 4 'display (propertize "] " 'face '(:box t))))
;; 因 `:box' 产生的显示瑕疵消失 (progn (add-text-properties 1 2 '(face (:box t) display " [")) (put-text-property 2 3 'face '(:box t)) (add-text-properties 3 4 '(face (:box t) display "] ")))