How to move screen without moving cursor in Vim? - vim

I recently discovered Ctrl+E and Ctrl+Y shortcuts for Vim that respectively move the screen up and down with a one line step, without moving the cursor.
Do you know any command that leaves the cursor where it is but moves the screen so that the line which has the cursor becomes the first line? (having a command for the last line would be a nice bonus).
I can achieve this by manually pressing Ctrl+E (or Ctrl+Y) the proper number of times, but having a command that somehow does this directly would be nice.
Any ideas?

zz - move current line to the middle
of the screen
(Careful with zz, if you happen to have Caps Lock on accidentally, you will save and exit vim!)
zt - move current line
to the top of the screen
zb - move
current line to the bottom of the
screen

Additionally:
Ctrl-y Moves screen up one line
Ctrl-e Moves screen down one line
Ctrl-u Moves cursor & screen up ½ page
Ctrl-d Moves cursor & screen down ½ page
Ctrl-b Moves screen up one page, cursor to last line
Ctrl-f Moves screen down one page, cursor to first line
Ctrl-y and Ctrl-e only change the cursor position if it would be moved off screen.
Courtesy of www.lagmonster.org/docs/vi2.html

Vim requires the cursor to be in the current screen at all times, however, you could bookmark the current position scroll around and then return to where you were.
mg # This book marks the current position as g (this can be any letter)
<scroll around>
`g # return to g

I'm surprised no one is using the Scrolloff option which keeps the cursor in the middle of the page.
Try it with:
:set so=999
It's the first recommended method on the Vim wiki and works well.

I've used these shortcuts in the past (note: separate key strokes i.e. tap z, let go, tap the subsequent key):
z t ...or... z enter --> moves current line to top of screen
z z ...or... z . --> moves current line to center of screen
z b ...or... z - --> moves current line to bottom
If it's not obvious:
enter means the Return or Enter key.
. means the DOT or "full stop" key (.).
- means the HYPHEN key (-)
For what it's worth, z. avoids the danger of saving and closing Vi by accidentally typing ZZ if the caps-lock is on.
More info: :help scroll-cursor

Here's my solution in vimrc:
"keep cursor in the middle all the time :)
nnoremap k kzz
nnoremap j jzz
nnoremap p pzz
nnoremap P Pzz
nnoremap G Gzz
nnoremap x xzz
inoremap <ESC> <ESC>zz
nnoremap <ENTER> <ENTER>zz
inoremap <ENTER> <ENTER><ESC>zzi
nnoremap o o<ESC>zza
nnoremap O O<ESC>zza
nnoremap a a<ESC>zza
So that the cursor will stay in the middle of the screen, and the screen will move up or down.

To leave the cursor in the same column when you use Ctrl+D, Ctrl+F, Ctrl+B, Ctrl+U, G, H, M, L, gg
you should define the following option:
:set nostartofline

my mnemonic for scrolling...
Adding to other answers also pay attention to ze and zs, meaning: move screen to the left/right of the cursor (without moving the cursor)
+-------------------------------+
^ |
|c-e (keep cursor) |
|H(igh) zt (top) |
| ^ |
| ze | zs |
|M(iddle) zh/zH <--zz--> zl/zL |
| | |
| v |
|L(ow) zb (bottom) |
|c-y (keep cursor) |
v |
+-------------------------------+
also look at the position of h and l and t and b and (with qwertz keyboard) c-e and c-y (also the "y" somehow points to the bottom) on the keyboard to remember where the screen is moving.

Enter vim and type:
:help z
z is the vim command for redraw, so it will redraw the file relative to where you position the cursor. The options you have are as follows:
z+ - Redraws the file with the cursor at top of the window and at first non-blank character of your line.
z- - Redraws the file with the cursor at bottom of the window and at first non-blank character of your line.
z. - Redraws the file with the cursor at centre of the window and at first non-blank character of your line.
zt - Redraws file with the cursor at top of the window.
zb - Redraws file with the cursor at bottom of the window.
zz - Redraws file with the cursor at centre of the window.

You can prefix your cursor move commands with a number and that will repeat that command that many times
10Ctrl+E will do Ctrl+E 10 times instead of one.

zEnter does exactly what this question asks for.
It works where strangely zz would not work (vim 7.4.1689 on Ubuntu 2016.04 LTS with no special .vimrc)

You may find answers to "Scrolling Vim relative to cursor, custom mapping" useful.
You can use ScrollToPercent(0) from that question to do this.

Sometimes it is useful to scroll the text with the K and J keys, so I have this "scroll mode" function in my .vimrc (also bound to zs).
See scroll_mode.vim.

I wrote a plugin which enables me to navigate the file without moving the cursor position. It's based on folding the lines between your position and your target position and then jumping over the fold, or abort it and don't move at all.
It's also easy to fast-switch between the cursor on the first line, the last line and cursor in the middle by just clicking j, k or l when you are in the mode of the plugin.
I guess it would be a good fit here.

Related

VIM: How do I move the cursor to the left of the screen?

I know that 0 moves to the beginning of the line and $ to the end of the line, but I am working with long lines with nowrap set. I want to jump to the left side of the screen.
How would I do that?
While we are at it, how do I jump to the right of the screen?
g0 to move to beginning
g$ to move to end
gm to move to middle
g^ to move to first non-blank character
Further Reading
start from :h g_ for in-built help
vim moving with hjkl in long lines (screen lines)

Don't center screen when hitting end in vim

With nowrap and when on a long line, hitting the end button takes the cursor to the end of the line (of course). Furthermore, the screen will be centered on the cursor.
It will take the cursor from here:
to here:
How can I make it scroll right only up to "line."? And thus have the last "this is a long line." aligned to the right of the window?
Edit: I already know about sidescroll and sidescrolloff but those only apply when using the arrow keys. It doesn't change behavior for the end key, and thus don't solve my problem.
if you check :h ze
ze Scroll the text horizontally to position the cursor
at the end (right side) of the screen. This only
works when 'wrap' is off. {not in Vi}
so if you create a mapping, map $ or <end> to $ze or <end>ze, it should work as you wish.
hope it helps.
EDIT
if you want to map like what you wanted in INSERT mode:
:set sidescroll=1
:inoremap <End> <Esc><End>zei

Vim: Why can't I map to the <j> key?

I saw this key bind in tips.txt:
: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>
Which results in smooth scrolling up for CTRL-U. It only moves the viewport though, and I'd like to also move the cursor, so for scrolling down I tried:
:map <C-D> <C-E><j><C-E><j><C-E><j><C-E><j><C-E><j><C-E><j><C-E><j><C-E><j>
Since CTRL-E moves the viewport down and j moved the cursor down. This doesn't work however. When I press CTRL-D the viewport just hops one line down and the terminal beeps.
How do I map CTRL+D to scroll and move the cursor?
You shouldn't have the angled brackets (</>) around j.

VimTutor arrow keys v/s hjkl

VimTutor says in its first lesson:
NOTE: The cursor keys should also work. But using hjkl you will be
able to
move around much faster, once you get used to it. Really!
However, I find no difference at all between them. Is there really a difference between using hjkl v/s the arrow keys?
You don't have to move your hand from the touch type position to use hjkl, whereas you do if you use the arrow keys.
The thing is that you start out using the "hjkl" key just as a slightly better way to move your cursor, but the truth is that they are actually motions.
h motions one character left
j motions one line down
k motions one line up
l motions one character right
So for example, with the delete operator d: dl deletes the current character, dh deletes the previous character, dj deletes the current line and a line below it, and dk deletes the current line and a line above it. The same is of course true for the y, c, V, gU and any operator.
Another example are split windows. You can create a couple of windows using Control-w+s and Control-w+v, then use your trusty hjkl to move around between your windows, Control-w+h moves a window left, Control-w+j moves a window down, etcetera.
So it's not just that they are an improvement over the arrow keys. As your understanding of Vim grows, you'll learn that the hjkl keys can be combined with other commands in many ways, and you will be happy you can use them.
In fact, using h j k l keys makes a good practice to avoid to much of right hand movimentation on your keyboard when you have to reach the arrow keys but, there are more efficient ways to navigate through a text file using vim:
f <char> : Go to the next occurrence of a character<char> on the current line. Cursor is placed above the character;
t <char> : Go to the next occurrence of a character<char> on the current line. Cursor is placed right before the character;
T and F: Backward your character search on this line, however T will put the cursor right after the character(or before if you think backwards ;) ), and F will put it above of it.
/ <char> <Enter>: Go the next occurrence of a character independent of line. After you do this one time, pressing n or N goes to the next and previous occurrence.
? <char> <Enter>: Go to the next occurrence of a character independent of line, backwards. n will search next occurrence(backwards) and N will go to the previous.
{ and } : Navigate on paragraphs. Paragraphs are basically blocks divided by an empty line. See :help paragraph for further details.
( and ) : Navigate back and forward on Sentences(:help sentence). A sentence is a group of words ended by . ! or ? followed by a space, tab or endline.
e : next word, place the cursor at the end of the word
w : next word, place the cursor at the start of the word
b : back 1 word, place the cursor at the start of the word
ge : back 1 word, place the cursor at the end of the word
E W B and gE : Same as e w b ge, but with WORD. See :help word for further details.
If you want to start by getting the first good habits of using h j k l or other movements and avoid the arrow keys, pleace the following lines on your .vimrc file inside your home to disable them:
noremap <Up> <NOP>
noremap <Down> <NOP>
noremap <Left> <NOP>
noremap <Right> <NOP>

To switch from vertical split to horizontal split fast in Vim

How can you switch your current windows from horizontal split to vertical split and vice versa in Vim?
I did that a moment ago by accident but I cannot find the key again.
Vim mailing list says (re-formatted for better readability):
To change two vertically split
windows to horizonally split
Ctrl-w t Ctrl-w K
Horizontally to vertically:
Ctrl-w t Ctrl-w H
Explanations:
Ctrl-w t makes the first (topleft) window current
Ctrl-w K moves the current window to full-width at the very top
Ctrl-w H moves the current window to full-height at far left
Note that the t is lowercase, and the K and H are uppercase.
Also, with only two windows, it seems like you can drop the Ctrl-w t part because if you're already in one of only two windows, what's the point of making it current?
Ctrl-w followed by H, J, K or L (capital) will move the current window to the far left, bottom, top or right respectively like normal cursor navigation.
The lower case equivalents move focus instead of moving the window.
When you have two or more windows open horizontally or vertically and want to switch them all to the other orientation, you can use the following:
(switch to horizontal)
:windo wincmd K
(switch to vertical)
:windo wincmd H
It's effectively going to each window individually and using ^WK or ^WH.
The following ex commands will (re-)split any number of windows:
To split vertically (e.g. make vertical dividers between windows), type :vertical ball
To split horizontally, type :ball
If there are hidden buffers, issuing these commands will also make the hidden buffers visible.
In VIM, take a look at the following to see different alternatives for what you might have done:
:help opening-window
For instance:
Ctrl-W s
Ctrl-W o
Ctrl-W v
Ctrl-W o
Ctrl-W s
...
Horizontal to vertical split
Ctrl+W for window command,
followed by Shift+H or Shift+L
Vertical to horizontal split
Ctrl+W for window command,
followed by Shift+K or Shift+J
Both solutions apply when only two windows exist.
After issuing the window command Ctrl+W, one is basically moving the window in the direction indicated by Shift+direction letter.
Opening help in a vertical split by default
Add both of these lines to .vimrc:
cabbrev help vert help
cabbrev h vert h
cabbrev stands for command abbreviation.
:vert[ical] {cmd} always executes the cmd in a vertically split window.
Inspired by Steve answer, I wrote simple function that toggles between vertical and horizontal splits for all windows in current tab. You can bind it to mapping like in the last line below.
function! ToggleWindowHorizontalVerticalSplit()
if !exists('t:splitType')
let t:splitType = 'vertical'
endif
if t:splitType == 'vertical' " is vertical switch to horizontal
windo wincmd K
let t:splitType = 'horizontal'
else " is horizontal switch to vertical
windo wincmd H
let t:splitType = 'vertical'
endif
endfunction
nnoremap <silent> <leader>wt :call ToggleWindowHorizontalVerticalSplit()<cr>
Following Mark Rushakoff's tip above, here is my mapping:
" vertical to horizontal ( | -> -- )
noremap <c-w>- <c-w>t<c-w>K
" horizontal to vertical ( -- -> | )
noremap <c-w>\| <c-w>t<c-w>H
noremap <c-w>\ <c-w>t<c-w>H
noremap <c-w>/ <c-w>t<c-w>H
Edit: use Ctrl-w r to swap two windows if they are not in the good order.

Resources