Vim - 进行分号循环

时间:2017-02-26 00:23:43

标签: vim

;的默认行为是在同一方向上重复上一次f / F / t / T搜索,并{{1向相反方向移动。当他们按照各自的方向到达行中的最后一次搜索时,继续按下它们会导致No-op。如何让它们回绕,以便它们在前后循环中进行搜索? E.g。

, a [b] c foo bar baz

fb abc foo [b] ar baz

; abc foo bar [b] az

; a [b] c foo bar baz

或者,我也很高兴看到一个版本在其结束时开始向另一个方向移动,例如。

; a [b] c foo bar baz

fb abc foo [b] ar baz

; abc foo bar [b] az

; abc foo [b] ar baz

1 个答案:

答案 0 :(得分:2)

起初,我认为这很容易。事实证明并非如此。您必须基本上重新实现fFtT;,的每个组合,包含许多边缘情况。这最终是32行的vimscript。这是:

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>

一个难点来自大写变体,,是双重可否定的,向前发展。这就是16-28行的原因,硬编码了所有可能的组合。

  

或者,我也很高兴看到一个版本在结束时开始向另一个方向移动

考虑到有关上次搜索,当前方向等的信息已经存储,这可能不会很难实现。但它带来了一些有趣的角落案例。例如,如果您使用;直到它向后切换,然后按,会发生什么。该尝试是否应该向前转,然后向后切换?