This command should output the number of the last buffer in the buffer list (see :h bufnr()
):
:echo bufnr('$')
This command should output the range of buffer numbers, from the first one to the last one (see :h range()
):
:echo range(1, bufnr('$'))
This command should output the 'readonly'
option of the buffer 123
(see :h getbufvar()
):
:echo getbufvar(123, '&l:ro')
This command should remove from the list of buffer numbers [1,2,3,4,5]
, the ones whose 'readonly'
option is unset (see :h filter()
):
:echo filter([1,2,3,4,5], {i,v -> getbufvar(v, '&l:ro') == 1})
This command should output the whole range of buffer numbers, whose 'readonly'
option is set:
:echo filter(range(1, bufnr('$')), {i,v -> getbufvar(v, '&l:ro') == 1})
You could join the numbers of the last command, and pass them to :bd
(see :h :exe
and :h join()
):
:exe 'bd '.join(filter(range(1, bufnr('$')), {i,v -> getbufvar(v, '&l:ro') == 1}))
And to make this simpler to execute, you could install a custom :BdReadOnly
command (see :h :com
):
com! -bar BdReadOnly exe 'bd '.join(filter(range(1, bufnr('$')), {i,v -> getbufvar(v, '&l:ro') == 1}))
There may be “holes” in the range. That is, some index may have been used in the past for a buffer, but the latter may have been deleted since then. In this case, the index is not re-used for another buffer.
For such non-existing buffer, getbufvar()
should then return an empty string:
:echo getbufvar(999999999, '&l:ro') is# ''
→ 1
So, the previous test in the lambda expression should fail:
getbufvar(v, '&l:ro') == 1
And, I think, the index should be correctly filtered.
Also, if the buffers which are deleted are not exactly the ones you want, you may need to tweak the condition getbufvar(v, '&l:ro') == 1
in the lambda expression, and build a more complex one.
In this case, you could be interested in some other functions (see :h buffer-functions
).
To name a few:
bufexists(123)
will tell you whether the buffer 123
exists
buflisted(123)
will tell you whether the buffer 123
is currently listed
bufname(123)
will give you the name of the buffer 123
, and empty(bufname(123))
will test whether it has one in the first place
win_findbuf(123)
will tell you in which window(s) the buffer 123
is being displayed, and empty(win_findbuf(123))
will tell you whether it is displayed anywhere in the first place