如何在两个emacs窗口之间交换缓冲区

119

我正在使用emacs,有时我会把两个文件分别放在两个窗口中。

例如: 我使用 C-x C-f file1.c RET 打开一个文件。

然后我将框架拆分成两个窗口: C-x 3

接着我打开另一个文件 C-x C-f file2.c RET

这样我就有了两个文件:

窗口1 (左) file1.c

窗口2 (右) file2.c

我想知道是否有任何快捷键可以交换这两个文件?通常情况下,当我有两个窗口时,我喜欢在左边的窗口上工作。我知道我可以轻松地通过C-x o 将光标移动到右边的窗口。

但是,我只是想知道是否可以交换这两个文件,以便 file2.c 在左窗口中,而file1.c 在右窗口中?


这也可以运行(在emacs24中测试过):交换两个缓冲区 它似乎与Bahbar的答案类似. - nephewtom
10个回答

99

我使用 buffer-move 来实现这个功能。现在,如果你正在编辑左侧的缓冲区,调用 'buf-move-right' 将会与右侧的缓冲区交换位置。我猜这正是你想要的。


这个解决方案非常完美,注释也非常清晰 - 只要确保你阅读了它们 :) - Martin Clarke
3
如果你只想交换窗口(与所选窗口无关),可以使用以下代码:(defun win-swap () "使用 buffer-move.el 交换窗口" (interactive) (if (null (windmove-find-other-window 'right)) (buf-move-left) (buf-move-right)))这段代码会调用 buffer-move.el 库来实现窗口的交换。当调用该函数时,如果当前窗口右侧没有其他窗口,则会将当前窗口向左移动,否则将当前窗口向右移动。 - mefiX
buffer-move在我只有两个窗口的布局中无法正常工作,但是使用win-swap却可以很好地工作,谢谢! - Ev Dolzhenko
2
buffer-move 的源代码中,你会看到关于将 C-S-up 映射到 buf-move-up 等所有重要映射的注释。 - Micah Elliott

70

在 Emacs 26.1 的 NEWS 文件中有以下条目:

+++
*** New command 'window-swap-states' swaps the states of two live
windows.

这似乎提供了类似于crux-transpose-windows的功能,但还可以进行一些高度/宽度方面的转置吗?


3
易懂且有效 - Pedro Delfino
易用、高效、内置,无需第三方插件。当我打开了4个文件时,它正好实现了我想要的功能,即交换左侧文件和右侧文件,同时保持其他两个文件不变。Emacs 27.2。 - Nick
这么简单,为什么这么慢?执行需要大约2秒钟。 - Jay Lee

36

transpose-frame 库提供了一系列比较全面的函数,用于翻转或旋转框架中的窗口布局。

M-x flop-frame RET 可以满足这个特定问题的需求。

以下图表来自该库的评论部分(和它在 EmacsWiki 页面中的描述):

‘transpose-frame’ … Swap x-direction and y-direction

       +------------+------------+      +----------------+--------+
       |            |     B      |      |        A       |        |
       |     A      +------------+      |                |        |
       |            |     C      |  =>  +--------+-------+   D    |
       +------------+------------+      |   B    |   C   |        |
       |            D            |      |        |       |        |
       +-------------------------+      +--------+-------+--------+

‘flip-frame’ … Flip vertically

       +------------+------------+      +------------+------------+
       |            |     B      |      |            D            |
       |     A      +------------+      +------------+------------+
       |            |     C      |  =>  |            |     C      |
       +------------+------------+      |     A      +------------+
       |            D            |      |            |     B      |
       +-------------------------+      +------------+------------+

‘flop-frame’ … Flop horizontally

       +------------+------------+      +------------+------------+
       |            |     B      |      |     B      |            |
       |     A      +------------+      +------------+     A      |
       |            |     C      |  =>  |     C      |            |
       +------------+------------+      +------------+------------+
       |            D            |      |            D            |
       +-------------------------+      +-------------------------+

‘rotate-frame’ … Rotate 180 degrees

       +------------+------------+      +-------------------------+
       |            |     B      |      |            D            |
       |     A      +------------+      +------------+------------+
       |            |     C      |  =>  |     C      |            |
       +------------+------------+      +------------+     A      |
       |            D            |      |     B      |            |
       +-------------------------+      +------------+------------+

‘rotate-frame-clockwise’ … Rotate 90 degrees clockwise

       +------------+------------+      +-------+-----------------+
       |            |     B      |      |       |        A        |
       |     A      +------------+      |       |                 |
       |            |     C      |  =>  |   D   +--------+--------+
       +------------+------------+      |       |   B    |   C    |
       |            D            |      |       |        |        |
       +-------------------------+      +-------+--------+--------+

‘rotate-frame-anti-clockwise’ … Rotate 90 degrees anti-clockwise

       +------------+------------+      +--------+--------+-------+
       |            |     B      |      |   B    |   C    |       |
       |     A      +------------+      |        |        |       |
       |            |     C      |  =>  +--------+--------+   D   |
       +------------+------------+      |        A        |       |
       |            D            |      |                 |       |
       +-------------------------+      +-----------------+-------+

2
flop-frame仅在窗口之间的分割垂直时才有效,对于水平分割,您需要使用flip-frame。然而,rotate-frame无论分割方向如何都有效;只需一个命令即可在两个窗口之间交换缓冲区 :) - legends2k

16
如果您正在使用Prelude,则可以直接使用C-c s (prelude-swap-windows)进行操作。根据Prelude文档所述:

C-c s运行命令crux-swap-windows (在prelude-mode-map中找到), 这是crux.el中的crux-transpose-windows的别名。


Prelude 看起来很复杂(而且没有任何打包 - curl | sh = wtf?),但 Crux 确实看起来很不错,并且做了一堆我自己一开始就做的事情。 - anarcat
我知道curl | sh是什么,但我的意思是:它很邪恶。 - anarcat

11

我不知道是否有任何内置的函数能够做到这一点。

然而,似乎很容易编写一些elisp来完成它。但是细节决定成败。

(defun swap-buffers-in-windows ()
  "Put the buffer from the selected window in next window, and vice versa"
  (interactive)
  (let* ((this (selected-window))
     (other (next-window))
     (this-buffer (window-buffer this))
     (other-buffer (window-buffer other)))
    (set-window-buffer other this-buffer)
    (set-window-buffer this other-buffer)
    )
  )

值得注意的是,这可能与您希望插入符号最终停留的位置不符。 然而,您首先需要说明您想要什么 :p


我复制并粘贴了这段代码,但似乎没有任何反应。 - user181548
好的。你让我有点困惑了。你提到了C-x 3。这是用来创建2个Emacs窗口,而不是2个Emacs框架。你是在使用框架还是窗口?你如何称呼窗口和框架? - Bahbar
另外,您没有提到顶部和底部部分。您同时显示超过2个缓冲区吗? - Bahbar
我不是提问的人,我只是一个闯入者。在看到这个问题之前,我从未使用过C-x 3,但正如你所说的那样,它会分割Emacs窗口,而不是创建一个新框架。 - user181548
嗯,你的答案似乎是正确的!不知何故,尽管我努力了,但我一直无法理解Lisp。 - user181548
显示剩余3条评论

9

目前的emacs 29版本中,我们有windmove,它可以像魔法一样交换窗口。

windmove-swap-states-right windmove-swap-states-up windmove-swap-states-left windmove-swap-states-down


2
如果您使用我强烈推荐的Ace window,您可以使用ace-swap-window来交换缓冲区。

2
如果您使用prelude,可以使用S-w来使用ace-window。从那里,您可以执行许多在其文档中列出的操作。
您也可以通过调用ace-window开始,然后决定切换到删除或交换等操作。默认情况下绑定如下:
x - 删除窗口 m - 交换(移动)窗口 c - 公平地拆分窗口,垂直或水平 v - 垂直拆分窗口 b - 水平拆分窗口 n - 选择上一个窗口
因此,它将是S-w m

对于Spacemacs用户,ace-swap-window绑定到SPC w M。此功能默认可用。 - Claudio

1

以下代码片段可以切换缓冲区。

(defun ab/switch-buffer-each-other (arg)
  "switch current buffer with other window buffer 
   right-2-left and up-2-down"
  (interactive "p")
  (cond
   ((windmove-find-other-window 'right) (buf-move-right))
   ((windmove-find-other-window 'left) (buf-move-left))
   ((windmove-find-other-window 'up) (buf-move-up))
   ((windmove-find-other-window 'down) (buf-move-down)))
(message "switch buffer done"))

-1
我会设法在所需位置打开文件#2,即在按下c-x 3后,使用c-x o移动光标并导航到第二个文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接