38

One way to select a buffer in vim could be to browse the buffers list, using standard commands as :ls, or with some external plugin / vimscript code to browse a list in a window.

Let's say I want to jump to a buffer directly, as fast as possible.

To traverse the buffer list in sequential mode, I now use <C-J> <C-K> shortcuts, having set in my .vimrc:

" move among buffers with CTRL
map <C-J> :bnext<CR>
map <C-K> :bprev<CR>

Another way (direct access) could be switching by number: knowing the buffer number, it is possible to switch directly by entering the buffer number followed by <C-^>. So if I want to switch to buffer number 5, I would press 5<C-^>.

But this seem not working for me (I use vim 7.4 on ubuntu box, from a Windows guest, with Italian keyboard). I suspect that's because the ^ character is in the upper case key in the Italian keyboard, so in fact to got ^ I need to press SHIFT-^

Any ideas?

  • 2
    Can you press <c-6> instead of <c-^>? – Peter Rincker Feb 23 '15 at 15:34
  • do you mean Ctrl-1 to go to buffer number 1 ? Unfortunately doesn't work. nothing happen – Giorgio Robino Feb 23 '15 at 18:52
  • 1
    No. Some terminals can understand Ctrl-6 which is the same as Ctrl-^ on the US keyboard. – Peter Rincker Feb 23 '15 at 19:54
  • 2
    +1 Great, It work! I use an Italian keyboard layout (using putty terminal emulator). So: 1<C-6> switchs to buffer number 1. Thanks! – Giorgio Robino Feb 24 '15 at 7:12
  • You can try to use CtrlSpace. – Hongbo Liu Oct 17 '16 at 13:57
45

The :b command can also take a substring of the name of the file of the buffer which you want to travel to, which is very convenient.

For example, if you have three buffers foo, bar, and baz, then

  • :b bar will switch to the bar file.

  • :b o will switch to the foo file.

  • :b a will give you an error because it could mean either bar or baz, but you can fix the name to be more specific with, for example, : r Enter.

This can be very useful, because it means instead of

:buffer very/very/long/path/to/a/veryVeryLongFileName.txt

you can do something like

:b LongFileName

which is much shorter and easier.

This command can also take a number, if you want to use that:

:b 5
  • 7
    A caveat about using partial buffer names: if the partial buffer name appears at the beginning of a word boundary in some buffer's path, no buffer with the partial name in the middle of a word will be accessible by the :b command. For example, if you have two buffers path/to/foo and path/to/tofu, the command :b f<Tab> will never match path/to/tofu, since it matches at the beginning of a word in path/to/foo. – tommcdo Feb 23 '15 at 13:36
  • 2
    :5b is slightly shorter then :b 5 ;-) – joeytwiddle Feb 24 '15 at 22:00
14

This is what I use:

nnoremap <Leader>b :ls<CR>:b<Space>

Now pressing \b will list the available buffers and prepare :b for you.

Then you can just type the buffer number, and hit Enter.

Or you can type part of the filename, and hit Enter. (However I usually hit Tab before hitting Enter, to check I got the right buffer. If not, I continue cycling with Tab until I get the one I wanted.)


In fact, I use a slightly tweaked version of the above:

nnoremap <C-e> :set nomore <Bar> :ls <Bar> :set more <CR>:b<Space>

This will prevent the -- More -- prompt from appearing when you have more buffers than available lines to display them.

But if you usually have the 'more' option disabled anyway, this mapping will really annoy you, because it re-enables the 'more' option after doing ls!

  • 1
    Truth be told, I don't actually use either of those, I use my own little plugin, but the functionality is very similar. With the plugin, I can also perform Tab-complete on the filenames of un-opened buffers. – joeytwiddle Feb 24 '15 at 22:24
  • 1
    Although this technique isn't as fast as using [count]<C-^> when you know the buffer number, it is pretty useful when you don't know. – joeytwiddle Feb 24 '15 at 22:28
  • 2
    thanks joeytwiddle for your notes. I'll check your plugin asap. In my case (see keyboard issue above) [count]<C-6> appear to me the fastest way to switch to known buffer – Giorgio Robino Feb 25 '15 at 9:25
  • Yeah I am also using [count]<C-^> these days. But that means I need to run MiniBufExplorer or something similar, to know what the buffer numbers are! – joeytwiddle Sep 25 '17 at 4:16
  • why do you need the <CR> and the <SPACE>? At first it appears to me, as if it works fine without them... – Felix Crazzolara Aug 30 '18 at 19:59
8

:CtrlPBuffer from plugin ctrlp.vim (>3.5k ★)

Main feature of this plugin is to provide a fuzzy matching to conveniently open a different buffer with a better visual feedback than the builtin approach.

Open the fuzzy buffer listing with :CtrlPBuffer or press <C-p> followed by either two times <C-f> or a single <C-b> (with the default configuration).

Enter a sufficient number of characters to specify the buffer you want to open.
You can also use <C-j> and <C-k> to cycle through the list and select manually the buffer.

enter image description here

Customization

If you wish to open the buffer list immediately with <C-p>, add following line to your vimrc:

let g:ctrlp_cmd = 'CtrlPBuffer'

You can use again <C-f/b> to switch the mode of the ctrlp window.

I personally use let g:ctrlp_cmd = 'CtrlPMRU'. The most recently used (mru) list also contains the opened buffers. If you use different ctrlp modes and want to stick to your last mode, try let g:ctrlp_cmd = 'CtrlPLastMode [--dir]'.

Similar plugins

There are more plugins which provide a buffer list with an interactive prompt with fuzzy matching, e.g.

The dark side vs. the light side

(i.e. plugin-heavy vim setup vs. the vim way)

Before you decide to use these more complex plugins, study the answers by @Doorknob and @joeytwiddle. In particular, check the one-liner if one of them already fulfills your needs.

  1. nnoremap <Leader>b :b <C-d>
  2. nnoremap <Leader>b :ls<Cr>:b<Space>

Installing the plugins just for buffer switching might be an overkill. See also the remarks on https://www.vi-improved.org/recommendations and the article by Drew Neil ‘On sharpening the saw’.

  • yes Hotschke, I confess i often use :CtrlPBuffer – Giorgio Robino Jan 11 '17 at 10:36
  • I am using map <leader>a <ESC>:CtrlPBuffer<CR><CR> to jump to the previously opened buffer with <leader>a (while <leader>b just opens the buffer list for me) – Rolf Sep 13 '18 at 7:59
  • @Rolf: do you know <C-^> (= <C-6>)? see :h CTRL-^. Afaik, this just does what your mapping <leader>a seems to do. Therefore I think you just brought an example why people say using plugins might lead to vim user who do not know what vim already can do on its own. – Hotschke Sep 13 '18 at 8:25
  • @Hotschke: No, I didn't know that. Learned something knew, thanks! I'm gonna remap <C-^> though. – Rolf Sep 14 '18 at 6:44
7

In addition to really useful answers by joeytwiddle and Doorknob don't forget about :b#, which switches to most recently used buffer. It can also be done with just <C-^>. When you have a lot of buffers and you constantly switch between them, the most recent buffer is usually the most common destination.

Personally I use combination of many methods. When I'm working with mainly two buffers and the rest is opened just for occasional reference, I tend to switch between them with :b# or <C-^>. When I have to work with more of them and switch more often, I use either numbers (as in joeytwiddle tip), or part of names (as in Doorknob tip) with TAB to complete them. When the names are confusing, and there are many buffers opened (usually over 10), I use Ctrl-P plugin more often (https://github.com/kien/ctrlp.vim) With two fast keystrokes I got the list of them all and I'm able to use powerful fuzzy search over them to find quickly what I want.

  • 2
    <C-^> alone (<C-6> in my case, as Peter Rincker suggested) is a good trick in case of just 2 buffers :-) – Giorgio Robino Feb 26 '15 at 16:50
5

[b and ]b from plugin vim-unimpaired (> 2k ★)

If you happen to have installed vim-unimpaired, you can use

  • [b (:bp[revious]) and
  • ]b (:bn[ext])

for cycling through open buffers. No need to define more precious mappings for the same commands. Furthermore, jumping to the first and last buffer can be done by

  • [B (:bf[irst]) and
  • ]B (:bl[ast]).

There are plenty more bracket-mappings contained in vim-unimpaired which you might find useful. They all follow the same scheme which makes it easy to memorize them.

The dark side vs. the light side

This plugin can be considered lightweight and 'vimish'. It is denoted by the #vim community as a "does not harm" plugin.

  • +1 Also worth noting that you can provide a count. 3[b to jump three buffers back. – joeytwiddle Apr 29 at 3:28
1

Currently I'm using <Leader>+number key to switch. The leader key is my <space> key. I also use vim-airline to show the buffer nr on top of the window.

" airline settings
let g:airline#extensions#tabline#buffer_nr_show = 1
let g:airline#extensions#tabline#enabled = 1

While the bufnr often exceeds 10, so I tweak my own mapping, if the number is the only match, switch buffer immediately, otherwise wait for more number input or <space> key for confirm:

nnoremap <expr> <Leader>1 tweak#wtb_switch#key_leader_bufnum(1)
nnoremap <expr> <Leader>2 tweak#wtb_switch#key_leader_bufnum(2)
nnoremap <expr> <Leader>3 tweak#wtb_switch#key_leader_bufnum(3)
nnoremap <expr> <Leader>4 tweak#wtb_switch#key_leader_bufnum(4)
nnoremap <expr> <Leader>5 tweak#wtb_switch#key_leader_bufnum(5)
nnoremap <expr> <Leader>6 tweak#wtb_switch#key_leader_bufnum(6)
nnoremap <expr> <Leader>7 tweak#wtb_switch#key_leader_bufnum(7)
nnoremap <expr> <Leader>8 tweak#wtb_switch#key_leader_bufnum(8)
nnoremap <expr> <Leader>9 tweak#wtb_switch#key_leader_bufnum(9)




func! tweak#wtb_switch#key_leader_bufnum(num)
    let l:buffers = tweak#wtb_switch#buflisted()
    let l:input = a:num . ""

    while 1

        let l:cnt = 0
        let l:i=0
        " count matches
        while l:i<len(l:buffers)
            let l:bn = l:buffers[l:i] . ""
            if l:input==l:bn[0:len(l:input)-1]
                let l:cnt+=1
            endif
            let l:i+=1
        endwhile

        " no matches
        if l:cnt==0 && len(l:input)>0
            echo "no buffer [" . l:input . "]"
            return ''
        elseif l:cnt==1
            return ":b " . l:input . "\<CR>"
        endif

        echo ":b " . l:input

        let l:n = getchar()

        if l:n==char2nr("\<BS>") ||  l:n==char2nr("\<C-h>")
            " delete one word
            if len(l:input)>=2
                let l:input = l:input[0:len(l:input)-2]
            else
                let l:input = ""
            endif
        elseif l:n==char2nr("\<CR>") || (l:n<char2nr('0') || l:n>char2nr('9'))
            return ":b " . l:input . "\<CR>"
        else
            let l:input = l:input . nr2char(l:n)
        endif

        let g:n = l:n

    endwhile
endfunc

func! tweak#wtb_switch#buflisted()
  return filter(range(1, bufnr('$')), 'buflisted(v:val)')
endfunc

The code is pasted from here

By the way, I also use <S-h> and <S-l> for :bp and :bn, or :tabp and :tabn if more than one tabpage is opened currently. It's quite intuitive for me.

1

These days I am using [buffer_number]<Ctrl-^> to switch buffers because it is very fast.

But how to know the buffer number? I use MiniBufExplorer so I can always see the buffer numbers at the top of Vim.

I also use the following mapping, because <C-^> is a bit hard to reach with one hand.

:nmap <C-E> <C-^>

On a fresh machine with no config, I fall back to :b [part_of_filename]<Tab><Enter>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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