ChatGPT解决这个技术问题 Extra ChatGPT

Vim: Close All Buffers But This One

vim

How can I close all buffers in Vim except the one I am currently editing?

I fount this link

O
OldTimeGuitarGuy

I was able to do this pretty easily like this:

:%bd|e#

This is a nice answer. It makes BufOnly feel a bit overkill (I mean, a whole plugin?) unless you're using the argument passing feature of BufOnly. All I ever want to really do is :%bd|e#
@jorgeh %bd = delete all buffers. e# = open the last buffer for editing. The pipe in between just does one command after another.
@Jared You can use %bd|e#|bd# to delete the [No Name] buffer that gets created.
Wonderful. Then here you have the only thing I ever used the BufOnly plugin for, distilled to a single command: command! BufOnly silent! execute "%bd|e#|bd#"
@Finn you need to escape |: map <leader>o :%bd\|e#<cr>
g
gayavat

Try this

bufdo bd

bufdo runs command for all buffers

http://vim.wikia.com/wiki/Run_a_command_in_multiple_buffers


This doesn't close the NERDTree buffer.
You might want to close NERDTree before doing this to prevent the bd command close the vim itself; nnoremap <silent> <leader>c :NERDTreeClose<bar>bufdo bd<CR>.
The documentation warns that the argument to :bufdo ‘must not delete buffers or add buffers to the buffer list’. So if this solution works, it works by accident … and it often doesn’t work for me (switches to a different buffer).
This closes all buffers for me, which is not what the questions asks. (MacVim version 8.0.1207)
This command closes all the buffers. How can I leave the current one open?
V
VoY

You could use this script from vim.org:

http://www.vim.org/scripts/script.php?script_id=1071

Just put it to your .vim/plugin directory and then use :BufOnly command to close all buffers but the active one. You could also map it elsewhere you like in your .vimrc.

Source on Github (via vim-scripts mirror): https://github.com/vim-scripts/BufOnly.vim/blob/master/plugin/BufOnly.vim


j
juananruiz

If you don´t care the current one, is more simple to do something like (no script needing):

1,100bd

It will close nerdtree buffer as well.
I faced some problems using this command when NERDTree is enabled. I recomment using the BufOnly.vim plugin as mentioned by @VoY .
I made the following mapping which accounts for deleting the NERDTree buffer: nnoremap <leader>bd :%bd | NERDTree<cr>
I used this for a long time, but now I get E16: Invalid range because some of the buffers in the range don't actually exist. It was ignoring that until recently.
@Jon Check :ls to see the largest buffer you actually have open, and set your range to that (i.e. if your highest buffer is 22, then :1,22bd). I got the same error until I did that.
i
iamnotsam

I do this

:w | %bd | e#

My favorite if I just want my current buffer open and close all others.

How it works: first write current buffer's changes, then close all open buffers, then reopen the buffer I was currently on. In Vim, the | chains the execution of commands together. If your buffer is up to date the above can be shortened to :%bd | e#


It mostly works fine. but sometimes % can't work as all selector. Could you guess anything?
@JinyoungKim (from [1]) In the ":%bd" command, the '%' range will be replaced with the starting and ending line numbers in the current buffer. Instead of using '%' as the range, you should specify numbers for the range. For example, to delete all the buffers, you can use the command ":1,9999bd" [1] vimdoc.sourceforge.net/cgi-bin/vimfaq2html3.pl#8.8
I just checked out the document. So then, '%' range rely on a number of current file lines?
I found built-in function bufnr("$") that returns last buffer number. but I have no idea to interpolate to string when I use like this :1,bufnr("$")bd. Maybe.. best solution would be :1,9999bd.
:help :bd shows :%bdelete " delete all buffers. So % is exactly what you want. I use a variant of your solution: :%bd<CR><C-O>:bd#<CR> This will delete all buffers, then use <C-O> to get restore the position in the current file, then :bd# to remove the unamed buffer. This closes all buffers and leaves you in the same location in the file.
c
cutemachine

Building on juananruiz's answer.

Make a small change in the buffer you want to keep, then

:1,1000bd

The command bd (buffer delete) will not delete any buffers with unsaved changes. This way you can keep the current (changed) file in the buffer list.

Edit: Please notice that this will also delete your NERDTreeBuffer. You can get it back with :NERDTree


Perfect, short and simple! :)
:%bd is actually "all" instead 1-1000.
Does this rely on set nohidden to be set?
This is the best answer. Even works when you want to keep more than one buffer.
C
CH.

Note: As mentioned in the comments, this closes windows and not buffers.

By using

:on[ly][!]

and

:h only

Still useful, as people may well Googling for the wrong term, and will find this. So thanks to both of you. :)
@archgoon yeah, but should be specified in the answer.
Y
Yulin

I put this in my .vimrc file

nnoremap <leader>ca :w <bar> %bd <bar> e# <bar> bd# <CR>

then your leader + ca (close all) close all the buffers except the current one.

What it does is

:w - save current buffer

%bd - close all the buffers

e# - open last edited file

bd# - close the unnamed buffer


Love it, tweaked slightly and added to my config: nnoremap <silent> <leader>bo :w <bar> %bd <bar> e# <bar> bd# <CR><CR>
0
0xMH

Here's what I do. So I like to keep my cursor position after removing all buffers and most of the solutions above just ignores this fact. I also think remapping the command is better than typing it so Here I use <leader>bd to remove all buffers and jump back to my original cursor position.

noremap <leader>bd :%bd\|e#\|bd#<cr>\|'"

%bd = delete all buffers.

e# = open the last buffer for editing (Which Is the buffer I'm working on).

bd# to delete the [No Name] buffer that gets created when you use %bd.

The pipe in between just does one command after another. You've gotta escape it though using \|

'" = keep my cursor position.


m
mynyml

Closing all open buffers:

silent! execute "1,".bufnr("$")."bd"

Closing all open buffers except for the current one:

function! CloseAllBuffersButCurrent()
  let curr = bufnr("%")
  let last = bufnr("$")

  if curr > 1    | silent! execute "1,".(curr-1)."bd"     | endif
  if curr < last | silent! execute (curr+1).",".last."bd" | endif
endfunction

Add this function to .vimrc and call it using :call CloseAllBuffersButCurrent().

Convenience map:

nmap <Leader>\c :call CloseAllBuffersButCurrent()<CR>

I noticed that when resuming vim sessions, which does restore buffers, I wasn't able to remove buffers anymore using the above. Instead, I had to use :%bd|e#|bd#
Best solution. I added a command to reopen NERDTree nmap <Leader>\c :call CloseAllBuffersButCurrent()<CR>:NERDTree<CR>
N
Niko Bellic

There's a plugin that does exactly this and a bit more!

Check out close-buffers.vim


Absolutely fantastic plugin! Having tried the other options (remappings) I highly recommend this plugin.
B
BrendanArms

so this is an old question but it helped me get some ideas for my project. in order to close all buffers but the one you are currently using, use;

map <leader>o :execute "%bd\|e#"<CR>


C
Community

I like 1,100bd (suggested by juananruiz) which seems to work for me.

I added a quit! to my mapping to give me

nnoremap <leader>bd :1,100bd<CR>
nnoremap <leader>bdq :1,100bd<CR>:q!<CR>

This kills all the buffers and shuts down Vim, which is what I was looking for mostly.


There's really no reason for you to have the bdq mapping that closes all buffers and exits vim with :q!, when instead you can just use :qa!. Unless I'm overlooking something
D
Dave Powers

How about just:

ctrl-w o

(thanks to https://thoughtbot.com/blog/vim-splits-move-faster-and-more-naturally)


This closes windows, not buffers.
c
cxw

I combined Alejandro's comment with badteeth's comment:

command! Bonly silent execute "%bd|norm <C-O>"

The norm jumps to the last position in the jump list, which means where the cursor was before the %bd.

I used silent instead of silent!. That way, if any open buffers are modified, Vim prints an error message so I know what happened. The modified buffers stay open in my tests.

Unrelated: this is my 500th answer!


d
drzel
nnoremap <leader>x :execute '%bdelete\|edit #\|normal `"'\|bdelete#<CR>

Close all buffers (side-effect creates new empty buffer)

Open last buffer

Jump to last edit position in buffer

Delete empty buffer


c
chunyang.wen

The answer with highest votes will reopen the buffer, it will lose the current line we are working on.

Close then reopen will induce a flush on screen

function! CloseOtherBuffer()
    let l:bufnr = bufnr()
    execute "only"
    for buffer in getbufinfo()
        if !buffer.listed
            continue
        endif
        if buffer.bufnr == l:bufnr
            continue
        else
            if buffer.changed
                echo buffer.name . " has changed, save first"
                continue
            endif
            let l:cmd = "bdelete " . buffer.bufnr
            execute l:cmd
        endif
    endfor
endfunction

let mapleader = ','
nnoremap <leader>o :call CloseOtherBuffer()<CR>

Previous code will take effect when you are on the target buffer and press , + o. It will close all other buffers except current one.

It iterates all the buffers and close all the buffer number which is not equal to current buffer number.