For single-digit buffers, you can actually hardcode 9 mappings, one for each digit:
nnoremap <Leader>b1 :buffer 1<CR>
nnoremap <Leader>b2 :buffer 2<CR>
nnoremap <Leader>b3 :buffer 3<CR>
nnoremap <Leader>b4 :buffer 4<CR>
nnoremap <Leader>b5 :buffer 5<CR>
nnoremap <Leader>b6 :buffer 6<CR>
nnoremap <Leader>b7 :buffer 7<CR>
nnoremap <Leader>b8 :buffer 8<CR>
nnoremap <Leader>b9 :buffer 9<CR>
If you don't like the repetition, you could use a
:for loop to produce these lines:
for i in range(1, 9)
execute 'nnoremap <Leader>b'.i.
\ ' :buffer '.i.'<CR>'
For the double-digit case, it can be tricky to do with a mapping. You can potentially use
getchar() to keep getting more characters and check whether they're valid digits. But you need a way to terminate the sequence, possibly by checking when you get a
getchar(), but that means the user will have to press an extra key to finish the sequence. (Though you could handle keys other than
<CR> or digits by terminating the sequence and feeding them back with
Since an extra key is likely needed, you might consider using
input() instead, in which case you can even allow completion on buffer names!
" Start by listing existing buffers
let n = input('Switch to: ', '', 'buffer')
execute 'buffer' n
nnoremap <Leader>bs :call SwitchBuffer()<CR>
You could use such a mapping in addition to the single-digit mappings, for cases where you want to use buffer names or two-digit buffer numbers. Also, listing them first as part of the command might be useful as well.