12.11.2 创建与删除缓冲区局部绑定

Command: make-local-variable variable

该函数在当前缓冲区中为 variable(一个符号)创建缓冲区局部绑定。其他缓冲区不受影响。返回值为 variable

variable 的缓冲区局部值初始时与其原先的值相同。如果 variable 原本未定义,则它保持未定义状态。

;; In buffer ‘b1’:
(setq foo 5)                ; Affects all buffers.
     ⇒ 5
(make-local-variable 'foo)  ; Now it is local in ‘b1’.
     ⇒ foo
foo                         ; That did not change
     ⇒ 5                   ;   the value.
(setq foo 6)                ; Change the value
     ⇒ 6                   ;   in ‘b1’.
foo
     ⇒ 6

;; In buffer ‘b2’, the value hasn’t changed.
(with-current-buffer "b2"
  foo)
     ⇒ 5

在变量的 let 绑定范围内为该变量创建缓冲区局部绑定的做法无法保证可靠性,除非执行此操作的缓冲区在进入或退出 let 时均非当前缓冲区。这是因为 let 不会区分不同类型的绑定 —— 它仅记录该绑定对应的变量名称。

为常量或只读变量创建缓冲区局部绑定属于错误操作。See 永不改变的变量

若该变量是终端局部变量(see Multiple Terminals),此函数会抛出错误。这类变量无法同时拥有缓冲区局部绑定。

警告: 切勿对钩子变量使用 make-local-variable。如果你在调用 add-hookremove-hook 时传入 local 参数,钩子变量会在需要时自动成为缓冲区局部变量。

Macro: setq-local &rest pairs

pairs 是一组 “变量 - 值” 配对列表。该宏会为列表中的每个变量在当前缓冲区创建缓冲区局部绑定,并为其赋予缓冲区局部值。这等效于对每个变量依次调用 make-local-variable 后再调用 setq。这些变量应为未加引号的符号。

(setq-local var1 "value1"
            var2 "value2")
Command: make-variable-buffer-local variable

该函数将 variable(一个符号)标记为自动缓冲区局部变量,此后任何对它的赋值操作,都会使其在当前缓冲区中变为局部。它常与 make-local-variable 混淆,但与之不同的是:此操作无法撤销,并且会影响所有缓冲区中该变量的行为。

该特性有一个特殊之处:使用 let 或其他绑定结构对变量进行绑定,并不会为其创建缓冲区局部绑定。只有在变量没有在当前缓冲区中建立过 let 风格绑定的前提下,通过 setsetq 对变量赋值,才会建立缓冲区局部绑定。

如果 variable 原本没有默认值,调用此命令会为其赋予默认值 nil。如果 variable 已有默认值,则该值保持不变。后续对 variable 调用 makunbound,只会使其缓冲区局部值变为未定义,而不会影响其默认值。

返回值为 variable

为常量或只读变量设置为缓冲区局部属于错误操作。See 永不改变的变量

警告: 不要仅仅因为用户 可能 希望在不同缓冲区中对用户选项变量进行不同定制,就想当然地使用 make-variable-buffer-local。用户在需要时,可以自行将任意变量设为局部。将选择权交给用户会是更好的做法。

使用 make-variable-buffer-local 的场景是:必须确保任意两个缓冲区绝不会共享同一个绑定。例如,当某个变量被 Lisp 程序用于内部逻辑,且该程序依赖于「不同缓冲区中该变量拥有独立值」的特性时,使用 make-variable-buffer-local 会是最佳解决方案。

Macro: defvar-local variable value &optional docstring

该宏将 variable 定义为一个变量,为其设置初始值 value 和文档字符串 docstring,并将其标记为自动缓冲区局部变量。这等效于先调用 defvar,再调用 make-variable-buffer-localvariable 应为未加引号的符号。

Function: local-variable-p variable &optional buffer

variable 在缓冲区 buffer(默认值为当前缓冲区)中是缓冲区局部变量,则返回 t;否则返回 nil

Function: local-variable-if-set-p variable &optional buffer

variable 满足以下任一条件,返回 t: 在缓冲区 buffer 中拥有缓冲区局部值; 或被标记为自动缓冲区局部变量。 若不满足上述条件,则返回 nil。若 buffer 参数被省略或传入 nil,则默认使用当前缓冲区。

Function: buffer-local-value variable buffer

该函数返回缓冲区 buffervariable(一个符号)的缓冲区局部绑定值。若 variable 在缓冲区 buffer 中无缓冲区局部绑定,则返回该变量的默认值(see 缓冲区局部变量的默认值)。

Function: buffer-local-boundp variable buffer

若满足以下任一条件,该函数返回非 nil 值: 缓冲区 buffer 中存在 variable(一个符号)的缓冲区局部绑定; 或 variable 拥有全局绑定。

Function: buffer-local-variables &optional buffer

该函数返回一个列表,描述缓冲区 buffer 中的所有缓冲区局部变量。(若省略 buffer 参数,则使用当前缓冲区。)通常,列表中的每个元素格式为 (sym . val):其中 sym 是缓冲区局部变量(符号),val 是其对应的缓冲区局部值。但如果某个变量在 buffer 中的缓冲区局部绑定为「未定义(void)」状态,则其在列表中仅以 sym 单个符号的形式存在。

(make-local-variable 'foobar)
(makunbound 'foobar)
(make-local-variable 'bind-me)
(setq bind-me 69)
(setq lcl (buffer-local-variables))
    ;; First, built-in variables local in all buffers:
⇒ ((mark-active . nil)
    (buffer-undo-list . nil)
    (mode-name . "Fundamental")
    ...
    ;; Next, non-built-in buffer-local variables.
    ;; This one is buffer-local and void:
    foobar
    ;; This one is buffer-local and nonvoid:
    (bind-me . 69))

注意,向此列表中cons 单元的 CDR 部分存入新值,并 不会 改变这些变量的缓冲区局部值。

Command: kill-local-variable variable

该函数删除当前缓冲区中 variable(一个符号)的缓冲区局部绑定(如果存在)。执行后,variable 的默认绑定会在此缓冲区中生效。这通常会导致 variable 的值发生变化,因为默认值通常与刚刚删除的缓冲区局部值不同。

如果你删除了一个被赋值后自动变为缓冲区局部的变量的局部绑定,这会使默认值在当前缓冲区中生效。但是,如果你再次对该变量赋值,将会重新为它创建缓冲区局部绑定。

kill-local-variable 返回 variable

该函数是一个交互式命令,因为有时在交互使用中删除某个缓冲区局部变量是很有用的,就像交互式创建缓冲区局部变量一样有用。

Function: kill-all-local-variables &optional kill-permanent

该函数清除当前缓冲区的所有缓冲区局部变量绑定。执行后,该缓冲区将使用绝大多数变量的默认值。默认情况下,被标记为「永久(permanent)」的变量、以及拥有非 nil 类型 permanent-local-hook 属性的局部钩子函数(see Setting Hooks)不会被清除;但如果可选参数 kill-permanent 为非 nil 值,这些变量也会被清除。

该函数还会重置缓冲区的若干其他相关信息:将局部按键映射设为 nil,将语法表设为 (standard-syntax-table) 的值,将大小写转换表设为 (standard-case-table),并将缩写表设为 fundamental-mode-abbrev-table 的值。

该函数执行的第一个操作是运行普通钩子 change-major-mode-hook(见下文)。

每个主模式命令都会先调用此函数 —— 这一操作等效于切换到基本模式(Fundamental mode),并清除上一个主模式产生的大部分效果。为确保该函数能正常工作,主模式所设置的变量不应被标记为「永久」。

kill-all-local-variables 返回 nil

Variable: change-major-mode-hook

函数 kill-all-local-variables 会在执行任何其他操作之前运行这个普通钩子。这为主模式提供了一种机制:当用户切换到另一个主模式时,可通过该钩子执行特定的自定义操作。对于「缓冲区专属的次要模式」而言,该钩子也很有用 —— 若用户切换主模式,这类次要模式应被清除,可通过此钩子实现。

为达到最佳效果,应将此变量设为缓冲区局部变量:这样它在完成自身使命后便会消失,且不会干扰后续切换的主模式。See Hooks

若某个缓冲区局部变量的名称(符号)拥有非 nilpermanent-local 属性,则该变量被称为 永久(permanent) 缓冲区局部变量。此类变量不受 kill-all-local-variables 影响,因此切换主模式时,其局部绑定不会被清除。永久局部变量适合存储与「文件来源」「文件保存方式」相关的数据,而非与「内容编辑方式」相关的数据。


emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© 2025 Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike