web-dev-qa-db-ja.com

画面上のカーソルを変更せずにVimをスクロールする

カーソルが画面の中央にあり、下にスクロールすると、カーソルが画面上を上に移動します。私はそれをしたくありません。

画面上のカーソルを変更せずにスクロールするにはどうすればよいですか?

解決策、回答後に追加:

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

画面内の任意の場所にカーソルを置いてカーソルとビューポートの両方を移動する場合は、両方を同時に実行するようにカスタムキーバインディングを設定する必要があります。

といった:

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

これにより、Ctrl-eを押すたびにカーソルが下(j)に移動し、ビューポート(Ctrl-Alt-u)が移動します(通常モードのみ)。

7
wds

私が考えることができる2つの方法があります: ctrl-E そして ctrl-Y ウィンドウに対するカーソルの位置を移動せずにバッファをスクロールします。それがあなたの望みだと思います。また、scrolloffを大きな数値に設定すると、と同じ効果が得られます。 ctrl-E そして ctrl-Y 移動キーで。ただし、scrolloffを設定すると、カーソルをウィンドウに対して垂直方向に移動させるのが難しくなります。 (:set so=999のようなものを使用してください。soscrolloffの省略形です。)

:help 'scrolloff'
:help scrolling
44
Alok Singhal

ctrl-D そして ctrl-U あなたが望むものです。

ctrl-D14j14<C-e>と同じ効果があります(数字の14はハードコードされておらず、移動量は画面の実際のサイズによって異なります):カーソルをテキスト内で数行下に移動しますが、カーソルはそのままになります。画面の中央。

同様に ctrl-U14k14<C-y>のように機能します。

補遺:画面に30行ある場合、2つはまったく同じです。

11
Matthias 009

.vimrcでこのマッピングを試してください

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

私が知っている2つの方法があります。これらの行を.vimrcファイルに追加します(2つの方法のうち1つだけを選択します)。

方法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 TipswikiおよびStackExchangeに投稿されています):

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

2番目の方法で私が抱えている唯一の問題は、行が画面幅より長く、ワードラップがオンになっている場合、カーソルが上下に移動して、折り返しからの余分な行を考慮できることです。また、ファイルの最上部と最下部でカーソルを移動できます。最初の方法は、実際にはすべての場合にカーソルを動かさないようにします。

0
M Kelly

これにより、画面上のカーソルの位置が変更されますが、画面上のカーソル行の位置は変更されません。

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>は1行スクロールします(Vimは奇妙です)。

おそらく、1<C-D>1<C-U>に基づくVimscript関数が最適でしょう。

0
Alexey