Tabs, spaces, and vim

General considerations

As we develop programs, it becomes mandatory for the sake of our sanity to structure our source code by indenting logical blocks with an homogeneous amount of whitespace.

// This is what a sane person would do
int main(void)
{
    if (42)
        puts("Don't panic, and carry a towel");
    return 0;
}

// Oh my god what is wrong with you?
int main(void)
{
if (42)
puts("Don't panic, and carry a towel");
return 0;
}

Among the grand family of programmers, we can observe two schools of thought: those who indent with spaces, and those who indent with tabulation characters ('\t', internally known as 0x09 for any self respecting charset).

The choice of your school is usually a matter of style, but it is nonetheless important to keep those principles in mind:

  • Use one or the other, not both.

  • Try to use the same style inside your team, of lest your source code becomes a nightmarish chimera.

  • never use anything else than 8 as the length of your tab character ('\t'). This is a de facto standard: a tab character means just enough whitespace to reach the next multiple of 8. Note that as we're talking about indentation and putting those tabs characters at the beginning of lines, we can simply consider that a tab character is defined here as a 8 characters symbol. What this implies is that if you join the Church of the Holy Tab, you vow to always indent by increments of 8, as any other value would mean mixing up tabs and spaces. You don't want that, do you?

  • In this article we are talking about indentation, not variable alignment. While two schools of thought exists for indentation, most people agree on spaces being the only sane option for variable alignment (that is, assuming you want to align your variable names in the first place. Seriously, who does that outside of school?). Some people (me included) consider that this ultimately means mixing spaces and tabs, and that would be evil™, hence the choice of spaces only.

Vim settings

Now that we're a bit clearer on the topic, let's see how to configure vim to make if reflect our religious faith.

There are four vim options that define how the editor will behave towards indentation:

  • expandtab: If this option is set, pressing the Tab key will trigger the insertion of a certain amount of spaces instead of the '\t' character. (As with every vim option, you can explicitly disable it by prefixing it with no, e.g.: noexpandtab)

  • tabstop: represents the length of the tab character ('\t'). As explained above, its default value is 8 and should never been changed. I'm only describing it for the sake of completude.

  • softtabstop: represents the amount of spaces inserted upon pressing the Tab key, assuming expandtab is enabled. Its default value is 0, which effectively means deactivating the option.

  • shiftwidth: represents the indentation level. Depending on the value of expandtab, vim will insert either spaces only, or a combination of both tabs and spaces (yuck!). Its default value is 8.

One important thing to note is that softtabstop and shiftwidth do not necessarily share the same value. That is, pressing the Tab key doesn't always insert the same amount of whitespace as the one automatically inserted via vim's indentation mechanism. As i personally don't find that behaviour desirable, I suggest setting shiftwidth to either 8, or the same value of softtabstop, depending on your faith.

Hence, supporters of the way of the space shall configure their editor thusly:

set expandtab
set tabstop=8 ; The default behaviour, just for documentation
set softtabstop=n
set shiftwidth=n

with n being left to the reader's discretion (I personally like 4).

Meanwhile, Chuch of the Holy Tab zealots shall use the following configuration:

set noexpandtab
set tabstop=8 ; Same thing, I'm only documenting the value
set softtabstop=0
set shiftwidth=8

Those lines are, as you can guess, to be inserted in your .vimrc.

Filetype specific indentations

As I said earlier, the choice of you indentation religion is usually left to you. Some languages though, have made that choice for you. make, for example, expects tabs in your Makefile and simply won't work with spaces. Another example is python, which while working perfectly fine with either, strongly recommends the use of spaces with an indentation level of 4 in the Pep 8.

So what happens if we chose spaces and have to edit a Makefile? Fear not, for vim can detect filetypes and override your options with suitable ones. That is, of course, assuming you have this essential line in your .vimrc:

filetype plugin indent on

This line tells vim to try and detect the filetype of the files being edited, and loads up filetype specific plugins and indentation rules. This is thanks to that rule that we don't have to manually set the indentation type with cindent, smartindent, lispindent, or whatever: it is automatically loaded upon filetype detection.

Note that we can -- and should! -- still set the following option:

set autoindent

as it only sets up a poor man's indentation (i.e.: copies the indentation level of the previous line) when a filetype hasn't been detected, as a fallback.

Conclusion

Because every blog post ever should finish on an humorous note, here is a funny image posted by eph3mereal on #vim@freenode:

 TabsSpacesBoth

Addendum: expanding on the "tabs are 8"

Upon publication, this article received mixed reviews, sitting currently at a perfect 50/50 ratio of upvotes/downvotes on reddit. It isn't hard to determine the reason of this, as almost every comment is about disagreeing with the third bullet point of this article, the "tabs are 8" one (All the remaining comments being about the horrid colorscheme used for the code samples. I'm going to change that, promise!).

This honestly comes as a bit of a surprise for me, as I initially thought that most people agreed on that topic. I wish I could consider that point yet another holy war, but I am clearly part of a minority here, making me *gasp* wrong on that point. Rather than editing out the polemic topic, I feel it is more honest to address the problem in an addendum.

What readers wisely remarked is that having a variable tabstop brings a very interesting feature to your code: the ability for everyone to view it as they prefer it. That means that if I'm a "indent by 2" kind of guy, I can code in a way that is respectful of my beliefs, while still pleasing the buddy I'm working with, who is a "indent by 4" dude.

I won't comment on that aspect because it is undeniably a very good solution to the problem of people having to work together, and provides much flexibility, making it a serious argument for the Church of the Holy Tab. While I am personally a way of the space guy and prefer having everyone see the same level of indentation, I can't deny that the other way is an entirely sensible and perfectly valid approach.

What I meant to say though, is that this feature would be perfect, provided that every software out there had the ability to change the tabstop.

I originally described the "tabs are 8" as a de facto standard. What that means is that, while this particular length is nowhere to be found in any official standard (that would be a de jure standard), earlier programs implicitly agreed to set that value to 8, with only a few of them providing a way to alter that. Thus, the fear was for your code to end up in the dirty hands of a legacy system that would forcefully display your indent level as 8. And 8 is kind of big, to be honest. Sufficiently big to become a bother for some people that don't initially realize that and write a code with ts=2 and multiple nested indentations. Only when they see their code displayed with the one and true value of 8 (I kid, I kid) will they realize what hellish fiend they released upon the programming world.

While not common, this problem can appear sometimes. A silly example would be my school's coding style, which forbids and punishes source code containing lines larger than 80 columns. The program checking that your source code is norm compliant (affectuously called the Moulinette), expands the tabs to 8 spaces during that check. Thus, each year we see a good chunk of students receiving a negative mark for their week long project, because they unknowillingly broke the coding style and were punished as such.

But all in all, I recognize that my point has been somewhat extreme, and as such will try and mitigate my faith from now on. I won't edit the article further though, as I feel it would be dishonest and that errors we make are not to be ashamed of, and should be discussed rather than hidden away.

I hope this addendum cleared some confusion towards my original point, and I wish you luck in your future religious practices.

Comments !