Wikia

Vim Tips Wiki

Changes: Cycle through buffers including hidden buffers

Edit

Back to page

(Comments: tweaked version of merged code, with same problems)
(Change <tt> to <code>, perhaps also minor tweak.)
 
Line 16: Line 16:
   
 
==Cycling through listed buffers==
 
==Cycling through listed buffers==
The commands <tt>:bnext</tt> and <tt>:bprevious</tt> will switch to the next or previous buffer in the buffer list. So a couple of useful maps for cycling through your buffers are:
+
The commands <code>:bnext</code> and <code>:bprevious</code> will switch to the next or previous buffer in the buffer list. So a couple of useful maps for cycling through your buffers are:
 
<pre>
 
<pre>
 
:nnoremap <C-n> :bnext<CR>
 
:nnoremap <C-n> :bnext<CR>
Line 37: Line 37:
   
 
==Including unlisted buffers in the cycle==
 
==Including unlisted buffers in the cycle==
The <tt>:bnext</tt> and <tt>:bprevious</tt> commands skip unlisted buffers, which can prove frustrating when buffers have been opened to view directory listings, or when you want to view a buffer previously deleted with <tt>:bdelete</tt>. Consider the following example.
+
The <code>:bnext</code> and <code>:bprevious</code> commands skip unlisted buffers, which can prove frustrating when buffers have been opened to view directory listings, or when you want to view a buffer previously deleted with <code>:bdelete</code>. Consider the following example.
 
<pre>
 
<pre>
 
gvim ~ /etc/motd
 
gvim ~ /etc/motd
Line 59: Line 59:
 
This maps <C-n> to switch to the buffer which has a buffer number one higher than the buffer number of the current buffer. While <C-p> cycles in the opposite direction.
 
This maps <C-n> to switch to the buffer which has a buffer number one higher than the buffer number of the current buffer. While <C-p> cycles in the opposite direction.
   
However, this does not always work, because there might be holes in the buffer numbers. For example, the buffer list may contain buffer numbers 1, 2, 6, 9, 10 and 14. Using the above map for <C-n> from buffer #6, would produce the error message "E86: Buffer 7 does not exist". Also, unlike <tt>:bnext</tt> and <tt>:bprevious</tt>, the above maps will cycle from non-help buffers to help buffers and vice-versa.
+
However, this does not always work, because there might be holes in the buffer numbers. For example, the buffer list may contain buffer numbers 1, 2, 6, 9, 10 and 14. Using the above map for <C-n> from buffer #6, would produce the error message "E86: Buffer 7 does not exist". Also, unlike <code>:bnext</code> and <code>:bprevious</code>, the above maps will cycle from non-help buffers to help buffers and vice-versa.
   
A solution is to write a function searching for the next buffer with <tt>bufexists()</tt>, and checking its filetype with <tt>getbufvar()</tt>.
+
A solution is to write a function searching for the next buffer with <code>bufexists()</code>, and checking its filetype with <code>getbufvar()</code>.
 
<pre>
 
<pre>
 
function! SwitchToNextBuffer(incr)
 
function! SwitchToNextBuffer(incr)
Line 90: Line 90:
   
 
==Leaving modified buffers==
 
==Leaving modified buffers==
If Vim is running with its default settings, or in vi compatible mode, the commands <tt>:bnext</tt>, <tt>:bprevious</tt> and <tt>:buffer</tt> won't abandon the buffer until any changes have been written. There are a few ways this can be changed.
+
If Vim is running with its default settings, or in vi compatible mode, the commands <code>:bnext</code>, <code>:bprevious</code> and <code>:buffer</code> won't abandon the buffer until any changes have been written. There are a few ways this can be changed.
*The commands can be called with a trailing !, for example, <tt>:bnext!</tt>, which will discard any changes made to the buffer.
+
*The commands can be called with a trailing !, for example, <code>:bnext!</code>, which will discard any changes made to the buffer.
*Setting the ''hidden'' option (<tt>:set hidden</tt>) will keep the changes to the buffer without writing them to the file. This affects all commands and all buffers.
+
*Setting the ''hidden'' option (<code>:set hidden</code>) will keep the changes to the buffer without writing them to the file. This affects all commands and all buffers.
*Setting either the ''autowrite'' or the ''autowriteall'' options (<tt>:set autowrite</tt> or <tt>:set autowriteall</tt>) will automatically save the changes made to the buffer.
+
*Setting either the ''autowrite'' or the ''autowriteall'' options (<code>:set autowrite</code> or <code>:set autowriteall</code>) will automatically save the changes made to the buffer.
   
 
==References==
 
==References==
Line 124: Line 124:
 
</pre>
 
</pre>
   
Press the mapped keys to switch to the next buffer ''and'' display a list of all buffers to indicate where you are. Problems: The list of buffers is often not visible (it is overwritten by the <tt>:bnext</tt> message); if have many buffers, the display is not helpful; after closing several buffers, the display includes unhelpful blank entries. [[User:JohnBeckett|JohnBeckett]] 07:03, April 27, 2010 (UTC)
+
Press the mapped keys to switch to the next buffer ''and'' display a list of all buffers to indicate where you are. Problems: The list of buffers is often not visible (it is overwritten by the <code>:bnext</code> message); if have many buffers, the display is not helpful; after closing several buffers, the display includes unhelpful blank entries. [[User:JohnBeckett|JohnBeckett]] 07:03, April 27, 2010 (UTC)

Latest revision as of 05:53, July 13, 2012

Tip 873 Printable Monobook Previous Next

created 2005 · complexity basic · version 6.0


This tip shows how to cycle through all of your buffers (including unlisted buffers such as directory listings).

For suggestions on how to switch to any other buffer see Easier buffer switching.

Cycling through listed buffersEdit

The commands :bnext and :bprevious will switch to the next or previous buffer in the buffer list. So a couple of useful maps for cycling through your buffers are:

:nnoremap <C-n> :bnext<CR>
:nnoremap <C-p> :bprevious<CR>

On gvim, you may want to try using Tab and Shift-Tab instead:

:nnoremap <Tab> :bnext<CR>
:nnoremap <S-Tab> :bprevious<CR>

A list of your buffers can be shown after switching by using the following maps:

:nnoremap <A-n> :bnext<CR>:redraw<CR>:ls<CR>
:nnoremap <A-p> :bprevious<CR>:redraw<CR>:ls<CR>

The buffer you are currently editing will be shown with a '#'. From there you should be able to get an idea of how far you have to go to the desired buffer and then use the first set of maps to quickly navigate to it.

Including unlisted buffers in the cycleEdit

The :bnext and :bprevious commands skip unlisted buffers, which can prove frustrating when buffers have been opened to view directory listings, or when you want to view a buffer previously deleted with :bdelete. Consider the following example.

gvim ~ /etc/motd
    gvim goes to directory ~
  :bn
    gvim goes to /etc/motd
  :bp
    but will not go back to ~, because it is unlisted
  :ls!
    ~ is shown in the list of buffers 1,2
  :buf 1
    have to give it the buffer number to find it

The problem gets worse with several levels of directory navigation. The simplest solution for this are the following two mappings:

:nnoremap <C-n> :execute ":buffer ".(bufnr("%") + 1)<CR>
:nnoremap <C-p> :execute ":buffer ".(bufnr("%") - 1)<CR>

This maps <C-n> to switch to the buffer which has a buffer number one higher than the buffer number of the current buffer. While <C-p> cycles in the opposite direction.

However, this does not always work, because there might be holes in the buffer numbers. For example, the buffer list may contain buffer numbers 1, 2, 6, 9, 10 and 14. Using the above map for <C-n> from buffer #6, would produce the error message "E86: Buffer 7 does not exist". Also, unlike :bnext and :bprevious, the above maps will cycle from non-help buffers to help buffers and vice-versa.

A solution is to write a function searching for the next buffer with bufexists(), and checking its filetype with getbufvar().

function! SwitchToNextBuffer(incr)
  let help_buffer = (&filetype == 'help')
  let current = bufnr("%")
  let last = bufnr("$")
  let new = current + a:incr
  while 1
    if new != 0 && bufexists(new) && ((getbufvar(new, "&filetype") == 'help') == help_buffer)
      execute ":buffer ".new
      break
    else
      let new = new + a:incr
      if new < 1
        let new = last
      elseif new > last
        let new = 1
      endif
      if new == current
        break
      endif
    endif
  endwhile
endfunction
nnoremap <silent> <C-n> :call SwitchToNextBuffer(1)<CR>
nnoremap <silent> <C-p> :call SwitchToNextBuffer(-1)<CR>

Leaving modified buffersEdit

If Vim is running with its default settings, or in vi compatible mode, the commands :bnext, :bprevious and :buffer won't abandon the buffer until any changes have been written. There are a few ways this can be changed.

  • The commands can be called with a trailing !, for example, :bnext!, which will discard any changes made to the buffer.
  • Setting the hidden option (:set hidden) will keep the changes to the buffer without writing them to the file. This affects all commands and all buffers.
  • Setting either the autowrite or the autowriteall options (:set autowrite or :set autowriteall) will automatically save the changes made to the buffer.

ReferencesEdit

CommentsEdit

The following is a tweaked version of code from a proposed new tip (the author's original code is in the previous version of this page):

function! GoBuf()
  bnext
  echon '    '
  for buf in range(1, bufnr('$'))
    echon '['
    if bufloaded(buf)
      echohl WarningMsg | echon bufname(buf) | echohl None
    else
      echon bufname(buf)
    endif
    echon ']  '
  endfor
endfunction
map <F8> :call GoBuf()<CR>

Press the mapped keys to switch to the next buffer and display a list of all buffers to indicate where you are. Problems: The list of buffers is often not visible (it is overwritten by the :bnext message); if have many buffers, the display is not helpful; after closing several buffers, the display includes unhelpful blank entries. JohnBeckett 07:03, April 27, 2010 (UTC)

Around Wikia's network

Random Wiki