Прокрутка Vim без изменения курсора на экране
Когда курсор находится в середине экрана, и я прокручиваю вниз, курсор перемещается вверх по экрану. Я не хочу, чтобы это делалось.
Как я могу прокручивать, не меняя курсора на экране?
Решение, добавленное после ответа:
noremap <C-k> 14j14<C-e>
noremap <C-l> 14k14<C-y>
Ответы
Ответ 1
Если вы хотите как перемещать курсор, так и область просмотра с помощью курсора в любом месте экрана, возможно, вам нужно настроить некоторые пользовательские привязки клавиш для выполнения обоих сразу.
Например:
:nnoremap <C-M-u> j<C-e>
Это приведет к перемещению курсора вниз (j
) и перемещению области просмотра (Ctrl-e
) всякий раз, когда вы нажимаете Ctrl-Alt-u
(только в нормальном режиме).
Ответ 2
Есть два способа, о которых я могу думать: ctrl - E и ctrl - Y прокручивать буфер, не перемещая позицию курсора относительно окна. Я думаю, это то, чего вы хотите. Кроме того, если вы установите scrolloff
на большое число, вы получите тот же эффект, что и ctrl - E и ctrl - Y с помощью клавиш перемещения. scrolloff
будет затруднять перемещение курсора по вертикали относительно окна. (Используйте что-то вроде :set so=999
, so
является аббревиатурой для scrolloff
.)
:help 'scrolloff'
:help scrolling
Ответ 3
ctrl - D и ctrl - U - это то, что вы хотите.
ctrl - D имеет тот же эффект, что и 14j14<C-e>
(просто, что число 14 не жестко закодировано, а количество движения зависит от фактического размера экрана): вы перемещаете курсор на несколько строк вниз в тексте, но курсор остается посередине экрана.
Аналогично ctrl - U работает как 14k14<C-y>
.
Приложение: Если на вашем экране 30 строк, то они точно совпадают.
Ответ 4
Попробуйте это сопоставление в .vimrc
map <ScrollWheelUp> 5<C-Y>
map <ScrollWheelDown> 5<C-E>
Ответ 5
Это изменяет положение курсора на экране, но не меняет положение курсора на экране:
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 странно).
Вероятно, функция Vimscript, основанная на 1<C-D>
и 1<C-U>
, была бы лучшей.
Ответ 6
Есть два метода, о которых я знаю. Добавьте эти строки в ваш .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 для перемещения вверх, вниз по экрану экрана вместо фактической строки. Его сложнее, чем казалось бы, нужно просто правильно работать, когда линии длиннее ширины экрана и wordwrap.
Или этот метод (который ранее был опубликован в вики-вики и на 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>
Единственная проблема, с которой я сталкиваюсь во втором методе, - это когда строки длиннее ширины экрана и wordwrap, тогда курсор может перемещаться вверх или вниз, чтобы учитывать дополнительные строки из обертки. Также в самом верхнем и нижнем углу файла курсор может перемещаться. Первый метод действительно пытается никогда не перемещать курсор во всех случаях.