Vim

7icode 7x faster!^]

Or the few vim commands I use all the time because they improve editing speed a lot.

Do not try to learn it all at once, it's better to learn bit by bit. But really practice and force yourself into using the bit you have learned. When it becomes natural, proceed with the next bit.

Note: ^x means control-x, not ^ then x. I also use ^M to mean the enter key.

Introduction (aka the stuff you can skip)

Vi is a visual editor. That is all it does, editing files, but it does it damn well. One of the reasons I use w3m to browse the web is that it can invoke vim to fill forms fields (yes, there are some other plugins for some other webbrowsers, but they just can't replace a real vim). Of course, I also use the vi mode of zsh.

Vim shortcuts are meant for working on editing files only, and that's what they are good at. And they combine very logically and powerfully. Use shortcuts, that is what makes vi so good.

The keyboard is your friend. The mouse is a slow device. Use the keyboard. Learn typing without looking at it. You'll save way more time in the future than what you'll have spent to learn that.

Moving around

Don't use the arrow keys. Learn the h j k l movements, it's way faster to use than moving the hand to the arrows.

Train yourself into using H, M, L, { }, (, ), ^, $, %, w, W, b, B, e, E, or even use /foo, t), f), ; to quickly go where you need. Yes, really get used to use them all. It looks idiotic to have so many ways to move around but it actually makes things way faster, once having taken the habit of using each of them exactly when it fits what you need.

Use ^E and ^Y to reposition your viewing position without moving the cursor. z^M, z. and z- are very useful to quickly reposition globally.

Use repeaters: instead of pressing j several times, press e.g. 10j then j a couple of time: it's faster to make a rough estimation and fix it than moving line by line.

Use ; and , just like you would use n and N: for example, while moving inside /some/very/long/path, using w is a bit tedious because you'll need to press it twice for each path item. You can instead use f/ to go to the next /, but it's tedious to type f/ repeatedly. Use f/ once, and then ;, it'll repeat the last f movement! This is also useful for instance when moving from command to command separated by ; on a command line.

Use marks: ma puts mark 'a' where you were. Use 'a to get back to it. You can of course use a-z and A-Z. '' is a quickie for going back to the last position (after e.g. a /).

It is also quite often nice to go back to previous places, ^O and ^I allow to browse back and forward in the locations, including among files!

Registers

It happens very often that I have two things to copy/paste here and there, such as an ifdef/endif pair:

#ifdef FOO_BAR
...
#endif /* FOO_BAR */

Registers help a lot here: instead of just yy to copy just the ifdef, use "ayy, which copies one line into the a register. And "byy to copy the other line. Then use "ap to paste the first line, move a bit, and "bp to paste the second line.

Registers can also be used to accumulate text: "ayy will set the initial content, and then "Ayy will add the current line to the register, which can be done several times of course, and eventually use "ap to paste the collected text.

There are a lot of other registers, notably + and * which are actually the X11 selection and clipboard, permitting safe copy/paste from/to vim in an X11 desktop. Another way is to use :set paste to tell vi that you are about to paste, and it should thus disable auto-indentation and such.

^R can be used to paste the content of a register while in insertion mode (which can be very useful while doing a c command for instance), but also while typing a command. For instance, one can copy a file name with yE and then type :! rm ^R0 to remove it.

Looking for things

Jumping inside source code is of utmost importance when browsing in a big project.

Use tags: run ctags -R at the root of your project, and when the cursor is on a function call (or macro etc.), type ^], that'll jump to the function definition. Use ^t to jump back to where you were.

Use * and #: it looks for what is under the cursor. It's very convenient to e.g. follow what happens to a variable within a function. It's also useful to make sure there is only one occurence of a word in the whole file.

For programmers, gd Goes to the Definition of the variable under the cursor.

delete, change, ...

You are here:

printf("Hello there! How are you?\n");

And you changed your mind, you want to replace "How are you" with "What a nice place!".

Use /How or /!^Mll or f!ll to put yourself there. It's very often way faster to type than to move with the arrows.

Use ctx and cfx. tx is a quickie for “search for next occurrence of x, go just before it (for t) or on it (for f)”. Combined with c (change), that gives you “change up to next occurrence of x”, which is exactly what you need, and that's very common: up to closing parenthesis, up to next comma (to drop one or more arguments of a function, use f, or F, to go further or back, and then paste it again, up to > (end of the html tag), etc. When dealing with paths, it's convenient to use repetition: 3ct/ will change up to 3rd occurrence of '/'.

Also use it for copy/pastes: 2dw will delete the two words, df; will delete up to the semicolon, d) will delete the whole sentence.

I also use it quite often on the shell, taking an existing for loop from the shell history:

for i in bla bli blu; do something complex $i ; done

Going to bla then ct; and voilà, ready to type another list of things to work on.

Really, train yourself into thinking about using such kind of combination, they happen really often!

% can also be very convenient: since it moves to the matching parenthesis, brace, etc., you can easily take some code out and paste it further away.

Even better, i and a can be used to designate a section while you are inside it, for instance:

<foo><bar baz="kljsdf"/></foo

with the cursor e.g. on baz; just use ci< to change the content of the tag (inside), or da< to remove the tag completely (around). This also works with a lot of other movements, for instance daw will remove the word inside which the cursor is, ci" will remove the content of the "-quoted string and enter insertion mode to type the new text. Prepending a number allows to go one level more of tags, quotes, etc.

You can also combine with the < and > commands, to remove/add indentation levels: <i} will add an identation level to the inside of the current brace block.

Yes, learn both d and c, the second is very precious when using '.' (see below).

Oh, yeah, of course, with vim you can also use v to set a visual selection, but quite often it's less efficient than the above. It can still be useful to understand what is happening, and

That said, a nice tip with v: say you want to underline a title:

mytitle

just type yypVr= : it copies the line and replaces it with '=' characters!

Rectangular selection

^V permits to make a rectangular selection, which can be convenient for cut/pastes etc. It's also worth noting that when combined with I, A, or s, it can add a lot of text, e.g. to add some directory within paths:

/foo/bar/baz/file1
/foo/bar/baz/file2
/foo/bar/baz/file3
/foo/bar/baz/file4

Make a rectangular selection over a vertical line of '/', then press I, type a directory name, escape, and voilà, it's done over all the lines. It's way faster than working out the substitution command!

It is also convenient for prepending a # at the beginning of a series of lines, to comment them.

Repeating a selection

It's sometimes useful to make several actions on a selection, but unfortunately after the action the selection is lost. One can however use gv to get the same selection again, to do the next action, etc.

Use '.'

. repeats the last action. It's very useful to e.g. repeat an edition on several words, going through them with n or other movements.

It becomes very powerful to repeat shortcuts like 3ct\, because that's just one action, which you can then repeat in other places.

Use maps

Sometimes one needs to do the exact same things several times, but not exactly everywhere. It can then be useful to map e.g. F1 and F2 to the two cases, for instance here if you want to replace blah with bleh in some files of a series:

:map F1 :s/blah/bleh^M:wn^M/blah^M
:map F2 :n^M/blah^M

Note: ^M is obtained by typing ^V before ^M.

you can then just start with /blah in the first file, and from then on, if the replacement has to be done, press F1 to achieve it and proceed to the next file, or F2 to just proceed to the next file.

It can also be used when some change has to be done in files, and you don't really want to find out how to do it in sed (or perhaps it'll be horribly complex) while you know how to do it reliably with vi, for instance:

:map F1 :wn^M/foo^Mt/^M2ct/baz^[

^[ is ^V escape.

Then you just need to frenetically press F1, while still being able to watch what you are doing.

In combination with predictible changes, movements, etc. you can easily make great automation, real-life instance:

:map F1 yyp^f*96^Af:4^Af"96^A

Use recorded macros

Using :map can be tedius since you don't see what you are doing while typing it. A trick is to record a macro instead. Type q1 , which starts recording macro number 1 (actually stored in register 1), then do the actions you want to see automatized, and finish with q. One can then execute macro number 1 by typing @1 , and then repeat it several times by typing @@. You can also use :map F1 @1 to get the macro executed by pressing F1!

Use ~

~ switches the case of letters. Used with l or space, it permits to fix e.g. the first letter of a sentence to which you prependent some words. Used with w, it turns a whole word (or the end of a word) up or down.

Use external commands

Vim is an editor. Whatever is not editing stuff should be done outside vim, but you can invoke that from vim, for instance to sort some lines of your buffer, first select them, then type !sort, vim will filter the selected lines through sort, and thus sort them. This can also be used for grepping, cutting, tring, etc. or even to make computations: type the computation, select it, and type !bc

Use :r! : it simply puts into the buffer the output of the command, for instance :r! ls *foo*.tex , :r! ifconfig.

Edit over ssh

A very nice feature is this:

vi scp://foo//etc/hosts

which copies the file via scp, edits it, and on write copies it back! It's a killer feature with vimdiff:

vimdiff scp://{foo,bar}//etc/hosts

Indentation

Indentation can be a nightmare when you are working on several projects with differing coding styles (tab vs spaces, number of spaces, etc.). Two options are possible:

Once configured, one can apply the indentation by using = .

Opening files

Of course, one can just put files on the command line: vim file1.txt file2.txt , or even vim $(grep -rl boo .)

Using the -o or -O allows to open them alongside.

One can also specify where to go inside the file: vim file1.txt +10

From inside vim, one can open another file by using :e thefile.txt . It can be very interesting to install a fuzzyfinder plugin to be able to make file name mistakes :)

One can also rather browse files, by using vim . and then use gf to open the file whose name is under the cursor (or alternatively ^W f to open in a splitted window.

Git

The Vim-fugitive plugin allows to integrate git in vim.

This is very convenient to browse inside git annotate: while you are editting a file, type :Gblame, which opens a split on the left with the git annotations. Typing o or p on an annotation line will open the corresponding patch as a new split at the top. Typing - reruns blame, but at the revision of the current line ; typing P reruns blame at the revision just before that of the current line, thus allowing to pass through the commit.

:Gdiff is a very convenient alternative to git diff since it uses the vimdiff output.

:Gstatus shows git status of course, but it contains shortcuts: - to add/reset the changes (or p to go through hunks)), D to see the differences as a vimdiff (or dp to get it as a patch), and eventually cc (resp. ca)to commit (resp. --amend).

To be continued

...


Copyright (c) 2011-2017, 2020 Samuel Thibault

This text is available under the Creative Commons Attribution-ShareAlike Licence (V3.0), as described on http://creativecommons.org/licenses/by-sa/3.0/ and whose full text is available on http://creativecommons.org/licenses/by-sa/3.0/legalcode . Contact me if the ShareAlike clause poses problem.