1

我喜欢使用nnoremapfor nto nzz,但是当下一场比赛正好在我现在所在的比赛之下,或者两行之下时,当我按下 时,我会迷失方向n。我想要一个命令来做什么zz,但前提是光标当前不在中间 10 行中。你能帮助我吗?

4

4 回答 4

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>和第三行在那里,因为<expr>必须在切换到新位置后启动映射。我无法放入n映射<expr>,因为zz在切换到新位置之前将评估带有条件的第二部分。

有一个替代方案:

    nnoremap <silent> n n:if abs(winline()-winheight(0)/2)>5<bar>execute 'normal! zz'<bar>endif<CR>

,但<expr>映射是我想到的第一件事,因此我会保留它。

于 2012-10-15T17:19:38.440 回答
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
于 2012-10-15T17:20:56.613 回答
1

http://vim.wikia.com/wiki/Make_search_results_appear_in_the_middle_of_the_screen

于 2012-10-15T17:50:22.307 回答
-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>
于 2012-10-15T17:49:07.827 回答