2010-08-17 228 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