Vim: Close All Buffers But This One - vim

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

I was able to do this pretty easily like this:
:%bd|e#

Try this
bufdo bd
bufdo runs command for all buffers
http://vim.wikia.com/wiki/Run_a_command_in_multiple_buffers

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

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

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#

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

Note: As mentioned in the comments, this closes windows and not buffers.
By using
:on[ly][!]
and
:h only

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

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.

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>

There's a plugin that does exactly this and a bit more!
Check out close-buffers.vim

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>

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.

:%bd then Ctrl-o
:%bd to delete all buffers
Ctrl-o to jump back to the last buffer, which would be the "This One" you were referring to.

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.

How about just:
ctrl-w o
(thanks to https://thoughtbot.com/blog/vim-splits-move-faster-and-more-naturally)

I combined Alejandro's comment with badteeth's comment:
command! Bonly silent execute "%bd|norm <C-O>"
The norm <C-O> 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!

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

Related

Close Multiple Buffers Programatically in Vim

I'm trying to write a function that allows me to toggle TPope's Vim Fugitive git-log viewer.
The plugin allows you to view the history of your project, by opening up git objects as buffers that begin with fugitive://
I'm trying to write a function in vimscript that will allow me to close all of these buffers at once, when they're open. The function currently looks like this, and is quite close to working:
function! ToggleGLog()
if buflisted(bufname('fugitive'))
:cclose
:bd fugitive*<C-a><cr>
else
Glog
endif
endfunction
command! ToggleGLog :silent :call ToggleGLog()
nnoremap <silent> <leader>gl :ToggleGLog<CR>
The problem that I'm encountering is that the <C-a><cr> portion of the function doesn't work. Normally, the <C-a> would expand the * selector to match all the buffers that start with "fugitive."
How can I write this so that the names of those buffers are automatically expanded and the :bd command will close them all?
How about the following?
execute "normal! :bdelete fugitive*\<C-a>\<CR>"
normal lets Vim run the command to its right as if you typed it, including keys like <C-a>. But as the latter is somewhat special, it needs to be interpreted; this is what execute is doing here. (See the end part of :help normal.)

How to have multiple views of the same buffer in vim?

I have been trying to implement a function in vimscript to switch between two views of the same buffer. The functionality I want to have is like this:
I press a key and the screen position and cursor are moved to my previously saved location. If there is not yet another saved location, it creates one at the current view and cursor location. I have a vimscript function that does exactly this functionality i described:
fun! SwitchFileMarker(reset)
if a:reset == 1
if exists("b:switch_file_window")
unlet b:switch_file_window
endif
endif
if exists("b:switch_file_window")
let cursor_location = getpos("'0")
let top_location = getpos("'9")
:execute "normal! m0Hm9`0"
call setpos('.', top_location)
:execute "normal! zt"
call setpos('.', cursor_location)
:execute "normal! zv"
else
" save the location
:execute "normal! m0Hm9`0"
endif
let b:switch_file_window = 1
endfun
nmap <leader>b :call SwitchFileMarker(0)<CR>
nmap <leader>B :call SwitchFileMarker(1)<CR>
The only problem with this function is I want it to save the folds of the current view and load the folds of the saved view when the function is called. I can achieve this by using :mkview and :loadview, but the problem with that is if the number of lines in the file changes, the folds are lost. The :mkview function seems to remember the folds at a specific line number, and If ive added several lines above that fold location while editing the file, when i use :loadview, the fold is lost. using the marks, as done in the function i show works to save my cursor position (but not folds) because the marks keep track of the changing line number. The funcionality that I am trying to get is essentially like having two views of a buffer but in the same window, rather than two windows. If i have a two windows editing the same buffer, I can add lines in one window and the folds are not lost in the other, so this is exactly the functionality I want, just in one window instead of two. Any suggestions how this can be done?
Use marks!
To set a mark, you can use m<letter> or :mark <letter>.
To go to a marked line, use '<letter>. To go to the exact position, prefer `<letter>.
If the letter is lowercase, it is buffer-local. If it is uppercase, it is global.
Edit: OP wants to save folds, which this can’t do. But it’s helpful to know anyway, so I’m leaving the answer.

How to delete a buffer in Vim without losing the split window?

When a buffer gets deleted (via the :bd[elete] command), it not only deletes the buffer but also removes the split window that buffer was in.
Is there a way to delete/unload a buffer and keep the window split?
bp|bd # will do it.
Details: The bp command (“buffer previous”) moves us to a different buffer in the current window (bn would work, too), then bd # (“buffer delete” “alternate file”) deletes the buffer we just moved away from. See :help bp, :help bd, and :help alternate-file.
I really like bufkill.vim there is a github repo as well
You can add the following to your .vimrc to have Bd work as bd but without touching the window splits:
command Bd bp\|bd \#
I found this as a useful complement to what Mud answered.
See deleting a buffer without closing the window on VIM tips wiki.
I do something similar to #Mud, but switch to previous view buffer, #, instead of the previous buffer in buffer list. Here is a binding key in my .vimrc:
nnoremap <silent> <leader>q :lclose<bar>b#<bar>bd #<CR>
Close Location windows, if exist, switch to the previous view buffer, and then close the last switched buffer.
My Choice is
:sb # | bd #
:sb 1 | bd #
: <1. Recall Buffer> | <2. Delete Buffer>
Think Like that! /// <1. Recall Buffer> | <2. Delete Buffer>
:vert sb 2 | bd #
:vert sb <tab key~completed file(buffer)name> | bd #
why?! It's easy to remember 3 (+ 1) keyword!
sb split_buffer
bd delete buffer ▶ simple 2 keywords
# or Number of buffer
vert ▶ short_form of vertical (split_buffer or else)
That are easy and very useful in many other many case!
Have a nice Day! :)
I used to use :
:bp<bar>sp<bar>bn<bar>bd<CR>
But I found certain occasions where it closed my window. On top of that the next or previous buffer might not be what you want to be displayed in the split.
Now I do this :
switch to the buffer I want to work on
Delete the alternate buffer
nnoremap <leader>d :bd#<CR>
I actually like the behaviour of :bd some of the time so I use the following combination:
nmap <silent> <Leader>d :enew \| bd#<Return>
nmap <silent> <Leader>w :bd<CR>
This allows me to use <Leader>d to close a buffer whilst maintaining splits and <Leader>w to close a buffer and split simultaneously.
:enew creates a new buffer and switches focus to it
bd # delete the last buffer that was focused

Vim close buffer but not split window

If I have 2 buffers split horizontally/vertically and want to close one of them, but i don't want to close a window. I want to keep places of split windows are the same as before closing buffer.
If I press :bd , the window in which was closed buffer also became closed.
Like #RusAlex I don't like plug-ins. I also like to know what code I enter actually does.
nmap ,d :b#<bar>bd#<CR>
In short this adds a key mapping to vim's normal mode waiting for key sequence ,d. When executed this switches to a previously open buffer and attempts to delete the buffer you switched away from.
Deleting an off-screen buffer keeps the screen split as it is.
The command consists of three space-separated parts:
nmap - add/change key mapping for mode normal
,d - key sequence to react to; first , (comma), then d
:b#<bar>bd#<CR> - key sequence to execute
The command to be executed consists of five parts:
: - switch vim to mode command-line
b# - switch window to previously open buffer
<bar> - expect a follow-up command; represents | (pipe character); used for chaining commands
bd# - delete previously open buffer, i.e. the buffer just switched away from
<CR> - execute command(s); represents carriage return, basically the keys Return or Enter
The command is in the format it is used in a configuration file like ~/.vimrc. If you want to add the mapping from within vim you prepend : (colon) - the mapping then will be lost when exiting vim:
:nmap ,d :b#<bar>bd#<CR>
When you open vim it is usually in normal mode as opposed to modes insert (indicated on the bottom of the screen by -- INSERT -- after pressing i), visual and so on. The n in nmap specifies the key mapping to be added to normal mode only. Find more on mappings here
Important notes:
b# will switch to the current buffer if it is the only known buffer.
b# may switch to a hidden/closed buffer, e.g. the one you just closed by pressing ,d.
bd# will close the current buffer if it is the only known buffer unsplitting the screen leaving you with an empty buffer.
bd# will fail if the buffer switched away from is a hidden/closed buffer.
bd# will still unsplit if after switching another window shows the buffer to close.
Additional notes:
:windo b# will switch all windows to the previously open buffer. Not sure how to combine with bd.
<CR> can be left out in which case you have to manually press Return or Enter to execute.
:nmap , displays all normal mode mappings starting with ,.
:ls lists open buffers.
It's impossible to have an empty window in vim, but you can just create a new empty file in the current window using :enew.
I'll have to check on my work computer, but I think the script I'm using for this is BufClose.
You want to delete the buffer but keep the split? You need a new buffer then - :new will do that for you, creating a buffer for a new/empty file, but you'll still need to kill the old buffer/window. In vim a window is a viewport on a buffer, so if you want an empty window you need an empty buffer.
Here's a variation on the answer provided #zenbro that keeps all your (split) windows and tabs open even if the buffer you close is the last one.
The function switches all windows pointing to the current buffer (that you are closing) to the next buffer (or a new buffer if the current buffer is the last one).
function! CloseBuffer()
let curBuf = bufnr('%')
let curTab = tabpagenr()
exe 'bnext'
" If in last buffer, create empty buffer
if curBuf == bufnr('%')
exe 'enew'
endif
" Loop through tabs
for i in range(tabpagenr('$'))
" Go to tab (is there a way with inactive tabs?)
exe 'tabnext ' . (i + 1)
" Store active window nr to restore later
let curWin = winnr()
" Loop through windows pointing to buffer
let winnr = bufwinnr(curBuf)
while (winnr >= 0)
" Go to window and switch to next buffer
exe winnr . 'wincmd w | bnext'
" Restore active window
exe curWin . 'wincmd w'
let winnr = bufwinnr(curBuf)
endwhile
endfor
" Close buffer, restore active tab
exe 'bd' . curBuf
exe 'tabnext ' . curTab
endfunction
To map it:
map <silent> <F4> :call CloseBuffer()<cr>
#RusAlex version + activate current buffer in the end need if delete buffer twice.
nmap ,d :b#<bar>bd#<bar>b<CR>
Here is some workaround:
function! CloseSplitOrDeleteBuffer()
let curNr = winnr()
let curBuf = bufnr('%')
wincmd w " try to move on next split
if winnr() == curNr " there is no split"
exe 'bdelete'
elseif curBuf != bufnr('%') " there is split with another buffer
wincmd W " move back"
exe 'bdelete'
else " there is split with same buffer"
wincmd W
wincmd c
endif
endfunction
nnoremap <silent> Q :call CloseSplitOrDeleteBuffer()<CR>

Keep the cursor column while swapping buffers in vim

In vim, if you swap buffers with :bn and :bp, the cursor stays on the same line, but not on the same column. Is there a way to keep it on the same column as well ?
:set nostartofline
from the help: "In case of buffer changing commands the cursor is placed at the column where it was the last time the buffer was edited."
Off the top of my head I don't think so. But Vim sets the mark " as the last position when exiting a buffer. So typing `" will get you back to that spot. You could try creating an auto-command to jump to that mark automatically on entering a buffer. Try something like
:au BufEnter * :normal `"

Resources