在文本属性的典型使用场景中,通常有多个连续字符的某一属性值相同。 相比逐字符检查,处理属性值相同的文本块效率会高得多。
以下函数可实现该需求,它们使用 eq 比较属性值。
所有函数中,参数 object 均默认指向当前缓冲区。
为保证性能,务必为这些函数指定 limit 参数,尤其是搜索单个属性的函数— 否则,若目标属性未发生变化,函数可能会花费大量时间扫描至缓冲区末尾。
这些函数不会移动光标(point),而是返回一个位置(或 nil)。
需注意,位置始终位于两个字符之间;这些函数返回的位置,恰好是两个属性不同字符的分界处。
该函数从字符串或缓冲区 object 的 pos 位置向前扫描文本, 直至发现某文本属性发生变化,然后返回该变化的位置。 换言之,它返回 pos 之后首个属性与 pos 紧邻字符属性不同的字符位置。
若 limit 非 nil,扫描会在 limit 位置终止。
若该位置前未发现属性变化,函数返回 limit。
若 limit 为 nil 且属性一直无变化直至 object 末尾,返回值为 nil。
若返回值非 nil,则为大于或等于 pos 的位置;仅当 limit 等于 pos 时,返回值才等于 pos。
以下示例演示如何按属性恒定的文本块扫描缓冲区:
(while (not (eobp))
(let ((plist (text-properties-at (point)))
(next-change
(or (next-property-change (point) (current-buffer))
(point-max))))
Process text from point to next-change...
(goto-char next-change)))
该函数与 next-property-change 类似,但从 pos 位置向后(反向)扫描。
若返回值非 nil,则为小于或等于 pos 的位置;仅当 limit 等于 pos 时,返回值才等于 pos。
该函数扫描文本以查找 prop 属性的变化,然后返回该变化的位置。 扫描从字符串或缓冲区 object 的 pos 位置向前进行。 换言之,该函数返回 pos 之后首个 prop 属性与 pos 紧邻字符属性不同的字符位置。
若 limit 非 nil,扫描会在 limit 位置终止。
若该位置前未发现属性变化,next-single-property-change 返回 limit。
若 limit 为 nil 且属性一直无变化直至 object 末尾,返回值为 nil。
若返回值非 nil,则为大于或等于 pos 的位置;仅当 limit 等于 pos 时,返回值才等于 pos。
该函数与 next-single-property-change 类似,但从 pos 位置向后(反向)扫描。
若返回值非 nil,则为小于或等于 pos 的位置;仅当 limit 等于 pos 时,返回值才等于 pos。
该函数与 next-property-change 类似,但同时考虑覆盖层属性和文本属性;
若缓冲区末尾前未发现变化,返回缓冲区最大位置而非 nil(从这个角度看,它更接近对应的覆盖层函数 next-overlay-change,而非 next-property-change)。
该函数无 object 参数,因为它仅作用于当前缓冲区。
它返回下一个任一类型属性发生变化的位置。
该函数与 next-char-property-change 类似,但从 pos 位置向后(反向)扫描;
若未发现变化,返回缓冲区最小位置。
该函数与 next-single-property-change 类似,但同时考虑覆盖层属性和文本属性;
若 object 末尾前未发现变化,返回 object 中的最大有效位置而非 nil。
与 next-char-property-change 不同,该函数 包含 object 参数;
若 object 非缓冲区,则仅考虑文本属性。
该函数与 next-single-char-property-change 类似,但从 pos 位置向后(反向)扫描;
若未发现变化,返回 object 中的最小有效位置。
若 start 至 end 范围内至少有一个字符的 prop 属性值为 value,
该函数返回非 nil 值——更准确地说,返回首个符合条件字符的位置;否则返回 nil。
可选的第五个参数 object 指定要扫描的字符串或缓冲区,位置均相对于 object。 object 的默认值为当前缓冲区。
若 start 至 end 范围内至少有一个字符的 prop 属性值不等于 value,
该函数返回非 nil 值——更准确地说,返回首个符合条件字符的位置;否则返回 nil。
可选的第五个参数 object 指定要扫描的字符串或缓冲区,位置均相对于 object。 object 的默认值为当前缓冲区。
根据 predicate 规则,搜索下一个 prop 属性匹配 value(默认值为 nil)的文本区域。
该函数模仿 search-forward(see 字符串搜索)及其相关函数的行为:
它会移动光标,但返回一个描述匹配结果的结构体,而非通过 match-beginning 等函数返回结果。
若未找到属性值匹配的文本,函数返回 nil;若找到,光标会移至该匹配文本属性区域的末尾,
函数返回一个包含匹配信息的 prop-match 结构体。
predicate 可以是 t(等同于 equal)、nil(表示“不相等”),
或一个接收两个参数的谓词函数:value 和候选匹配缓冲区位置的 prop 文本属性值。
若匹配成功,该函数应返回非 nil;否则返回 nil。
若 not-current 非 nil,且光标已处于属性匹配区域内,则跳过该区域,查找下一个匹配区域。
prop-match 结构体有以下访问函数:
prop-match-beginning(匹配起始位置)、
prop-match-end(匹配结束位置)、
prop-match-value(匹配起始位置的 property 属性值)。
以下示例使用一个内容如下的缓冲区:
This is a bold and here’s bolditalic and this is the end.
即 “bold” 相关单词应用了 bold 外观样式,“italic” 单词应用了 italic 外观样式。
光标位于起始位置时:
(while (setq match (text-property-search-forward 'face 'bold t))
(push (buffer-substring (prop-match-beginning match)
(prop-match-end match))
words))
这段代码会提取所有应用 bold 外观样式的单词。
(while (setq match (text-property-search-forward 'face nil t))
(push (buffer-substring (prop-match-beginning match)
(prop-match-end match))
words))
这段代码会提取所有无外观样式属性的文本片段,结果为列表 ‘("This is a " "and here's " "and this is the end")’
(由于使用了 push,实际顺序为逆序,详见 see 修改列表变量)。
(while (setq match (text-property-search-forward 'face nil nil))
(push (buffer-substring (prop-match-beginning match)
(prop-match-end match))
words))
这段代码会提取所有 face 属性被设置的区域,且会按属性变化位置拆分,
因此结果为 ‘("bold" "bold" "italic")’。
以下是更贴近实际的使用场景:假设缓冲区中某些段落代表 URL,且被标记了 shr-url 属性。
(while (setq match (text-property-search-forward 'shr-url nil nil)) (push (prop-match-value match) urls))
这段代码会提取所有此类 URL 组成的列表。
该函数与 text-property-search-forward 类似,但方向为向后搜索;
若找到匹配项,光标会移至匹配区域的起始位置(而非末尾)。