《elisp 每日一练》——窗口操作

《elisp 每日一练》——窗口操作

Masimaro
2026-08-12 / 0 评论 / 1 阅读 / 正在检测是否收录...

经过之前两篇,我们差不多把buffer相关的内容都了解了,主要是buffer的创建、删除、获取以及buffer属性的变动。本篇我们将开始讨论关于窗口的话题

背景知识

首先需要了解的是窗口和buffer不是一个概念,窗口是用来显示buffer内容的,而buffer只是保存文本信息。并且多个窗口可以显示同一个buffer的内容,但是不同的buffer不能由同一个Window显示。

创建一个窗口可以通过函数 split-window ,默认它会在光标所在窗口的右侧新建一个窗口,而新老窗口显示的是同一个buffer。它的函数原形如下:

(split-window &optional WINDOW SIZE SIDE PIXELWISE)
  • WINDOW 具体要分隔的是哪个窗口,默认不填的话就是当前窗口
  • SIZE 新窗口的大小(行数或列数), 如果为正数则表示新窗口的宽或者高,负数则表示留给原窗口的宽或者高
  • SIDE 分割方向

    • belowt 在下方创建新窗口
    • above 在上方创建新窗口
    • right 在右侧创建新窗口
    • left 在左侧创建新窗口
  • PIXELWISE 表示 SIZE 参数的单位, 若为非 nilSIZE 的单位将从字符行列数变为像素单位

它返回新创建的窗口对象。

因为它默认只能显示当前buffer,一般来讲我们会在创建的时候指定它要显示的buffer,修改窗口显示的buffer使用函数 set-window-buffer 它需要接收至少两个参数,分别是窗口和buffer(或者buffer的名称)

而我们如果希望获取window中显示的buffer可以使用函数 window-buffer, 它返回当前窗口中显示的buffer 对象。

一般在日常使用中将它们搭配使用

(defun my/show-message-buffer()
  (interactive)
  (let ((new-window (split-window nil 20 'below))) ;; 在当前窗口下方新建一个高度为20行的新窗口
    (set-window-buffer new-window "*Messages*"))) ;; 新窗口中显示 *Messages* buffer

上述例子执行之后我们发现,光标仍然停留在之前的窗口上,想要修改光标所在的窗口可以使用 select-window,它接收一个window对象表示要将光标移动到哪个窗口,或者说当前要激活哪个窗口。因此我们可以改进一下上述函数,做到立即跳转光标到新窗口。这里就不给代码了,读者可以自行尝试。

如果我们想遍历当前窗口可以使用 walk-windows ,它主要接受一个函数,每当遍历一个窗口时调用该函数。

最后再介绍一下删除窗口的操作。删除窗口操作可以使用 delete-windowquit-window, 一般而言quit-window 较为温和,而 delete-window 粗暴一些。 quit-window 用于删除一些临时性的或者弹出式窗口,而delete-window 用于删除其他窗口。

练习

本次的练习,我们结合 walk-windowscompleting-read 函数做一个遍历所有窗口并根据用户显示来将光标跳转到指定窗口的小功能。

(defun my/jump-to-selected-window ()
  "遍历所有窗口并通过补全进行跳转(支持同名 Buffer 区分)。"
  (interactive)
  (let ((window-collections '()))
    (walk-windows (lambda (win)
                    (let* ((buffer (window-buffer win))
                           (bname (buffer-name buffer))
                           ;; 生成格式如: "*scratch* [win #<window 3 on *scratch*>]"
                           (label (format "%s [%s]" bname win)))
                      (push (cons label win) window-collections))))
    (let ((selected (completing-read "请选择要跳转的窗口: " window-collections nil t)))
      (when (and selected (assoc selected window-collections))
        (select-window (cdr (assoc selected window-collections)))))))

上述代码我们考虑了多个window显示同一个buffer的问题,以buffer和window对象的字符串作为主键,后续根据用户选择来执行 select-window 操作。

总结

本篇我们介绍了基础的窗口操作,本篇介绍的函数如下:

  • split-window 创建新窗口
  • set-window-buffer 设置窗口显示的buffer
  • window-buffer 获取窗口显示的buffer对象
  • select-window 激活指定的窗口对象
  • walk-windows 遍历当前所有窗口
  • delete-windowquit-window 关闭窗口
0

评论 (0)

取消