29.7 拆分窗口

本节介绍通过 拆分(splitting) 现有窗口来创建新窗口的函数。注意,部分窗口具有特殊性,这些函数可能无法按此处描述的方式拆分它们。这类窗口的例子包括侧边窗口(see 侧边窗口)和原子窗口(see 原子窗口)。

Function: split-window &optional window size side pixelwise

该函数在窗口 window 旁边创建一个新的活动窗口。如果 window 被省略或为 nil,则默认为选中窗口。该窗口会被拆分并缩小尺寸,腾出的空间由新窗口占据,函数返回这个新窗口。

可选的第二个参数 size 决定 window 和/或新窗口的尺寸。如果它被省略或为 nil,两个窗口会被分配相等的尺寸;如果总行数是奇数,多余的一行会分给新窗口。如果 size 是正数,window 会被分配 size 行(或列,取决于 side 的值)。如果 size 是负数,新窗口会被分配 −size 行(或列)。

如果 sizenil,该函数会遵守变量 window-min-heightwindow-min-width(see 窗口尺寸)。因此,如果拆分后会导致某个窗口小于这些变量规定的尺寸,它会抛出错误。但是,size 为非 nil 时会忽略这些变量;在这种情况下,允许的最小窗口被认为是可以容纳一行高、两列宽文本的窗口。

因此,如果指定了 size,调用者有责任检查拆分出来的窗口是否足够大,以容纳它们的所有装饰,例如模式行或滚动条。函数 window-min-size(see 窗口尺寸)可用于确定 window 在这方面的最小尺寸要求。由于新窗口通常会从 window 继承模式行或滚动条这类区域,该函数也适合用来估算新窗口的最小尺寸。调用者只有在下次重绘前相应移除继承区域时,才应该指定更小的尺寸。

可选的第三个参数 side 决定新窗口相对于 window 的位置。如果它是 nilbelow,新窗口放在 window 下方。如果是 above,新窗口放在 window 上方。在这两种情况下,size 都以行为单位指定窗口总高度。

如果 sidetright,新窗口放在 window 右侧。如果是 left,新窗口放在 window 左侧。在这两种情况下,size 都以列为单位指定窗口总宽度。

可选的第四个参数 pixelwise 如果非 nil,表示以像素为单位解释 size,而不是以行和列为单位。

如果 window 是活动窗口,新窗口会从它继承多种属性,包括边距和滚动条。如果 window 是内部窗口,新窗口会继承在 window 所在框架内被选中窗口的属性。

只要变量 ignore-window-parametersnil,该函数的行为就可能被 window 的窗口参数改变。如果 split-window 窗口参数的值为 t,该函数会忽略所有其他窗口参数。否则,如果 split-window 窗口参数的值是一个函数,该函数会以 windowsizeside 为参数被调用,替代 split-window 原本的行为。除此之外,该函数会遵守 window-atomwindow-side 窗口参数(如果有的话)。See 窗口参数

举个例子,下面是一系列 split-window 调用,可以得到 窗口与框架 中讨论的窗口布局。这个例子同时演示了拆分活动窗口和拆分内部窗口。我们从一个只包含单个窗口(活动根窗口)的框架开始,用 W4 表示它。调用 (split-window W4) 会得到这样的窗口布局:

     ______________________________________
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||_________________W4_________________||
    | ____________________________________ |
    ||                                    ||
    ||                                    ||
    ||                                    ||
    ||_________________W5_________________||
    |__________________W3__________________|

这次 split-window 调用创建了一个新的活动窗口,记为 W5。它还创建了一个新的内部窗口,记为 W3,该窗口成为根窗口,同时也是 W4W5 的父窗口。

接下来,我们调用 (split-window W3 nil 'left),将内部窗口 W3 作为参数传入。结果如下:

     ______________________________________
    | ______  ____________________________ |
    ||      || __________________________ ||
    ||      |||                          |||
    ||      |||                          |||
    ||      |||                          |||
    ||      |||____________W4____________|||
    ||      || __________________________ ||
    ||      |||                          |||
    ||      |||                          |||
    ||      |||____________W5____________|||
    ||__W2__||_____________W3_____________ |
    |__________________W1__________________|

一个新的活动窗口 W2 被创建在内部窗口 W3 的左侧。一个新的内部窗口 W1 被创建,成为新的根窗口。

对于交互式使用,Emacs 提供了两个总是拆分选中窗口的命令。它们内部都会调用 split-window

Command: split-window-right &optional size window-to-split

该函数将窗口 window-to-split 拆分为左右并排的两个窗口,将 window-to-split 放在左侧。window-to-split 默认为选中窗口。如果 size 为正数,左侧窗口占据 size 列;如果 size 为负数,右侧窗口占据 −size 列。

Command: split-window-below &optional size window-to-split

该函数将窗口 window-to-split 拆分为上下两个窗口,保持上方窗口被选中。window-to-split 默认为选中窗口。如果 size 为正数,上方窗口占据 size 行;如果 size 为负数,下方窗口占据 −size 行。

Command: split-root-window-below &optional size

该函数将整个框架一分为二。上方保留当前窗口布局,并在下方创建一个占据整个框架宽度的新窗口。size 的处理方式与 split-window-below 相同。

Command: split-root-window-right &optional size

该函数将整个框架一分为二。左侧保留当前窗口布局,并在右侧创建一个占据整个框架高度的新窗口。size 的处理方式与 split-window-right 相同。

User Option: split-window-keep-point

如果这个变量的值为非 nil(默认值),split-window-below 就按上面描述的方式工作。

如果它为 nilsplit-window-below 会调整两个窗口中的光标位置,以最小化重绘。(这在慢速终端上很有用。)它会选中光标原本所在屏幕行所属的窗口。注意这只影响 split-window-below,不影响更底层的 split-window 函数。