如果光标不在范围内,则重绘

时间:2012-10-15 15:12:56

标签: vim

我喜欢nnoremapn的{​​{1}},但是当下一场比赛正好在我现在的那场比赛或者下面的两行时,我会迷失方向按nzz。 我想要一个命令来执行n所做的事情,但仅当光标当前不在中间10行时。 你能救我吗?

4 个答案:

答案 0 :(得分:3)

nmap            n                          <Plug>VimrcSearch<Plug>VimrcZZifnotinmiddle
nnoremap        <Plug>VimrcSearch          n
nnoremap <expr> <Plug>VimrcZZifnotinmiddle (abs(winline()-winheight(0)/2)>5 ? 'zz' : '')."\<C-l>"

以上三行是以下解决方法的结果:

  1. 第一行<Plug>和第二行是a)用于避免重新映射(实际上是为了避免记住部分可重映射映射未重新映射的情况)b)遵循规则“当使用可重映射映射{rhs中的每个符号时必须以已知的方式重新映射“。
  2. 第二行<Plug>和第三行是因为{/ 1}}映射必须在切换到新位置后启动。我无法将<expr>放在n映射中,因为在切换到新位置之前,将评估具有<expr>条件的第二部分。
  3. 还有另一种选择:

    zz

    ,但 nnoremap <silent> n n:if abs(winline()-winheight(0)/2)>5<bar>execute 'normal! zz'<bar>endif<CR> 映射是我想到的第一件事,因此我会保留它。

答案 1 :(得分:2)

对于一个简单的解决方案,您可能希望将'scrolloff'设置为大型。这实际上并没有完全解决你的问题,但它很简单,所以你可能想先尝试一下。

如果不满意,那么我们可以尝试更重的方法并在~/.vimrc中添加一个函数。

nnoremap <silent> n :call Recenter('n', 10)<cr>
nnoremap <silent> N :call Recenter('N', 10)<cr>

function! Recenter(cmd, tolerance)
  let ws = line('w0')
  let distance = line('w$') - ws
  exe 'norm! ' . a:cmd
  let tolerance = a:tolerance / 2
  let current_offset = line('.') - line('w0')
  if line('w0') != ws || (current_offset < (distance/2-tolerance) || current_offset > (distance/2+tolerance))
    norm! zz
  endif
endfunction

有关详细信息,请参阅:

:h 'scrolloff'
:h line()
:h zz

答案 2 :(得分:1)

答案 3 :(得分:-1)

function! CenterWhenNotAtTheMiddle()
    let currentLine = winline() 
    let offsetFromMiddleLine = 5
    let lineBeforeTenMiddleLines = winheight(0) / 2 - offsetFromMiddleLine
    let lineAfterTenMiddleLines = winheight(0) / 2 + offsetFromMiddleLine
    if currentLine < lineBeforeTenMiddleLines 
        normal zz
    else
        if currentLine > linesAfterTenMiddleLines
            normal zz
        endif
    endif
endfunction

nnoremap n n:call CenterWhenNotAtTheMiddle()<Cr>
nnoremap N N:call CenterWhenNotAtTheMiddle()<Cr>