ZMonster's Blog 巧者劳而智者忧,无能者无所求,饱食而遨游,泛若不系之舟

Emacs中的窗口操作

窗口

这里的窗口并不是指桌面环境中的窗口,而是指 Emacs 中的显示单元。在 Emacs 中,显示一个缓冲区内容的区域,就被称为 "窗口"。

一个窗口中只能显示一个缓冲区,而一个缓冲区是可以显示在多个窗口中的。出于一些需要,我们可能在使用 Emacs 的时候将整个 Emacs 显示区域分割成多个窗口,本文就将对这种情形下对窗口的常用操作做简要介绍。

窗口的新增

新增窗口是通过对当前窗口的分割来产生的,分割有两种方式:

  • C-x 2: 将当前窗口分割为上下两个,如下图所示

    emacs-window-split-hor.gif

  • C-x 3: 将当前窗口分割为左右两个,如下图所示

    emacs-window-split-ver.gif

分割后的子窗口都想显示被分割的窗口当时显示的缓冲区,如果想要在分割后切换到另外一个缓冲区,以下我编写的方法可以作为参考:

;; 将当前窗口分割为上下两个,并切换到另外一个 buffer
(defun split-window-new-buffer ()
  (interactive)
  (split-window-below)
  (call-interactively 'switch-to-buffer))

窗口的删除

窗口的删除有三个可用的快捷键,分别是:

  • C-x 0: 删除当前窗口
  • C-x 1: 删除当前窗口外的其他窗口
  • C-x 4 0: 删除当前窗口,并关闭其中显示的缓冲区

窗口的切换

默认的方法

Emacs 中提供了 C-x o(字母) 这个快捷键来在窗口间循环移动,方向大致是顺时针方向。分割的窗口数稍微一多的话,这么一个快捷键肯定是不够的。

事实上 C-x o 是调用了 other-window 这个内建方法,通过 C-h f 可以知道这个方法的原型是:

(other-window COUNT &optional ALL-FRAMES)

它的参数里我们要关心的是 COUNT 这个参数,这个参数可以取三种值:

  • 为正整数: 顺时针前进指定数目的窗口
  • 等于0: 原地不动
  • 为负整数: 逆时针前进指定数目(COUNT的绝对值)的窗口

所以我们可以很自然地写出一个 "切换到上一个窗口" 的方法来:

(defun prev-window ()
  (interactive)
  (other-window -1))

然后可以按自己的需要绑定到指定的快捷键上,以 C-x p 为例:

(global-set-key (kbd "C-x p") 'prev-window)

windmove package

Emacs 中其实还内置了更为简易的切换方法,可以向当前窗口指定方向的邻近窗口切换,不过并未给这些方法提供默认的快捷键绑定。

共有四个方法,它们在 windmove 这个包中被定义和实现:

  • windmove-up
  • windmove-down
  • windmove-right
  • windmove-left

功能的话看它们的名称就看得出来,我想就不用多解释了。

我们可以自己来进行绑定,或者也可以使用默认的设置:

(windmove-default-keybindings)

在配置文件中添加上面这句后,我们将可以使用 Shift+方向键 的方式来进行窗口切换。为求方便一般还会在其后跟上以下这句:

(setq windmove-wrap-around t)

这一条语句的作用是让 windmove 在边缘的窗口也能正常运作。举个例子,当前窗口已经是最左端的窗口了,如果使用 Shift+left ,将仍会停留在当前窗口——因为已经到边缘了,左边没有窗口可供选择。但在添加了上面这句后,Shift+left 将会跳到最右边的窗口中。垂直方向上的窗口切换同理。

窗口布局的保存与恢复

Emacs 中已经内置了窗口布局的保存与恢复功能,通过在配置文件中添加下列语句就可以启用布局保存功能:

(desktop-save-mode 1)

初次启用的时候会询问是否保存 "desktop" ,这个时候需要选择保存位置,布局一般会保存为名为 .emacs.desktop 的文件。

desktop-save-mode 不仅会保存窗口布局,还会保存每个窗口中打开了什么缓冲区,每个缓冲区中的光标位于哪一行这些非常游泳的信息,所以还是非常方便的。

不过虽然保存了 desktop 文件,Emacs 启动的时候却不会去主动加载它,一种办法是在配置文件里定义一个变量保存 desktop 文件所在的目录,然后在启动的时候就加载它:

(setq desktop-dir "~/Dropbox/doc/")
(desktop-read desktop-dir)

不过上面这样的设置是不够完美的,假如我们不带任何参数启动 Emacs ,当然是没什么问题,但如果我们是用 Emacs 打开某个文件,这样做明显是不合理的。