当光标在屏幕中间并且我向下滚动时,光标在屏幕上向上移动。我不希望它那样做。
如何滚动而不更改光标在屏幕上的位置?
解决方案,在回答后添加:
noremap <C-k> 14j14<C-e>
noremap <C-l> 14k14<C-y>
当光标在屏幕中间并且我向下滚动时,光标在屏幕上向上移动。我不希望它那样做。
如何滚动而不更改光标在屏幕上的位置?
解决方案,在回答后添加:
noremap <C-k> 14j14<C-e>
noremap <C-l> 14k14<C-y>
我可以想到两种方法:ctrl-E和ctrl-Y在不移动光标相对于窗口的位置的情况下滚动缓冲区。我认为这就是你想要的。此外,如果您设置为较大的数字,您将获得与-和-使用移动键 scrolloff
相同的效果。设置将使光标很难相对于窗口垂直移动。(使用类似,是 的缩写。)ctrlEctrlYscrolloff
:set so=999
so
scrolloff
:help 'scrolloff'
:help scrolling
ctrl-D和ctrl-U是你想要的。
ctrl-D具有相同的效果14j14<C-e>
(只是数字 14 不是硬编码,移动量取决于屏幕的实际大小):您在文本中向下移动光标几行,但光标停留在中间屏幕。
同样ctrl-U像14k14<C-y>
.
附录:如果您的屏幕有 30 行,那么两者完全相同。
如果您想同时移动光标和带有光标的视口在屏幕上的任何位置,也许您应该设置一些自定义键绑定来同时执行这两项操作。
如:
:nnoremap <C-M-u> j<C-e>
这将在您按下时向下移动光标 ( j
) 并移动视口 ( ) (仅在正常模式下)。Ctrl-e
Ctrl-Alt-u
在 .vimrc 中试试这个映射
map <ScrollWheelUp> 5<C-Y>
map <ScrollWheelDown> 5<C-E>
我知道有两种方法。将这些行添加到您的 .vimrc 文件中(仅选择两种方法之一):
方法一:
function! s:GetNumScroll(num)
let num_rows = winheight(0)
let num_scroll = a:num
if (a:num == -1)
let num_scroll = (num_rows + 1) / 2
elseif (a:num == -2)
let num_scroll = num_rows
endif
if (num_scroll < 1)
let num_scroll = 1
endif
return num_scroll
endfunction
function! s:RtrnToOrig(before_scr_line)
normal H
let delta = a:before_scr_line - winline()
while (delta != 0)
if (delta < 0)
let delta = winline() - a:before_scr_line
let iter = 1
while (iter <= delta)
execute "normal" "gk"
let iter +=1
endwhile
elseif (delta > 0)
let iter = 1
while (iter <= delta)
execute "normal" "gj"
let iter +=1
endwhile
endif
let delta = a:before_scr_line - winline()
endwhile
endfunction
function! s:scrollUP(num)
let num_scroll = <SID>GetNumScroll(a:num)
let num_rows = winheight(0)
" -------------
let before_scr_line = winline()
normal L
let after_scr_line = winline()
let extra = num_rows - after_scr_line
let extra += num_scroll
" move by 1 to prevent over scrolling
let iter = 1
while (iter <= extra)
execute "normal" "gj"
let iter +=1
endwhile
" -------------
call <SID>RtrnToOrig(before_scr_line)
endfunction
function! s:scrollDN(num)
let num_scroll = <SID>GetNumScroll(a:num)
" -------------
let before_scr_line = winline()
normal H
let after_scr_line = line(".")
execute "normal" "gk"
let after_scr2_line = line(".")
if ( (after_scr_line == after_scr2_line) && (after_scr_line > 1) )
execute "normal" "gk"
endif
let extra = (num_scroll - 1)
let extra += (winline() - 1)
" move by 1 to prevent over scrolling
let iter = 1
while (iter <= extra)
execute "normal" "gk"
let iter +=1
endwhile
" -------------
call <SID>RtrnToOrig(before_scr_line)
endfunction
nmap <silent> <C-J> :call <SID>scrollUP(1)<CR>
nmap <silent> <C-K> :call <SID>scrollDN(1)<CR>
nmap <silent> <C-F> :call <SID>scrollUP(-1)<CR>
nmap <silent> <C-B> :call <SID>scrollDN(-1)<CR>
nmap <silent> <PageDown>:call <SID>scrollUP(-2)<CR>
nmap <silent> <PageUp> :call <SID>scrollDN(-2)<CR>
这使用正常的 H, L 转到屏幕顶部,bot 和 gk, gj 命令按屏幕行而不是实际行向上、向下移动。当行长于屏幕宽度并且自动换行打开时,它比正常工作所需的复杂得多。
或者这个方法(之前已经在 vim Tips wiki 和 Stack Exchange 上发布过):
方法二:
" N<C-D> and N<C-U> idiotically change the scroll setting
function! s:Saving_scrollV(cmd)
let save_scroll = &scroll
execute "normal" a:cmd
let &scroll = save_scroll
endfunction
" move and scroll
nmap <silent> <C-J> :call <SID>Saving_scrollV("1<C-V><C-D>")<CR>
vmap <silent> <C-J> <Esc> :call <SID>Saving_scrollV("gv1<C-V><C-D>")<CR>
nmap <silent> <C-K> :call <SID>Saving_scrollV("1<C-V><C-U>")<CR>
vmap <silent> <C-K> <Esc> :call <SID>Saving_scrollV("gv1<C-V><C-U>")<CR>
nmap <silent> <C-F> :call <SID>Saving_scrollV("<C-V><C-D>")<CR>
vmap <silent> <C-F> <Esc> :call <SID>Saving_scrollV("gv<C-V><C-D>")<CR>
nmap <silent> <PageDown> :call <SID>Saving_scrollV("<C-V><C-D>")<CR>
vmap <silent> <PageDown> <Esc>:call <SID>Saving_scrollV("gv<C-V><C-D>")<CR>
nmap <silent> <C-B> :call <SID>Saving_scrollV("<C-V><C-U>")<CR>
vmap <silent> <C-B> <Esc> :call <SID>Saving_scrollV("gv<C-V><C-U>")<CR>
nmap <silent> <PageUp> :call <SID>Saving_scrollV("<C-V><C-U>")<CR>
vmap <silent> <PageUp> <Esc> :call <SID>Saving_scrollV("gv<C-V><C-U>")<CR>
第二种方法的唯一问题是当行长于屏幕宽度并且自动换行打开时,光标可以向上或向下移动一些以解决换行中的额外行。同样在文件的顶部和底部,光标可以移动。第一种方法确实试图在所有情况下都不移动光标。
这会更改光标在屏幕上的位置,但不会更改光标线在屏幕上的位置:
noremap <C-k> @="1\<lt>C-D>"<CR>:set scroll=0<CR>
noremap <C-l> @="1\<lt>C-U>"<CR>:set scroll=0<CR>
然而,这会重置选项scroll
,因此后续将滚动半屏。如果没有,该选项将被设置为 1,随后将滚动一行(Vim 很奇怪)。<C-D>
<C-U>
set scroll=0
scroll
<C-D>
<C-U>
可能是一个基于 Vimscript 的函数1<C-D>
并且1<C-U>
将是最好的。