Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vim - make semicolon cycle

Tags:

vim

The default behavior of ; is to repeat the last f/F/t/T search in the same direction, and , moves in the opposite direction. When they reach the last search in the line in their respective direction, continuing to press them results in a No-op. How can I make them wrap back around so they search in a forward and backward cycle? E.g.

fb a[b]c foo bar baz

; abc foo [b]ar baz

; abc foo bar [b]az

; a[b]c foo bar baz

Alternatively, I would also be happy with a version that started moving in the other direction once it hit the end, e.g.

fb a[b]c foo bar baz

; abc foo [b]ar baz

; abc foo bar [b]az

; abc foo [b]ar baz

like image 606
Kvass Avatar asked May 24 '26 15:05

Kvass


1 Answers

At first, I thought this would be fairly easy. Turns out it's not. You have to basically re-implement every single combo of fFtT and ;,, with numerous edge cases. This ends up being 32 lines of vimscript. Here it is:

function! RepeatFind(reverse)
  let l:dict = getcharsearch()

  if a:reverse == l:dict['forward']
    let l:text = getline('.')[:col('.') - 2]
    if l:dict['until']
      let l:text = l:text[:-2]
    endif
  else
    let l:text = getline('.')[col('.'):]
    if l:dict['until']
      let l:text = l:text[1:]
    endif
  endif

  if index(split(l:text, '.\zs'), l:dict['char']) != -1
    exe 'normal! '.(a:reverse ? ',' : ';')
  else
    if !a:reverse && l:dict['forward']
      normal 0;
    elseif !a:reverse && !l:dict['forward']
      normal! $;
    elseif a:reverse && l:dict['forward']
      normal! $,
    elseif a:reverse && !l:dict['forward']
      normal! 0,
    endif
  endif
endfunction

nnoremap ; :<C-u>call RepeatFind(0)<cr>
nnoremap , :<C-u>call RepeatFind(1)<cr>

One difficulty comes from the uppercase variants and , being double-negatable, working forward. That's what accounts for lines 16-28, hardcoding all of the possible combinations.

Alternatively, I would also be happy with a version that started moving in the other direction once it hit the end

This would probably not be very hard to implement, given that the info about last search, current direction etc. is already being stored. But it brings up some interesting corner cases. For example, what should happen if you use ; until it switches to backwards, and then press ,. Should that attempt going forwards and then switch backwards?

like image 54
DJMcMayhem Avatar answered May 26 '26 20:05

DJMcMayhem