Skip to main content
  1. Posts/

Switching Buffers in Neovim with mapping

··353 words·2 mins·
Nvim
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
Nvim Plugin
Pylsp setup for Neovim in 2023
··1020 words·5 mins
Nvim LSP
Work with JSON File in Neovim
·299 words·2 mins
Nvim