范围限制(Narrowing)指将 Emacs 编辑命令可访问的文本限定在缓冲区中的一段有限字符范围内。仍然可访问的文本称为缓冲区的可访问区域(accessible portion)。
范围限制(Narrowing) 通过两个缓冲区位置指定,这两个位置分别成为可访问区域的开头和结尾。对于大多数编辑命令和原语,这两个位置会取代缓冲区原本的开头与结尾位置。当范围限制生效时,可访问区域之外的文本不会显示,且光标无法移动到可访问区域之外。注意范围限制不会修改实际的缓冲区位置(see 光标位置);它仅决定哪些位置被视为缓冲区的可访问区域。大多数函数拒绝对可访问区域之外的文本进行操作。
保存缓冲区的命令不受范围限制影响;无论是否启用范围限制,这些命令都会保存整个缓冲区。
如果你需要在单个缓冲区中显示几种截然不同类型的文本,可以考虑使用 在两个缓冲区之间交换文本 中描述的替代功能。
此函数将当前缓冲区的可访问区域设置为从 start 开始到 end 结束。两个参数都应为字符位置。
在交互式调用中,start 与 end 被设为当前区域的边界(光标与标记,较小值在前)。
但是,当范围限制由带标签参数的 with-restriction 设置时(见下文),narrow-to-region 只能在该限制范围内使用。如果 start 或 end 超出这些范围,则会改用 with-restriction 设置的对应边界。若要访问缓冲区的其他区域,需使用带有相同标签的 without-restriction。
此函数将当前缓冲区的可访问区域设为仅包含当前页。可选的第一个参数 move-count 非 nil 时,表示按 move-count 页数向前或向后移动,然后限制到单页。变量 page-delimiter 指定页的起止位置(see 编辑中使用的标准正则表达式)。
在交互式调用中,move-count 被设为数字前缀参数。
此函数取消当前缓冲区的所有范围限制,使全部内容均可访问。这一操作称为解除限制(widening)。 它等价于如下表达式:
(narrow-to-region 1 (1+ (buffer-size)))
但是,当范围限制由带标签参数的 with-restriction 设置时(见下文),会恢复 with-restriction 设置的边界,而非直接取消限制。若要访问缓冲区的其他区域,需使用带有相同标签的 without-restriction。
若缓冲区处于限制状态,此函数返回非 nil,否则返回 nil。
此特殊形式保存当前可访问区域的边界,执行 body 中的表达式,最后恢复保存的边界,从而恢复之前生效的范围限制状态(或无限制状态)。即使通过 throw 或错误发生异常退出,范围限制状态也会被恢复(see 非局部退出)。因此,该结构是临时限制缓冲区的简洁方式。
该结构同时会保存并恢复由带标签参数的 with-restriction 设置的范围限制(见下文)。
save-restriction 的返回值为 body 中最后一个表达式的值,若未提供任何 body 表达式则返回 nil。
注意:使用 save-restriction 结构时很容易出错。在尝试使用前请阅读此处的完整说明。
若 body 改变了当前缓冲区,save-restriction 仍会恢复原始缓冲区的限制(即它保存限制状态的那个缓冲区),但不会恢复当前缓冲区的身份。
save-restriction 不会恢复光标位置;可使用 save-excursion 实现该功能。若同时使用 save-restriction 和 save-excursion,save-excursion 应放在外层。否则,旧的光标位置会在临时限制仍生效时被恢复。如果旧光标位置超出临时限制的边界,将无法准确恢复。
以下是 save-restriction 正确使用的简单示例:
---------- Buffer: foo ---------- This is the contents of foo This is the contents of foo This is the contents of foo∗ ---------- Buffer: foo ----------
(save-excursion
(save-restriction
(goto-char 1)
(forward-line 2)
(narrow-to-region 1 (point))
(goto-char (point-min))
(replace-string "foo" "bar")))
---------- Buffer: foo ----------
This is the contents of bar
This is the contents of bar
This is the contents of foo∗
---------- Buffer: foo ----------
此特殊形式保存缓冲区当前可访问区域的边界,将可访问区域设为从 start 开始到 end 结束,执行 body 中的表达式,然后恢复保存的边界。这种情况下它等价于:
(save-restriction (narrow-to-region start end) body)
当存在可选参数 label 时(该参数会被求值得到标签,且必须返回非 nil 值),该范围限制为带标签限制(labeled)。带标签限制与无标签限制在多个方面存在区别:
narrow-to-region 与 widen 只能在 start 与 end 范围内使用。
with-restriction 引入的限制并访问缓冲区其他区域,需使用带有相同 label 参数的 without-restriction。(另一种访问缓冲区其他区域的方式是使用间接缓冲区,see 间接缓冲区。)
若你使用带可选 label 参数的 with-restriction,建议在使用它的函数文档字符串中记录该 label,以便你代码调用的其他 Lisp 程序在需要时可以解除该带标签限制。
此特殊形式保存缓冲区当前可访问区域的边界,解除缓冲区限制,执行 body 中的表达式,然后恢复保存的边界。这种情况下它等价于:
(save-restriction (widen) body)
当存在可选参数 label 时,会解除由带有相同 label 参数的 with-restriction 设置的范围限制。