Skip to main content
  1. Posts/

Switching Buffers in Neovim with mapping

··353 words·2 mins·
Table of Contents

I usually use {num}Ctrl-6 to switch buffers in Neovim, where {num} is the number of buffer (see this post). Since Neovim has built-in gt mapping to switch between tabpages, I thought it might be a good idea to use gb as buffer switching shortcut avoid strech when pressing Ctrl-6.

Here is what I have got:

Click to show the code.
nnoremap <silent> gb :<C-U>call <SID>GoToBuffer(v:count, 'forward')<CR>
nnoremap <silent> gB :<C-U>call <SID>GoToBuffer(v:count, 'backward')<CR>

function! s:GoToBuffer(count, direction) abort
  if a:count == 0
    if a:direction ==# 'forward'
      bnext
    elseif a:direction ==# 'backward'
      bprevious
    else
      echoerr 'Bad argument ' a:direction
    endif
    return
  endif
  " Check the validity of buffer number.
  if index(s:GetBufNums(), a:count) == -1
    echohl WarningMsg | echomsg 'Invalid bufnr: ' a:count | echohl None
    return
  endif

  if a:direction ==# 'forward'
    silent execute('buffer' . a:count)
  endif
endfunction

function! s:GetBufNums() abort
  let l:buf_infos = getbufinfo({'buflisted':1})
  let l:buf_nums = map(l:buf_infos, "v:val['bufnr']")
  return l:buf_nums
endfunction

You can use gb and gB without count to switch forward and backward in the buffer list. When provided with a count, gb can also switch the buffer with that number. For example, if we have buffer with number 6, press 6gb in normal mode will switch to that buffer.

Issues I have met
#

Using count in mappings
#

If we use a count before the mapping, and then execute some command, vim will insert a range for this command automatically1. To prevent this, we use Ctrl-U to delete the range inserted by Vim.

Refs:

s:MyFunc or <SID>MyFunc
#

Another issue is that we need to use call <SID>GoToBuffer instead of call s:GoToBuffer. The s: notation only works if we are in the same script that defines this function. When we execute the mapping, we are usually in other files. If we use s: notation, we get the following error:

> E81: Using <SID> not in a script context

See also Neovim help file on this topic (h <SID>).

Ref:


  1. To verify, press a number, and then press : to enter command line mode. ↩︎

Related

Migrating from Packer.nvim to Lazy.nvim
··651 words·4 mins
Pylsp setup for Neovim in 2023
··1020 words·5 mins
Work with JSON File in Neovim
·299 words·2 mins