12.11.1 缓冲区局部变量简介

缓冲区局部变量拥有与特定缓冲区关联的缓冲区局部绑定。当该缓冲区成为当前缓冲区时,该绑定生效;否则不生效。如果你在缓冲区局部绑定生效时修改变量,新值只会存入该绑定,其他绑定保持不变。也就是说,修改只在你执行操作的这个缓冲区中可见。

变量不与任何特定缓冲区关联的普通绑定,称为 默认绑定(default binding)。大多数情况下,默认绑定就是全局绑定。

一个变量可以在部分缓冲区中拥有缓冲区局部绑定,在其他缓冲区中则没有。所有没有为该变量建立自身绑定的缓冲区(包括所有新建的缓冲区),都会共享默认绑定。如果你在一个没有为该变量建立缓冲区局部绑定的缓冲区中修改它,修改的是默认绑定,因此新值会在所有使用默认绑定的缓冲区中生效。

缓冲区局部绑定最常见的用途,是让主模式修改控制命令行为的相关变量。例如,C 模式和 Lisp 模式都会修改变量 paragraph-start,用来规定只有空行才能分隔段落。它们的实现方式是:在切换到 C 模式或 Lisp 模式的缓冲区中,将该变量设为缓冲区局部变量,然后为该模式设置新值。See Major Modes

创建缓冲区局部绑定的常规方式是使用 make-local-variable 函数,这也是主模式命令最常采用的方式。该操作仅作用于当前缓冲区;所有其他缓冲区(包括尚未创建的缓冲区)会继续共享默认值,除非显式为它们创建专属的缓冲区局部绑定。

一种功能更强的操作是调用 make-variable-buffer-local,将变量标记为 自动缓冲区局部(automatically buffer-local) 变量。你可以理解为:这会让该变量在所有缓冲区(甚至尚未创建的缓冲区)中都成为局部变量。更准确地说,其效果是:当修改变量时,如果该变量尚未成为当前缓冲区的局部变量,会自动将其设为当前缓冲区的局部变量。 所有缓冲区初始时都会像往常一样共享该变量的默认值,但对变量的赋值操作会为当前缓冲区创建缓冲区局部绑定。新值会存入这个缓冲区局部绑定中,而默认绑定保持不变。这意味着:无法通过 setq 在任何缓冲区中修改默认值;修改默认值的唯一方式是使用 setq-default

警告: 当一个变量在一个或多个缓冲区中存在缓冲区局部绑定时,let 会对当前生效的绑定进行临时重绑定。例如:如果当前缓冲区有缓冲区局部值,let 会临时重绑定这个局部值;如果没有生效的缓冲区局部绑定,let 会重绑定默认值。 若在 let 块内切换到另一个当前缓冲区(该缓冲区中生效的是另一套绑定),你将无法再看到 let 创建的临时绑定。而如果在切换后的缓冲区中退出 let 块,你不会看到解绑操作的直观效果(尽管解绑会正常执行)。以下示例可说明这一点:

(setq foo 'g)
(set-buffer "a")
(make-local-variable 'foo)
(setq foo 'a)
(let ((foo 'temp))
  ;; foo ⇒ 'temp  ; let binding in buffer ‘a
  (set-buffer "b")
  ;; foo ⇒ 'g     ; the global value since foo is not local in ‘b
  body...)
foo ⇒ 'g        ; exiting restored the local value in buffer ‘a’,
                 ; but we don’t see that in buffer ‘b
(set-buffer "a") ; verify the local value was restored
foo ⇒ 'a

注意,在 body 中对 foo 的引用会访问缓冲区 ‘b’ 的缓冲区局部绑定。

当文件指定了局部变量值时,在你打开该文件时,这些值会成为缓冲区局部值。See File Variables in The GNU Emacs Manual

终端局部变量无法被设为缓冲区局部变量(see Multiple Terminals)。


emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© 2025 Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike