2010-08-17 125 views
34

当光标位于屏幕中间时,向下滚动,光标在屏幕上向上移动。我不希望它那样做。Vim滚动时不改变光标在屏幕上的位置

如何在不改变游标屏幕位置的情况下滚动?

解决方案,答案后说:

noremap <C-k> 14j14<C-e> 
noremap <C-l> 14k14<C-y> 
+0

您可以使用光标进行滚动,也可以在不移动光标的当前行的情况下滚动屏幕(尽管它会在行移动时移动到屏幕上的位置)。我认为你不能完全实现你正在寻找的东西......如果只是打下页面呢? – Fosco 2010-08-17 14:34:51

+0

页面向下是更大的移动滚动。 – 2010-08-17 14:39:43

+3

这是一个重复: http://stackoverflow.com/questions/3458689/how-to-move-screen-without-moving-cursor-in-vim/ – GWW 2010-08-17 15:03:48

回答

5

如果要同时移动光标,光标在屏幕上任意位置的视窗,也许你应该设置一些自定义键绑定同时做两。

如:

:nnoremap <C-M-u> j<C-e> 

这将向下移动光标(j),只要你按Ctrl-Alt-u(仅在正常模式下)移动视(Ctrl-e)。

41

有两种方法我能想到的:CTRL - ËCTRL - Ÿ滚动没有位置相对光标移动到该窗口的缓冲区。我认为那就是你想要的。此外,如果您设置scrolloff有大量,您将得到同样的效果CTRL - ËCTRL - Ÿ与移动键。 scrolloff设置将使得光标很难相对于窗口垂直移动。 (使用类似:set so=999soscrolloff的缩写。)

:help 'scrolloff' 
:help scrolling 
+2

'ctrl-E' **确实**移动光标相对于窗口的位置,光标跟随文本;如果光标位于窗口/屏幕中间,并且反复按下“ctrl-E”,则光标移动到第一行;这正是提问者不想要的;他想要做'14j14 '只需要14个数字取决于他的屏幕大小 – 2012-11-22 18:13:59

+1

你的第二个建议,设置滚降,做什么操作要求,但它**没有提供相同的效果'CTRL-E';只有滚动的问题是它是永久性的,因为现在不可能在没有滚动的情况下移动;这将是一件好事,一键移动,一键移动而不滚动 – 2012-11-22 18:41:43

+0

Upvote for'so'选项,但@ Matthias009是正确的。 – 2015-01-02 20:07:47

10

CTRL - dCTRL - ü是你想要的。

CTRL - d具有作为14j14<C-e>相同的效果(刚才说的14号没有硬编码和移动量取决于屏幕的实际尺寸):你在向下移动光标的几行文本但光标停留在屏幕中间。

同样CTRL - ü作品像14k14<C-y>

附录:如果您的屏幕有30行,那么两者完全相同。

+1

更确切地说:[count] 和[count] 是他想要的。 – ciastek 2013-03-19 11:31:52

+0

@ciastek你应该做出答案。 – Zenexer 2013-06-11 05:43:56

0

试试这个映射。的vimrc

map <ScrollWheelUp> 5<C-Y> 
map <ScrollWheelDown> 5<C-E> 
0

可以改变光标在屏幕上的位置,但不会改变光标线在屏幕上的位置:

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选项,因此后续<C-D><C-U>会滚动一半屏幕。如果没有set scroll=0,则scroll选项将被设置为1,随后的<C-D><C-U>将滚动一行(Vim很奇怪)。

基于1<C-D>1<C-U>的Vimscript函数可能是最好的。

0

我知道有两种方法。这些行添加到您的.vimrc文件(选择两种方法只有一个):

方法1:

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命令可以通过屏幕线而不是实际线向上移动。当线条长度超过屏幕宽度并且打开wordwrap时,它会比看起来需要更加复杂的工作。

或者这种方法(先前已经在vim技巧wiki和对堆栈交易所发布):

方法2:

" 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> 

我有第二种方法唯一的问题是当行比屏幕宽度和wordwrap更长,则光标可以向上或向下移动一些以解释换行中的额外行。同样在文件的顶部和底部,光标可以移动。第一种方法确实试图在所有情况下不移动光标。

+0

你能否提供你的答案更详细的解释?否则对任何后来出现的人来说都没有意义。 – 2016-12-13 21:31:45

+0

好吧,您将这些行添加到.vimrc文件中。当wordwrap关闭时,或当它打开但线条都比窗口宽度短时,在不移动光标的情况下进行滚动非常简单。但是当wordwrap打开并且行比窗口宽度更长时,滚动可以将光标向上或向下移动一些,因为它会向下或向上移动一行。顶部方法无论如何保持光标位置,但我只在正常模式下使用它。 – 2016-12-14 01:05:36

+0

正常的H移动到最上面的一行,正常的L移动到最后一行,从那里你可以计算出用“gj”或“gk”移动多少屏幕行来滚动屏幕行,然后返回到原始屏幕线。 – 2016-12-14 01:08:07