(Move categories to tip template) |
(preious -> previous) |
||
Line 19: | Line 19: | ||
* If I close the buffer in a window, it '''must not be closed''' in the other possible windows. |
* If I close the buffer in a window, it '''must not be closed''' in the other possible windows. |
||
* If there is an alternate buffer must be showing that. |
* If there is an alternate buffer must be showing that. |
||
− | * If there is not alternate buffer then must be showing the |
+ | * If there is not alternate buffer then must be showing the previous buffer. |
* If there is no alternate nor previous buffer (it is the only buffer) must show an empty buffer. |
* If there is no alternate nor previous buffer (it is the only buffer) must show an empty buffer. |
||
Revision as of 17:12, 19 August 2008
Duplicate tip
This tip is very similar to the following:
These tips need to be merged – see the merge guidelines.
created December 17, 2003 · complexity basic · author Charles E. Campbell, Jr. · version 5.7
In short: if I close a buffer (with :bn for example), I want its window to stay, showing its previous buffer.
The behaviour details:
- The window layout must be kept in all circumstances.
- If I close the buffer in a window, it must not be closed in the other possible windows.
- If there is an alternate buffer must be showing that.
- If there is not alternate buffer then must be showing the previous buffer.
- If there is no alternate nor previous buffer (it is the only buffer) must show an empty buffer.
This is how it should work (gnu-emacs kill-buffer does it right):
- In a multi-window environment:
- visit a file in window,
- go to 2nd file (vim gf)
- go to 3rd file
- kill-buffer of 3rd file, and you are back to the view of 2nd file, without disturbing windows splits / cursor position
- kill 2nd file, and voila, you are back to 1st file.
Evolution of solutions
A list of trials and their flaws.
Vim internal
As you can see, the :bn cannot satisfy these requirements at all.
Small command
Here's a small command for your <.vimrc>:
com! Kwbd enew|bw # | bn map bd :Kwbd<CR> :com! Kwbd let kwbd_bn= bufnr("%")|enew|exe "bdel ".kwbd_bn|unlet kwbd_bn
To use it, type :Kwbd or bd Kwbd stands for: Keep window (layout) and delete the associated buffer.
Flaw: When a buffer is open in several windows, those other windows still get closed.
Trial two
" Delete the current buffer, issuing bnext in all windows " where displayed before that function DeleteBuffer2() let bid = bufnr("%") let wid = winnr() windo if bid == bufnr("%") | bprev | endif exe "bdel " . bid exe "normal " . wid . "^W^W" endfunction " count the number of buffers function BufferCount() " save cur buf number let cbuf = bufnr("%") let bnum = 0 bufdo let bnum = bnum + 1 " return to the buf exe "b " . cbuf return bnum endfunction function DeleteBuffer() if BufferCount() > 1 call DeleteBuffer2() else exe "bdel" endif endfunction map <C-K> :call DeleteBuffer()<CR> imap <C-K> <C-O><C-K>
Flaw: Deletes the buffer from all windows.
Trial three
Here's a command that doesn't implement a buffer kill ring such as the script above implements; but it does preserve window layout. Use
:Kwbd to clear the current window and only do a buffer delete if its the only instance of that buffer being displayed :Kwbd! clears all windows currently displaying the current buffer, and do a buffer delete
Both of these forms of the command preserve window layout.
" Kwbd: keep window layout and do a buffer delete {{{2 " :Kwbd -- clear current window, do buffer delete if its the only one " :Kwbd! -- clear all windows with current buffer and do buffer delete com! -bang -nargs=? Kwbd set lz|call <SID>Kwbd(<bang>0)|set nolz fun! s:Kwbd(really) let kwbd = winbufnr(0) let winnum = winnr() enew if a:really windo if winbufnr(0) == kwbd | enew | endif exe "bd ".kwbd else let s:cnt= 0 windo if winbufnr(0) == kwbd | let s:cnt=s:cnt+1 | endif if s:cnt == 0 exe "bd ".kwbd endif endif exe winnum."wincmd W" endfun
Flaw: It always give an empty buffer in the current window.
Trial four
That's a very simple function I wrote to enable someone to close the current buffer (like :bd) yet not close any associated windows with that buffer. I haven't seen anything easier and/or simpler than this. To use this function, just do :call Kwbd(1)
"delete the buffer; keep windows function Kwbd(kwbdStage) if(a:kwbdStage == 1) let g:kwbdBufNum = bufnr("%") let g:kwbdWinNum = winnr() windo call Kwbd(2) execute "bd! " . g:kwbdBufNum execute "normal " . g:kwbdWinNum . "" else if(bufnr("%") == g:kwbdBufNum) let prevbufvar = bufnr("#") if(prevbufvar > 0 && buflisted(prevbufvar) && prevbufvar != g:kwbdBufNum) b # else bn endif endif endif endfunction
Flaw: Works almost fine but if only one buffer is opened in two panes then it will close both panes. Anyway, awkward, two function in one.
See also
- script#1147
- script#559 Actually that script is not useful because it doesn't work as expected. Try closing a buffer that's open in several windows and see what happens... the windows close.
Comments
Here is a modification to the above script which binds it to the \bd key sequence. You can save it as kwbd.vim and drop it in you ~/.vim/plugin/ folder:
if exists('loaded_kwbd') finish endif let loaded_kwbd = 1 if !hasmapto('<Plug>Kwbd') map <unique> <Leader>bd <Plug>Kwbd endif noremap <unique> <script> <Plug>Kwbd :call <SID>Kwbd(1)<CR>:<BS> "delete the buffer; keep windows function <SID>Kwbd(kwbdStage) if(a:kwbdStage == 1) let g:kwbdBufNum = bufnr("%") let g:kwbdWinNum = winnr() windo call <SID>Kwbd(2) execute "bd! " . g:kwbdBufNum execute "normal " . g:kwbdWinNum . "" else if(bufnr("%") == g:kwbdBufNum) let prevbufvar = bufnr("#") if(prevbufvar > 0 && buflisted(prevbufvar) && prevbufvar != g:kwbdBufNum) b # else bn endif endif endif endfunction