29.13.1 为显示缓冲区选择窗口

命令 display-buffer 可以灵活地选择一个窗口用于显示,并在该窗口中显示指定缓冲区。它可以通过快捷键 C-x 4 C-o 交互式调用,也被许多函数和命令用作子例程,包括 switch-to-bufferpop-to-buffer(see 在窗口中切换到缓冲区)。

该命令会执行多个复杂步骤来找到用于显示的窗口。这些步骤通过 显示动作(display actions) 来描述,其形式为 (functions . alist)。其中,functions 可以是单个函数或函数列表,被称为 “动作函数(action functions)”(see 缓冲区显示动作函数);而 alist 是一个关联列表,被称为 “动作 alist”(see 缓冲区显示动作关联列表)。显示动作示例参见 see 冲区显示的核心原则

动作函数接受两个参数:要显示的缓冲区和一个动作 alist。它会尝试按照自身规则选择或创建窗口,并在其中显示缓冲区。如果成功,返回该窗口;否则返回 nil

display-buffer 的工作方式是:合并来自多个来源的显示动作,依次调用动作函数,直到其中一个成功显示缓冲区并返回非 nil 值。

Command: display-buffer buffer-or-name &optional action frame

该命令让 buffer-or-name 出现在某个窗口中,但不选中该窗口,也不将该缓冲区设为当前缓冲区。参数 buffer-or-name 必须是缓冲区或已有缓冲区的名称。返回值为选中用于显示该缓冲区的窗口,若未找到合适窗口则为 nil

可选参数 action 若非 nil,通常应为一个显示动作(见上文)。display-buffer 会通过整合以下来源的显示动作(按优先级从高到低),构建动作函数列表和动作 alist:

  • 变量 display-buffer-overriding-action
  • 用户选项 display-buffer-alist
  • 参数 action
  • 用户选项 display-buffer-base-action
  • 常量 display-buffer-fallback-action

在实际使用中,这意味着 display-buffer 会构建一个由所有这些显示动作指定的动作函数列表。列表的第一个元素是 display-buffer-overriding-action 指定的第一个动作函数(如果有)。最后一个元素是 display-buffer-pop-up-frame——即 display-buffer-fallback-action 指定的最后一个动作函数。列表中不会去除重复项,因此同一个动作函数可能在一次 display-buffer 调用中被多次执行。

display-buffer 会依次调用该列表指定的动作函数,将缓冲区作为第一个参数、合并后的动作 alist 作为第二个参数传入,直到某个函数返回非 nil。不同来源指定的显示动作如何被 display-buffer 处理的示例,参见 see 动作函数的优先级

注意,第二个参数始终是上述所有来源指定的**全部**动作 alist 条目的列表。因此,该列表的第一个元素是 display-buffer-overriding-action 指定的第一个动作 alist 条目(如果有)。最后一个元素是 display-buffer-base-action 的最后一个 alist 条目(如果有)——display-buffer-fallback-action 的动作 alist 为空。

还要注意,合并后的动作 alist 可能包含重复条目,以及同一键对应不同值的条目。按照规则,动作函数总是使用找到的第一个键关联。因此,动作函数使用的关联不一定是指定该函数的显示动作所提供的关联。

参数 action 也可以是非 nil、非列表的值。这具有特殊含义:即使选中窗口已经在显示该缓冲区,也应在其他窗口中显示。如果带前缀参数交互式调用,actiont。Lisp 程序应始终提供列表类型的值。

可选参数 frame 若非 nil,指定在判断缓冲区是否已显示时检查哪些框架。这等价于向 action 的动作 alist 中添加一个条目 (reusable-frames . frame)(see 缓冲区显示动作关联列表)。提供 frame 参数是为了兼容,Lisp 程序不应使用它。

Variable: display-buffer-overriding-action

该变量的值应为一个显示动作,会被 display-buffer 以最高优先级处理。默认值为空显示动作,即 (nil . nil)

User Option: display-buffer-alist

该选项的值是一个将条件映射到显示动作的 alist。每个条件会连同缓冲区名称与传给 display-bufferaction 参数一起,传递给 buffer-match-p(see 缓冲区列表)。若返回非 nil,则 display-buffer 使用对应的显示动作显示缓冲区。注意:如果使用 derived-modemajor-mode 作为条件,若在缓冲区主模式设置前调用 display-bufferbuffer-match-p 可能无法匹配成功。

如果 display-buffer 的调用者在其 action 参数中以符号形式传入一个类别,你就可以在 display-buffer-alist 中使用相同类别来匹配不同名称的缓冲区,例如:

(add-to-list 'display-buffer-alist
             '((category . comint)
               (display-buffer-same-window)
               (inhibit-same-window . nil)))

(display-buffer (get-buffer-create "*my-shell*")
                '(nil (category . comint)))

See buffer-match-p.

调用者以符号 comint 定义一个类别,与所显示缓冲区的名称无关。然后 display-buffer-alist 会对所有使用相同类别显示的缓冲区匹配该类别。这避免了构造复杂的正则表达式来匹配缓冲区名称。

User Option: display-buffer-base-action

该选项的值应为一个显示动作。可用于为 display-buffer 调用定义标准显示动作。

Constant: display-buffer-fallback-action

该显示动作指定了在未提供其他显示动作时,display-buffer 的后备行为。