Close all buffers besides the current one in Emacs
Asked Answered
S

12

107

How do I close all but the current buffer in Emacs? Similar to "Close other tabs" feature in modern web browsers?

Sarcous answered 5/8, 2010 at 17:29 Comment(0)
S
62

From 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)))))

Edit: updated with feedback from Gilles

Sarcous answered 5/8, 2010 at 17:34 Comment(5)
Why do the dired buffer not being killed? I like to remove that alsoWharfinger
dired buffers don't set buffer-file-name and thus the call to remove-if-not in the above example will preserve dired buffers (as well as scratch buffer, term buffers, help buffers, etc, anything not visiting a file). I can't think of an easy test that would close both file buffers and dired buffers, you'd need basically a whole second invocation of mapc with a different test for dired buffers.Adolescent
a simple modification to kill also dired buffers (defun kill-other-buffers () "Kill all 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)))))Acuate
It looks like in this video the man is able to do that. He opens a new Slime buffer whilst closing the GNU buffers and others. Do you have any idea how he does that? youtube.com/watch?v=BKFcznZ28BE&t=310sMcginty
Replacing cl-remove-if-not with remove-if-not works but this does not kill *helm.. buffersVermouth
M
109

For a more manual approach, you can list all buffers with C-x C-b, mark buffers in the list for deletion with d, and then use x to remove them.

I also recommend replacing list-buffers with the more advanced ibuffer: (global-set-key (kbd "C-x C-b") 'ibuffer). The above will work with ibuffer, but you could also do this:

m (mark the buffer you want to keep)
t (toggle marks)
D (kill all marked buffers)

I also use this snippet from the Emacs Wiki, which would further streamline this manual approach:

;; 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)
Mudslinger answered 5/8, 2010 at 22:23 Comment(2)
How can I return from ibuffer? @MudslingerVermouth
I'm not sure what you're asking, but maybe q? Use C-h m to learn keybindings, just as with any other mode.Mudslinger
S
62

From 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)))))

Edit: updated with feedback from Gilles

Sarcous answered 5/8, 2010 at 17:34 Comment(5)
Why do the dired buffer not being killed? I like to remove that alsoWharfinger
dired buffers don't set buffer-file-name and thus the call to remove-if-not in the above example will preserve dired buffers (as well as scratch buffer, term buffers, help buffers, etc, anything not visiting a file). I can't think of an easy test that would close both file buffers and dired buffers, you'd need basically a whole second invocation of mapc with a different test for dired buffers.Adolescent
a simple modification to kill also dired buffers (defun kill-other-buffers () "Kill all 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)))))Acuate
It looks like in this video the man is able to do that. He opens a new Slime buffer whilst closing the GNU buffers and others. Do you have any idea how he does that? youtube.com/watch?v=BKFcznZ28BE&t=310sMcginty
Replacing cl-remove-if-not with remove-if-not works but this does not kill *helm.. buffersVermouth
A
22

There isn't a way directly in emacs to do this.

You could write a function to do this. The following will close all the buffers:

(defun close-all-buffers ()
  (interactive)
  (mapc 'kill-buffer (buffer-list)))
Andryc answered 5/8, 2010 at 17:34 Comment(3)
Ah, but this will close all buffers.Sarcous
(delete (current-buffer) (buffer-list)) should give you a buffer list that you can map kill-buffer across and avoid killing the current buffer.Antebellum
@NickD: Yep, works fine. Thank you!Oxbow
M
19

There is a built in command m-x kill-some-buffers (I'm using 24.3.50) In my nextstep gui (not tried in a terminal but sure it's similar) you can then approve which buffers to kill.

Mikamikado answered 25/8, 2013 at 11:50 Comment(2)
This is especially useful when you have 1000+ buffers loaded.Scarito
@Scarito Did you mean this literally or figurativelyGuernsey
S
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)))))

It works as you expected.

And after reading @Starkey's answer, I think this will be better:

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

(buffer-list (current-buffer)) will return a list that contains all the existing buffers, with the current buffer at the head of the list.

This is my first answer on StackOverflow. Hope it helps :)

Stickup answered 4/1, 2013 at 16:41 Comment(2)
And this my friends is how elegant solutions arise from people sharing their ideasHenricks
I don;t know if the spec for buffer-list changed over the years, but (buffer-list (current-buffer)) to work as the answer above indicates will NOT work. Do C-h f buffer-list RET for the current spec.Antebellum
V
7

I found this solution to be the simplest one. This deletes every buffer except the current one. You have to add this code to your .emacs file

(defun kill-other-buffers ()
      "Kill all other buffers."
      (interactive)
      (mapc 'kill-buffer (delq (current-buffer) (buffer-list))))

Of course, then you use it with M-x kill-other-buffers RET or you paste the following code in the .emacs file too and then just press C-xC-b

(global-set-key (kbd "C-x C-b") 'kill-other-buffers)
Vomitory answered 17/3, 2017 at 15:59 Comment(0)
A
2

You can like this one as well - kill all buffers except current one, *Messages* and *scratch* (which are handy to have, I call them "toolkit"), close redundant windows as well, living you which one window which current buffer.

(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))
Angelynanger answered 30/7, 2018 at 12:21 Comment(2)
(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*"))Tamworth
Now that cl is deprecated (defines remove-if), is there an alternative approach? This has been extremely useful...Phina
J
1

I've use crux-kill-other-buffers for some months.

But I want dired buffers get deleted too. @Euge's and @wenjun.yan's answers solve this. But it will delete special buffers (e.g *git-credential-cache--daemon*, *scratch*, helm operation, and etc). So I came up with this (current) solution.

(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)))))

Inspired from kill-matching-buffers. You can add more condition on other buffer-name to exclude, if you want to.

Hope it helps :)

Jeffery answered 22/9, 2018 at 10:45 Comment(1)
See this for my improved solution.Jeffery
S
0

I've used one of the solutions in this list for years, but now I have a new one of my own.

(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 has buffers built in as a collection that you can iterate over. It gives you a chance to parse out anything you don't want to close. Here, I've made sure that it doesn't close anything you've modified, and it uses buffer-file-name instead of just buffer-name so it doesn't kill special buffers. I also added an 'unless' to take out the current buffer (though you could obviously add it to the 'when', I just thought this was clearer).

But for an even more generic solution, we can define this as a macro, and pass in a function that will apply to all these buffers.

(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)))

Now if you want to kill all buffers that match this, you can call it like this

(operate-on-file-buffers 'kill-buffer)
Stevens answered 13/7, 2021 at 18:32 Comment(0)
S
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)))
Sumption answered 27/6, 2023 at 8:35 Comment(0)
T
-1
(defvar my/kill-buffer-exceptions '("Messages" "emacs-file" "scratch"))
(defun my/kill-buffer-testfn (key lcar)
  ;; (print (list lcar key (string-match-p (regexp-quote key) lcar)))
  (string-match-p (regexp-quote key) lcar))

(defun my/kill-other-buffers ()
    "Kill all other buffers."
    (interactive)
    (mapc 'kill-buffer
          (delq (current-buffer) ; filter current buder
                ;; filter alive and not system
                (seq-filter (lambda (b) (and (buffer-live-p b) ; filter alive
                                             (/= (aref (buffer-name b) 0) ?\s) ; filter system
                                             ;; filter exceptions
                                             (not (seq-contains-p my/kill-buffer-exceptions
                                                             (downcase (buffer-name b))
                                                             #'my/kill-buffer-testfn))))
                            (seq-uniq (buffer-list))))))

(global-set-key (kbd "C-!") #'my/kill-other-buffers)
Trodden answered 31/3 at 22:31 Comment(0)
I
-5

This is what you want:

C-x 1

source: https://blasphemousbits.wordpress.com/2007/05/04/learning-emacs-part-4-buffers-windows-and-frames/

Imbecile answered 24/12, 2019 at 19:19 Comment(1)
I think the reason you got down-voted was that OP is asking to close other buffers, not windows. Emacs terminology can be a bit confusing.Kathrinkathrine

© 2022 - 2024 — McMap. All rights reserved.