0

When we have a buffer open, and we open a new one with :split or :vsplit, if in any opened window we execute :bprev or :bnext, we could have the same buffer open at the same time in both windows.

Is there any option (if any I will try with a vimscript) to not have the same same buffer open in multiple windows (e.g. don't show it in the new window if it's already open in another one, all in the same tab) while cycling through buffer list ?

3
  • 1
    I will try and come up with something. But for you and anyone else who is trying, my primary idea is to use the flag a of vims :ls command. A function which checks if a buffer is already active and acts accordingly is all there is to it.
    – 3N4N
    Jun 1, 2018 at 13:19
  • Yes, this is something I thought for a vimscript.
    – xyx
    Jun 1, 2018 at 13:20
  • Dare I say this is a duplicate of vi.stackexchange.com/questions/5643/… ? You'll find there an efficient solution that I've implemented and shared at github.com/LucHermitte/lh-misc/blob/master/plugin/… Jun 1, 2018 at 15:28

1 Answer 1

2

You need these following functions:

function! BetterBufferNext() abort

  for b in range(bufnr('%')+1, bufnr('$'))
    if buflisted(b) && bufwinnr(b)==-1
      exe "normal! :b".b."\<cr>"
      return
    endif
  endfor

  for b in range(1, bufnr('%')-1)
    if buflisted(b) && bufwinnr(b)==-1
      exe "normal! :b".b."\<cr>"
      return
    endif
  endfor

endfunction

function! BetterBufferPrev() abort

  for b in range(bufnr('%')-1, 1, -1)
    if buflisted(b) && bufwinnr(b)==-1
      exe "normal! :b".b."\<cr>"
      return
    endif
  endfor

  for b in range(bufnr('$'), bufnr('%')+1, -1)
    if buflisted(b) && bufwinnr(b)==-1
      exe "normal! :b".b."\<cr>"
      return
    endif
  endfor

endfunction

nnoremap <silent> <F7> :call BetterBufferPrev()<cr>
nnoremap <silent> <F8> :call BetterBufferNext()<cr>

Don't use my horrible provided mappings, use your own. Maybe something like [b and ]b. Or maybe even,

command! Bp call BetterBufferPrev()
command! Bn call BetterBufferNext()
8
  • 2
    Are you sure this is really what the OP is looking for? bufloaded() is about buffers being in memory, not about them being displayed somewhere. Jun 1, 2018 at 17:27
  • @LucHermitte I seem to have misunderstood the use bufloaded(). Thank you for noticing. But I don't have any idea how to check if a buffer is active. Do you?
    – 3N4N
    Jun 1, 2018 at 17:40
  • 2
    Let's say I open file foo.txt, and that it's bufnr('%') is 22. If I close the file with :q, the file is still loaded (bufloaded(22) -> 1). You should have used bufwinnr() -- As I understand OP's expressed need, see the other Q/A that this one duplicates Jun 1, 2018 at 17:42
  • @LucHermitte After reading :h bufwinnr() I think I need only to replace !bufloaded() with !bufwinnr(). Is that correct?
    – 3N4N
    Jun 1, 2018 at 17:45
  • 2
    Almost. 0 is a valid value. The result should be compared to -1 -> let undisplayed_buffers = filter(range(1, bufnr('$')), 'buflisted(v:val) && bufwinnr(v:val) == -1') Jun 1, 2018 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.