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 ?

3N4N
  • 5,684
  • 18
  • 45
xyx
  • 464
  • 3
  • 11
  • 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 01 '18 at 13:19
  • Yes, this is something I thought for a vimscript. – xyx Jun 01 '18 at 13:20
  • Dare I say this is a duplicate of http://vi.stackexchange.com/questions/5643/can-i-cycle-through-buffers-while-skipping-ones-ive-opened ? You'll find there an efficient solution that I've implemented and shared at https://github.com/LucHermitte/lh-misc/blob/master/plugin/next-undisplayed-buffer.vim – Luc Hermitte Jun 01 '18 at 15:28

1 Answers1

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()
3N4N
  • 5,684
  • 18
  • 45
  • 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. – Luc Hermitte Jun 01 '18 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 01 '18 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 – Luc Hermitte Jun 01 '18 at 17:42
  • @LucHermitte After reading :h bufwinnr() I think I need only to replace !bufloaded() with !bufwinnr(). Is that correct? – 3N4N Jun 01 '18 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') – Luc Hermitte Jun 01 '18 at 17:47
  • @LucHermitte I edited the answer, it works on my machine. Can you take a look again? – 3N4N Jun 01 '18 at 18:09
  • It looks more like it. I'd need to take to take a closer look at the loops (as you've seen my solution is loop-less -> more efficient & easier to debug). I guess that if you observe a correct behaviour then it should be correct :) – Luc Hermitte Jun 02 '18 at 14:32
  • I saw your solution. I didn't change mine to align with yours cause you already added a link to yours here. I've very little idea about vimscript. That's why mine is quick and dirty solution. – 3N4N Jun 02 '18 at 15:29