Vim滚动而不更改光标在屏幕上的位置

时间:2010-08-17 14:31:57

标签: vim scroll cursor

当光标位于屏幕中间并向下滚动时,光标在屏幕上向上移动。我不希望它这样做。

如何滚动而不更改光标在屏幕上的位置?

解决方案,回答后添加:

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

6 个答案:

答案 0 :(得分:43)

我能想到两种方法: ctrl - E ctrl - Y 滚动缓冲区不移动光标相对于窗口的位置。我想这就是你想要的。此外,如果将scrolloff设置为较大的数字,您将获得与 ctrl - E ctrl - <相同的效果带有移动键的kbd> Y 。 scrolloff设置会使光标难以相对于窗口垂直移动。 (使用:set so=999之类的内容,soscrolloff的缩写。)

:help 'scrolloff'
:help scrolling

答案 1 :(得分:11)

ctrl - D ctrl - U 就是你想要的。

ctrl - D 14j14<C-e>具有相同的效果(只是数字14不是硬编码的,移动量取决于实际尺寸你的屏幕):你在文本中向下移动光标几行,但光标停留在屏幕的中间。

类似地 ctrl - U 的作用类似于14k14<C-y>

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

答案 2 :(得分:6)

如果你想用光标在屏幕的任何地方移动光标和视口,也许你应该设置一些自定义键绑定来同时执行这两个操作。

如:

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

每按一次j(仅在正常模式下),这会将光标向下移动(Ctrl-e)并移动视口(Ctrl-Alt-u)。

答案 3 :(得分:1)

在.vimrc中尝试此映射

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

答案 4 :(得分: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功能可能是最好的。

答案 5 :(得分: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进入屏幕顶部,机器人和gk,gj命令向上移动,向下移动屏幕行而不是实际行。当线条长度大于屏幕宽度并且自动换行时,它比正常工作更复杂。

或者此方法(之前已在vim提示wiki和Stack Exchange中发布):

方法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>

我对第二种方法的唯一问题是当线条长度大于屏幕宽度并且自动换行时,光标可以向上或向下移动一些以考虑换行中的额外线条。同样在文件的顶部和底部,光标可以移动。第一种方法确实试图在所有情况下都不会移动光标。