Like Ben and statox, I wouldn't necessarily recommend this, but it is possible:
function FirstPress(c1) abort
let now = reltime()
while reltimefloat(reltime(now)) < &timeoutlen / 1000.0
" See if the user has typed another character
let c2 = getchar(0)
if c2 != 0
" The user typed something. Was it another h?
if c2 == char2nr(a:c1)
" The user typed a double h, switch buffers
if a:c1 == 'h'
bprevious
else
bnext
endif
else
" The user typed something else. Switch tabs and replay what they typed
call feedkeys((a:c1 == 'h' ? 'gT' : 'gt') . nr2char(c2), 't')
endif
return
endif
endwhile
" The user didn't press anything. Switch Tabs
if a:c1 == 'h'
tabprevious
else
tabnext
endif
endfunction
nnoremap <expr> h (getpos('.')[1] == 1 && getpos('.')[2] == 1) ? ':call FirstPress("h")<CR>' : 'h'
nnoremap <expr> l (getpos('.')[1] == line('$') && (getpos('.')[2] == col('$') - 1 \|\| col('$') == 1)) ? ':call FirstPress("l")<CR>' : 'l'
It works by mapping the single h
and l
keypresses only, and then in that mapping, checking if the user presses the given key a second time, and acting accordingly.
See also my answer to this recent similar, but slightly different question where the OP wanted to do the first mapping immediately and then perform the second as well if performed within timeoutlen
.
gt
andgT
. If you're looking to cycle buffers, tpope's unimpaired uses]b
and[b
for:bnext
and:bprev
, respectively, which I find quite nice.:ls
followed by:buffer
is also quite nice