Recently I’ve found myself editing in excess of twenty source files concurrently; time to use a vim session so that I don’t need to specify the list of files again each time I start editing. Basic usage is simple.
vim firstfile then :e secondfile, etc. At any time after they’re all open, do :mksession! which will create a Session.vim file in your initial location. When you want to open up those same files again, use vim -S and you’re there. One great advantage of this is that :b8 for example, will always take you to the same file, even if you close and re-open that file — vim knows that you appreciate consistency and does its best to help.

However, there is one small mystery. Say you originally opened up a, b, c and then did :ls. You would see that a was buffer 1 and c was buffer 3. But when you re-open your session, you find that a is buffer 2 and c is buffer 4 — why no buffer 1? The answer is that vim kept buffer 1 for your headline file, but you specified none. I still find this a bit weird, but the working invocation is vim a -S. Now it has opened a as buffer 1 and all other files mentioned in Session.vim as the remaining buffers, so it looks again as it did originally.

Note that Session.vim contains a cd command (which you can edit of course) so you could keep several session files in your base location, relying on the individual session file to set you up in the appropriate destination. For example, have core.vim and plugins.vim in your home directory. Then let vim -S core.vim take you to the base directory for editing those files.

Note also that a huge degree of behaviour is configurable via the sessionoptions setting.


There are many situations in which you would like something to run each time you save a file (or a process modifies a file). Since linux kernel 2.6 this has been possible via the inotify mechanism. All you need is a client package for whichever language (bash, perl, ruby, python, …) you want to use.
For perl we have liblinux-inotify2-perl and for bash we have inotify-tools which I’ll illustrate here.

In this example, each time one of the specified files is saved (in vim), the script of unit tests will be invoked. This particular line uses the fact that vim implements a ‘save’ by way of ‘move, move, delete’, so we detect the first ‘move’…

sources="lib/Cari/Plugin/ lib/Cari/Plugin/"
while inotifywait -qqe MOVE_SELF $tests $sources; do ./$tests; done

This is useful in lots of examples where you want to quickly see the results of editing source file(s), for example editing LaTeX files.

(Update: My latest vim issues ‘MODIFY’ instead of ‘MOVE_SELF’, so you’ll want to test yourself using inotifywait filename.)

For vim I use a .vimrc that has taken a couple of years to be happy with. For example it sets tabs to be replaced by four spaces. However, there are files for which that is a bad idea. Makefiles won’t work unless the leading whitespace is a tab, and js and css files will be leaner if one tab is used instead of four spaces. I could make my .vimrc smart enough to do that, but that wouldn’t help others who might edit these files without the advantage of my .vimrc. Modelines solve the tabs vs spaces problem.

To set my main.css file so that tabs don’t get converted to spaces but still appear equivalent to four spaces, I can put this line at the end of the file.

// vim: ai:ts=4:sw=4:et!

I have to enable interpretation of modelines, especially if I want them to work for ‘root’.

set modeline
set modelines=2

which instructs vim to look at the first and last two lines to check for a modeline.
For my main.css example I could have used parenthesis style comments /* ... */ but these require use of set which in turn requires a different use of colons. This time interpretation terminates after the first colon following set

/* vim: set ai ts=4 sw=4 et!: */

This won’t change existing spaces, for which I might want to try

:%s/    /^I/g

where “^I” is actually <ctrl>+<v>,<tab>
Thus file-by-file I can choose whether real tabs should be used instead of spaces, while keeping spaces as my overall default.

When you’re paging through a long file with many similar lines, sometimes you want to jump to the first line that doesn’t match the current crop. For example, say you’re staring at lines and lines that begin “drop INDEX ” and you want to jump to the first line that doesn’t begin with that:

/^\(drop INDEX \)\@!

will get you there.