Secrets of tabs in vim
Started: 2008-01-17 19:30:47
Submitted: 2008-01-17 21:00:08
Visibility: World-readable
I spend much of my day working on other people's code. People who have uncivilized ideas about how to indent their code. (Given some of the code I've seen, I sometimes think I should be simply pleased that they bothered to indent their code at all.) Until civilization aligns and we finally have elastic tabs, I'll have to deal with different tab styles. The popular ones tend to be:
- Tabs are eight columns wide. Each indentation level is one tab. (Popular with the Linux kernel.)
- Tabs are four columns wide. Each indentation level is one tab. (Popular with Windows developers using Visual Studio.)
- Each indentation level is four spaces. Tabs are not used. (Popular with Java programmers.)
I've seen some especially ... creative tab styles not listed above, including code indented with various innovative mixture of tabs and spaces. Out of the box, my favorite text editor (vim and its gui cousin, gvim) will default to indent using eight-column tabs, but vim can handle any (consistent) indentation style I've seen using four easy commands: tabstop, shiftwidth, expandtab, and softtabstop. (Each command listed below has links to the vim documentation for more details.)
tabstop
Set tabstop to tell vim how many columns a tab counts for. Linux kernel code expects each tab to be eight columns wide. Visual Studio expects each tab to be four columns wide. This is the only command here that will affect how existing text displays.
expandtab
When expandtab is set, hitting Tab in insert mode will produce the appropriate number of spaces.
shiftwidth
Set shiftwidth to control how many columns text is indented with the reindent operations (<< and >>) and automatic C-style indentation.
softtabstop
Set softtabstop to control how many columns vim uses when you hit Tab in insert mode. If softtabstop is less than tabstop and expandtab is not set, vim will use a combination of tabs and spaces to make up the desired spacing. If softtabstop equals tabstop and expandtab is not set, vim will always use tabs. When expandtab is set, vim will always use the appropriate number of spaces.
Indentation in the real world
Putting it all together, the following incantations will configure vim for each of the cases listed above:
- Tabs are eight columns wide. Each indentation level is one tab. (Popular
with the Linux kernel.)
:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab
- Tabs are four columns wide. Each indentation level is one tab. (Popular
with Windows developers using Visual Studio.)
:set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab
- Each indentation level is four spaces. Tabs are not used. (Popular with
Java programmers.)
:set softtabstop=4 shiftwidth=4 expandtab
Just to prove it's possible, here are some more ... creative indentation styles and their vim representation:
- Tabs are eight columns wide. Each indentation level is three columns,
which may be spaces or tabs.
:set tabstop=8 softtabstop=3 shiftwidth=3 noexpandtab
- Tabs are five columns wide. Each indentation level is six columns,
which may be spaces or tabs.
:set tabstop=5 softtabstop=6 shiftwidth=6 noexpandtab
... you get the idea.
Remembering these settings
So how do you make vim remember what indentation to use for all of your files? vim will read your personal startup file every time it runs; you can put your favorite indentation incantations there. (That's ~/.vimrc on Unix; $HOME/_vimrc on Windows. In gvim, you can click Edit -> Startup Settings to quickly edit this file.) On the opposite end of the spectrum, you can add special incantations to each file you edit, which will override the settings vim reads from elsewhere:
/* vim: tabstop=8:softtabstop=8:shiftwidth=8:noexpandtab */
(Obviously, wrap the text in your favorite comments to make sure your compiler doesn't try to compile the vim incantations.)
vim will also read .vimrc in the current directory (when the exrc option is set in your normal vimrc), which is useful when editing large numbers of source files in the same directory, or to avoid corrupting source files you don't control.
Visualizing tabs
So what do you do when you open a new source file and you're trying to figure out what tab style the last author used? (And how do you make sure you're doing the Right Thing to avoid mixing tab styles in your new code intermixed with the old code?) I find syntax highlighting useful. In gvim, I like seeing my tabs with underlines. (This tends not to work well on the text terminal for reasons I haven't been able to determine.) The following incantation will tell vim to match tabs, underline them in gvim, and highlight them in blue in color terminals:
syntax match Tab /\t/
hi Tab gui=underline guifg=blue ctermbg=blue
You can't just throw this into your .vimrc and expect all to work, though, because vim will flush its syntax highlighting rules when it loads new files. To hijack this process, add syntax files for your favorite languages in $HOME/.vim/syntax/. For C, the syntax file is c.vim. (Look in $VIM/syntax for a list of existing files.) vim will load the system-wide syntax file and then run your custom file, and you'll be able to visualize your tabs every time you load a C file.