In Vim normal mode, you can press ctrl+e and ctrl+y to scroll down and up, respectively. I'm trying to make a key-bind that lets me do this from insert mode as well. This is what I've got:
" Scroll up and down while in insert mode.
inoremap <C-e> <C-o><C-e>
inoremap <C-y> <C-o><C-y>
This works like expected, but it has a big flaw. It leaves insert mode, scrolls, then re-enters insert mode. This is relevant when it comes to undo, repeat command etc. and I would like to be able to scroll up and down without leaving insert mode. Thoughts?
You could take a look at :h i_CTRL-X_CTRL-E, which is a built-in insert-mode mapping to scroll:
*i_CTRL-X_CTRL-E*
CTRL-X CTRL-E scroll window one line up.
When doing completion look here: |complete_CTRL-E|
*i_CTRL-X_CTRL-Y*
CTRL-X CTRL-Y scroll window one line down.
When doing completion look here: |complete_CTRL-Y|
So in your case, this would probably do the trick:
inoremap <C-e> <C-x><C-e>
inoremap <C-y> <C-x><C-y>
undojoin fixes the undo part of it:
ino <C-E> <Space><BS><ESC><C-E>:undojoin<CR>gi
The <Space><BS> sequence makes sure there's an undo block to join with.
Surprisingly (to me) this doesn't help with the . breakage, so this might leave you in just as annoying a spot as you're in now...
I just discovered :set mouse=a. Amazing thing, it allows my coworkers to scroll over my openend files.
But here is the thing : I really don't want the cursor to move when I left-click somewhere. I don't want either the standard cursor which :set mouse=a brings (I want to keep the default text cursor).
In others words : is there a way to enable mouse scrolling in VIm without enable other support mouse stuff ?
Thanks.
EDIT - other idea : can I bind the wheel mouse UP to do the same thing that Page Up key ? It would be awesome !
Try this mapping:
:nnoremap <LeftMouse> <nop>
The main scrolling commands in Vim are:
Ctrl-B and Ctrl-F, as well as PageUp and PageDown scroll by full page
Ctrl-U and Ctrl-D scroll half a page by default
Ctrl-Y and Ctrl-E scroll one line
I lose visual context every time for the former two, so I have developed the bad habit of hitting the latter (Ctrl-Y and Ctrl-E) repetitively.
Since there is currently no first party support for smooth scrolling, what are the least objectionable workarounds/plugins?
I use both Vim and GVim depending on the task, and am happy to customize them separately if there is no one really good hack that works for both. The mouse scroll wheel works nicely in GVim, but I'm looking for keyboard based solutions.
Update: I have now pushed this code, refactored somewhat according to the guidelines at :help write-plugin, to a Github repo.
Using the Keyboard
Here is what I have in my .vimrc:
function SmoothScroll(up)
if a:up
let scrollaction="^Y"
else
let scrollaction="^E"
endif
exec "normal " . scrollaction
redraw
let counter=1
while counter<&scroll
let counter+=1
sleep 10m
redraw
exec "normal " . scrollaction
endwhile
endfunction
nnoremap <C-U> :call SmoothScroll(1)<Enter>
nnoremap <C-D> :call SmoothScroll(0)<Enter>
inoremap <C-U> <Esc>:call SmoothScroll(1)<Enter>i
inoremap <C-D> <Esc>:call SmoothScroll(0)<Enter>i
Features:
Scroll on the base of the Vim scroll option.
Customizable scrolling speed (adjust time argument of the sleep command; I use ten milliseconds). Note: just like slowing down the frame rate on a video, if you slow down the smooth scroll too much it will be jerky scroll, not smooth scroll. But whatever works best for you.
Works in normal or insert mode.
Note: all you copy-and-pasters, remember that the ^ character indicates a control character; copy-paste will produce invalid results and these must be entered manually!
^Y – CTRL-V then CTRL-Y
^E – CTRL-V then CTRL-E
However, the <C-U> and <Enter> style syntaxes are literally typed as those characters; the map command intelligently converts them to control characters.
Using the Mouse
The question mentions that scrolling with the mouse works well in GVim, but a keyboard solution is desired. This implies to me that the asker may be interested in a mouse solution if it works in regular terminal Vim.
For me, turning mouse support on allows smooth scrolling through the mouse wheel. Also, for me, smooth scrolling is most important when I am looking around (i.e. in normal mode), not when I am editing (in insert mode), and if I am not actively editing, the need for my hands to stay on the keyboard at all times is removed, so this works well.
On the basis of this question, though, it would seem that some people have to do some more manual setup beyond simply turning the mouse on (I just use set mouse=n):
My .vimrc has the following lines
set mouse=a
map <ScrollWheelUp> <C-Y>
map <ScrollWheelDown> <C-E>
There is a simple remap hack in vim's tips.txt:
Smooth scrolling *scroll-smooth*
If you like the scrolling to go a bit smoother, you can use these mappings:
:map <C-U> <C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y>
:map <C-D> <C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E>
Shameless plug, but I created a plugin here that you can use to easily adjust the distance, speed, and duration of the scrolling animation: https://github.com/terryma/vim-smooth-scroll
A Recent Plugin
I have posted something similar here, but basically there is a great plugin that we can use now for scrolling, called terryma/vim-smooth-scroll. It provides a very nice and smooth scrolling.
The install is quite easy:
1 I use Vundle so I simply appended this in .vimrc.bundles :
Bundle terryma/vim-smooth-scroll
In the latest version of Vundle available today, 29th April of 2016, you can put this in your .vimrc:
Plugin 'terryma/vim-smooth-scroll'
2 As stated in the doc, you can set up 3 arguments: distance, duration and speed.
I am using this in my .vimrc file:
noremap <silent> <c-b> :call smooth_scroll#up(&scroll*2, 10, 4)<CR>
noremap <silent> <c-f> :call smooth_scroll#down(&scroll*2, 10, 4)<CR>
What I do is I set the keyboard repeat to very fast, about 120 chars / second, and the delay small.
Then I map to 4j and to 4k
I navigate up and down source code using j and k which moves the cursor up and down nice and quick, pretty smooth.
But here's the good part, and this works on Linux, not Windows.
For a number of years now, X11's keyboard input works in such a way that when you press and hold j it obviously starts putting out j characters. But when you then keep holding down j and then also press the ctrl key, X11 starts putting out c-j characters without you having to re-press the j key. Then when you let go of the ctrl key and still keep on pressing j, X11 continues to put j's again.
So j makes the cursor start moving nice and smooth downwards, and you can periodically hit ctrl without letting go of j to give it a boost, a jolt.
Also, I do what Devin does, and I set scrolloffset to 5.
Lastly, I swap ctrl and cap lock. The default position of the ctrl key is completely retarded (no offense intended). It makes you have to rotate your left hand. I almost never use caps lock, so I swap them. Then my left pink finger can reach the ctrl key without any yoga moves.
These things have worked for me for years. I only use vim, never gvim.
This isn't exactly smooth scrolling, but it's how I handle not losing context when jumping pages.
set so=7
'scrolloff' 'so' number (default 0)
global
{not in Vi}
Minimal number of screen lines to keep above and below the cursor.
This will make some context visible around where you are working. If
you set it to a very large value (999) the cursor line will always be
in the middle of the window (except at the start or end of the file or
when long lines wrap).
For scrolling horizontally see 'sidescrolloff'.
NOTE: This option is set to 0 when 'compatible' is set.
The Plugin cskeeters/vim-smooth-scroll supports smooth scrolling and requires no configuration. It supports to support smooth scrolling with zt, zz, and zb. It's a fork of terryma's plugin. Some of the open pull requests have been applied.
This combines many of these answers, and this is what I use.
noremap <expr> <C-u> repeat("\<C-y> :sleep 10m<CR>", winheight('%')/2)
noremap <expr> <C-d> repeat("\<C-e> :sleep 10m<CR>", winheight('%')/2)
N <CR-E>
N <CR-Y>
...where 'N' is the number of single lines you want to scroll.
Not smooth in literal sense, but you keep the keyboard.
This may be controversial for hardcore users, but... the best way to smooth scroll in Vim is... mouse wheel.
I just found this plugin called "accelerated-smooth-scroll" ("Vim plugin for accelerated smooth scroll (mapping to <C-D>/<C-U>, <C-F>/<C-B>)") which can be for example used through Vundle by putting this line in your .vimrc:
Plugin 'yonchu/accelerated-smooth-scroll'
Then by restarting Vim and running the :PluginInstall command, then again restart Vim and use the <C-D> (Ctrl+D) and <C-O> (Ctrl+O) commands normally.
Sadly, this plugin also moves the cursor instead of what I wanted: to just scroll the screen like the <C-E> and <C-Y> commands.
I slightly modified #Keith Pinson's code so that ctrl-f and ctrl-b can be mapped too:
function SmoothScroll(scroll_direction, n_scroll)
let n_scroll = a:n_scroll
if a:scroll_direction == 1
let scrollaction=""
else
let scrollaction=""
endif
exec "normal " . scrollaction
redraw
let counter=1
while counter<&scroll*n_scroll
let counter+=1
sleep 10m " ms per line
redraw
exec "normal " . scrollaction
endwhile
endfunction
" smoothly scroll the screen for some scrolling operations
nnoremap <C-U> :call SmoothScroll(1,1)<cr>
nnoremap <C-D> :call SmoothScroll(2,1)<cr>
nnoremap <C-B> :call SmoothScroll(1,2)<cr>
nnoremap <C-F> :call SmoothScroll(2,2)<cr>
When I do a search with vim or gvim, the resulting positioning of the cursor within the window is somewhat random, all too frequently landing on the last (or first) line in the window. Search highlighting helps, but it's still cumbersome to have to look all around on the screen to find the cursor ... and a bit ironic, that after vim locates the next result in some megabytes-long log file, I have to use the ol' neocortex to isolate it from the last 4K or so.
I can manually get the effect I want by hitting 'zz' after every search, but would prefer to doctor up my _vimrc to make this happen automatically.
Will this work for you ?
:nmap n nzz
:nmap p pzz
I use this trick with other commands too:
nnoremap n nzz
nnoremap N Nzz
nnoremap <C-o> <C-o>zz
nnoremap <C-i> <C-i>zz
An alternative to nzz and Nzz is probably
:set scrolloff=5
which keeps 5 lines below/above cursor in view.
As #Mike-B pointed out, the accepted answer of doing
nmap n nzz
does not open folds.
As an alternative I propose the following. It is a bit hacky, but seems to work for me:
nmap nzvzz
and equivalent for the other motions, if you want. zv should open all folds till the current cursor position is visible.
I have a big file with thousands of lines of thousands of characters.
I move the cursor to 3000th character.
If I use PageDown or Ctrl+D, the file will scroll but the cursor will come back to the first no-space character.
There's is an option to set to keep the cursor in the same column after a such scroll ?
I have the behavior with gvim on Window, vim on OpenVMS and Cygwin.
CTRL-E - scroll down
CTRL-Y - scroll up
100<CTRL-E> will scroll down 100 lines for example
If you like using PageUp, PageDown or Ctrl+D etc. you can set the "nostartofline" option
:set nostartofline
Well, one easy way to do so is using the movement keys. For example, to go down 100 lines keeping the cursor at the same column: "100j"
Edit:
Alright, searching a little more to really find an answer to your question, there's an option to do exactly what you want:
:set nostartofline
A Recent Plugin
I am using terryma/vim-smooth-scrolling plugin as it provides a very nice and smooth scrolling.
To install, you can use Vundle:
Bundle terryma/vim-smooth-scrolling
As stated in the doc, you can set up 3 arguments: distance, duration and speed.
I am using this in my .vimrc file:
noremap <silent> <c-b> :call smooth_scroll#up(&scroll*2, 10, 4)<CR>
noremap <silent> <c-f> :call smooth_scroll#down(&scroll*2, 10, 4)<CR>
This might not suit your situation at all, but if it makes it easier to break the lines up you can break them at a certain character e.g. after ':'
:%s/:/\r&/g
Or every 80 characters
:%s/.\{80}/&\r/g