Buffer only in vim

Posted by chunyang on March 22, 2022
TAGS: #vim

I am using coc-pywright to jump to the definition for programming in python. I have set it up to open a vertically split window. Sometimes I just want to keep current buffer in order to fully spread it on the screen.

What I want?

A command or a shortcut to close all the buffers except current buffer. For example:

:BufferOnly

" o is short for only.
<leader>+o

Reference from google

Basically there are two ways:

  • Close all buffers and use edit # to reopen current buffer
  • Use a plugin which defines command and search for the specific buffer

The first solution will cause the screen to flush and if not configured correctly we will lose the editing position we previously working on.

nnoremap <leader>o :%bd\|e#<CR>
nnoremap <leader>o :execute '%bdelete\|edit #\|normal `"'\|bdelete#<CR>

The first command will close all buffers and reopen current buffer, but it will lose the editing position. The second command will close all the buffers, reopen current buffer and return to previous editing position. But it wlll cause the screen to flush and lose the cursor position (Not visible until we move the position)

Make my hand dirty

Try my best to learn the basic language of vimscript from following websites:

I come out with my own solution

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

nnoremap <leader>o :call CloseOtherBuffer()<CR>

I have defined leader to , previously using let mapleader=",".

The idea is simple:

  • Find my buffer number
  • Iterate all listed buffers and close those whose buffer number are not equal to my buffer number.

After carefully reading the code of close-buffers.vim and BufOnly.vim, I found out that the idea and implementations are similar.

:help getbufinfo
:help bufnr

Trips

  • bdelete buffer.bufnr not working. Vimscript does not replace variable with its value
" Works
let l:cmd = "bdelete " . buffer.bufnr
execute l:cmd

" Not working, buffer.bufnr not replaced with the actual number
bdelete buffer.bufnr
  • Should filter with buffer property listed, otherwise there will be other buffers which are not edited appearng.