我喜欢nnoremap
到n
的{{1}},但是当下一场比赛正好在我现在的那场比赛或者下面的两行时,我会迷失方向按nzz
。
我想要一个命令来执行n
所做的事情,但仅当光标当前不在中间10行时。
你能救我吗?
答案 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>"
以上三行是以下解决方法的结果:
<Plug>
和第二行是a)用于避免重新映射(实际上是为了避免记住部分可重映射映射未重新映射的情况)b)遵循规则“当使用可重映射映射{rhs中的每个符号时必须以已知的方式重新映射“。<Plug>
和第三行是因为{/ 1}}映射必须在切换到新位置后启动。我无法将<expr>
放在n
映射中,因为在切换到新位置之前,将评估具有<expr>
条件的第二部分。还有另一种选择:
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>