在Emacs中关闭当前缓冲区以外的所有缓冲区

107

如何在Emacs中关闭除当前缓冲区以外的所有缓冲区?类似于现代Web浏览器中的“关闭其他标签页”功能?

11个回答

109

如果您想要更加手动的方法,可以使用C-x C-b列出所有缓冲区,在列表中用d标记要删除的缓冲区,然后使用x将它们删除。

我还建议将list-buffers替换为更高级的ibuffer:(global-set-key (kbd "C-x C-b") 'ibuffer)。上述方法也适用于ibuffer,但您还可以这样做:

m(标记要保留的缓冲区)
t(切换标记)
D(删除所有标记的缓冲区)

我还使用了来自Emacs Wiki的代码片段,这将进一步简化这种手动方法:

;; Ensure ibuffer opens with point at the current buffer's entry.
(defadvice ibuffer
  (around ibuffer-point-to-most-recent) ()
  "Open ibuffer with cursor pointed to most recent buffer name."
  (let ((recent-buffer-name (buffer-name)))
    ad-do-it
    (ibuffer-jump-to-buffer recent-buffer-name)))
(ad-activate 'ibuffer)

我怎样从 ibuffer 返回?@phils - alper
1
我不确定你在问什么,但也许是 q?使用 C-h m 来学习按键绑定,就像任何其他模式一样。 - phils

61

来自EmacsWiki:Killing Buffers:

(defun kill-other-buffers ()
    "Kill all other buffers."
    (interactive)
    (mapc 'kill-buffer 
          (delq (current-buffer) 
                (remove-if-not 'buffer-file-name (buffer-list)))))

编辑: 根据 Gilles 的反馈更新


3
为什么 Dired 缓冲区没有被关闭?我想把它也删除掉。 - swdev
dired缓冲区不设置“buffer-file-name”,因此上面示例中对“remove-if-not”的调用将保留dired缓冲区(以及scratch缓冲区、term缓冲区、help缓冲区等,任何未访问文件的内容)。我想不出一个简单的测试来关闭文件缓冲区和dired缓冲区,你需要基本上使用另一个测试的整个第二次mapc调用来处理dired缓冲区。 - robru
一个简单的修改,以便删除dired缓冲区(defun kill-other-buffers () "杀死所有其他缓冲区." (interactive) (mapc 'kill-buffer (delq (current-buffer) (remove-if-not '(lambda (x) (or (buffer-file-name x) (eq 'dired-mode (buffer-local-value 'major-mode x)))) (buffer-list))))) - frinkr
在这个视频中,这个人似乎能够做到这一点。他打开了一个新的Slime缓冲区,同时关闭了GNU缓冲区和其他缓冲区。你有任何想法他是如何做到的吗?https://www.youtube.com/watch?v=BKFcznZ28BE&t=310s - MadPhysicist
cl-remove-if-not替换为remove-if-not可以解决问题,但这并不能关闭*helm..缓冲区。 - alper

22

在 Emacs 中没有直接实现这个功能的方法。

你可以编写一个函数来实现。下面的代码将关闭所有缓冲区:

(defun close-all-buffers ()
  (interactive)
  (mapc 'kill-buffer (buffer-list)))

5
啊,但这将关闭所有缓冲区。 - Sridhar Ratnakumar
1
(delete (current-buffer) (buffer-list)) 应该会给你一个缓冲区列表,你可以在其中映射 kill-buffer 并避免杀死当前缓冲区。 - NickD
@NickD:没错,运行良好。谢谢! - Carl Winbäck

19

有一个内置命令m-x kill-some-buffers(使用的是24.3.50版)在我的NextStep GUI中(没有在终端中尝试,但肯定相似),您可以批准要终止的缓冲区。


5
当你加载了1000个以上的缓冲区时,这将特别有用。 - ocodo
3
你的意思是字面意义还是比喻意义? - Aaron Bell

12
 (defun only-current-buffer () 
   (interactive)
   (let ((tobe-killed (cdr (buffer-list (current-buffer)))))
     (while tobe-killed
       (kill-buffer (car tobe-killed))
       (setq tobe-killed (cdr tobe-killed)))))

它的表现与您期望的一样。

在阅读了@Starkey的回答后,我认为这样会更好:

(defun only-current-buffer () 
  (interactive)                                                                   
    (mapc 'kill-buffer (cdr (buffer-list (current-buffer)))))

(buffer-list (current-buffer))将返回一个包含所有现有缓冲区的列表,其中当前缓冲区位于列表的开头。

这是我在StackOverflow上的第一篇答案。希望能对你有所帮助 :)


2
这就是朋友们分享想法所带来的优雅解决方案。 - Chris Clark
我不知道“buffer-list”的规范是否在这些年里发生了变化,但是按照上面的答案使用(buffer-list (current-buffer))不会起作用。请运行C-h f buffer-list RET以获取当前的规范。 - NickD

7
我发现这个解决方案是最简单的。它会删除除当前缓冲区之外的所有缓冲区。你需要将这段代码添加到你的.emacs文件中。
(defun kill-other-buffers ()
      "Kill all other buffers."
      (interactive)
      (mapc 'kill-buffer (delq (current-buffer) (buffer-list))))

当然,然后您可以使用 M-x kill-other-buffers RET 进行操作,或者将以下代码粘贴到 .emacs 文件中,然后只需按 C-xC-b 即可。
(global-set-key (kbd "C-x C-b") 'kill-other-buffers)

2
你也可以喜欢这个 - 关闭所有缓冲区,除了当前的缓冲区、*Messages*和*scratch*(它们很方便,我称它们为“工具包”),同时关闭多余的窗口,只留下一个窗口和当前缓冲区。
(defun my/kill-all-buffers-except-toolbox ()
  "Kill all buffers except current one and toolkit (*Messages*, *scratch*). Close other windows."
  (interactive)
  (mapc 'kill-buffer (remove-if
                       (lambda (x)
                         (or
                           (eq x (current-buffer))
                           (member (buffer-name x) '("*Messages*" "*scratch*"))))
                       (buffer-list)))
  (delete-other-windows))

1
(string-equal (buffer-name) (buffer-name x)) is the same as (eq x (current-buffer)), just less efficient. The remaining or can be simplified to (member (buffer-name x) '("*Messages*" "*scratch*")) - Stefan
现在 cl 已经被弃用(定义了 remove-if),是否有其他替代方案?这非常有用... - sgmoye

1

我已经使用crux-kill-other-buffers几个月了。

但是我也希望dired缓冲区也能被删除。@Euge和@wenjun.yan的答案解决了这个问题。但它会删除特殊的缓冲区(例如*git-credential-cache--daemon*,*scratch*,helm操作等)。所以我想出了这个(当前的)解决方案。

(defun aza-kill-other-buffers ()
  "Kill all buffers but current buffer and special buffers"
  (interactive)
  (dolist (buffer (delq (current-buffer) (buffer-list)))
    (let ((name (buffer-name buffer)))
      (when (and name (not (string-equal name ""))
             (/= (aref name 0) ?\s)
             (string-match "^[^\*]" name))
        (funcall 'kill-buffer buffer)))))

启发自kill-matching-buffers。如果您想要排除其他缓冲区名称,可以在其他condition上添加更多条件。
希望能对您有所帮助 :)

请查看此链接以获取我的改进解决方案。 - azzamsa

0

我已经使用了这个列表中的一个解决方案多年,但现在我有了自己的新解决方案。

(defun kill-all-file-buffers ()
  "Kills all buffers that are open to files. Does not kill
modified buffers or special buffers."
  (interactive)
  (mapc 'kill-buffer (cl-loop for buffer being the buffers
                              when (and (buffer-file-name buffer)
                                        (not (buffer-modified-p buffer)))
                              unless (eq buffer (current-buffer))
                              collect buffer)))

cl-loop内置了缓冲区作为一个集合,您可以迭代它。这给了您一个机会来解析出您不想关闭的任何内容。在这里,我确保它不会关闭您修改过的任何内容,并且它使用buffer-file-name而不仅仅是buffer-name,因此它不会杀死特殊缓冲区。我还添加了一个“unless”来删除当前缓冲区(尽管您显然可以将其添加到“when”中,但我认为这更清晰)。

但是,对于更通用的解决方案,我们可以将其定义为宏,并传递一个将应用于所有这些缓冲区的函数。

(defmacro operate-on-file-buffers (func)
  "Takes any function that takes a single buffer as an argument
and applies that to all open file buffers that haven't been
modified, and aren't the current one."
  `(mapc ,func (cl-loop for buffer being the buffers
                            when (and (buffer-file-name buffer)
                                      (not (buffer-modified-p buffer)))
                            unless (eq buffer (current-buffer))
                            collect buffer)))

现在,如果您想要杀死所有匹配此的缓冲区,可以这样调用它。
(operate-on-file-buffers 'kill-buffer)

0
(defun px/kill-other-buffers ()
  "Kill all other buffers."
  (interactive)
  (mapc (lambda (buffer)
          (when (and (buffer-file-name buffer) (not (eq buffer (current-buffer))))
            (kill-buffer buffer)))
        (buffer-list)))

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