开发者

Vim close buffer but not split window

开发者 https://www.devze.com 2023-01-27 03:03 出处:网络
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 closi

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>
0

精彩评论

暂无评论...
验证码 换一张
取 消