Tabs vs Spaces and Elastic Tabs
Tags: programming.tabs vs spaces, programming.elastic tabs
I was surprised to discover I’ve not written about “tabs vs spaces” before, despite all my love for writing about editors.
What’s “Tabs vs Spaces” All About?
The less something matters, the more programmers will argue over it. (No, not
“bikeshedding”, which is similar, but doesn’t quite account for things like
programmers arguing over different programming languages.).
Grammarians are similar, I suppose.
The biggest part of this ‘holy war’ consists of people arguing over whether
it’s better to indent with tabs or spaces. Roughly (and without any bias):
if you indent with spaces, then you know that it anything aligned will still be
aligned on another computer; but, people will have different preferences as
to whether to indent with 2-spaces, 4-spaces, or some other size.
Tabs let you change the size of indentation, so when using tabs to indent,
people can set the tabwidth to how they prefer it. The chief downside to this
is you can’t use tabs to align things, because aligning means you want
certain characters to be in the same column, which fixes the tabwidth.
– The middle ground to this is often called “mixed”: use tabs for indentation, and spaces for alignment.
Practicality
There are some practical problems about this, too:
Setting up “mixed” tabs/spaces in an editor isn’t as easy as only-spaces or
only-tabs.
Even using tabs-only can be messy, since it’s not always clear whether pressing
the Tab key on a keyboard will insert spaces or a proper tab; so a poorly
configured editor may insert spaces into what was previously a tabs-only file.
Modern editors are pretty capable at treating ‘4-spaces’ as if they were a
single indentation character: pressing a Tab key will insert 4 spaces, and
pressing backspace will delete 4 spaces.
Working on teams, it’s important for everyone to follow the same code style.
– I’ve heard stories of my friends where there was a sequence of commits which
were purely for tabifying or untabifying the codebase.
And, obviously, the diffs shown between these changes simply show “THE WHOLE
FILE WAS DELETED, THE WHOLE FILE WAS CREATED.”.
Why This is Whole Thing is Dumb
One of these programming ‘holy wars’ is dumb? You don’t say!
But, still.
HTML/CSS manages to separate content from form. - CSS Zen
Garden is a notable example of the exact same
content being displayed very differently with different themes.
– While some languages currently make use of whitespace/alignment as part of
syntax (famously Python, jokingly whitespace, but also even things like Haskell
[in places]), most don’t. – So, it’s kindof dumb that something which doesn’t
affect content is treated as content by tools. (Well, tools like Git will offer
to ignore whitespace changes in diffs; but, again, tools can be difficult to
use.).
For that to work, you’d have to have some program to decode from a neutral
source file so that it’s displayed how a programmer likes in an editor (2-space
indent or 4-space indent; braces aligned in the same column; spaces between
declarations; etc. etc.), as well as some program to encode to the source file
in a neutral layout. – This is just pie-in-the-sky, of course, and it’s not
hard to come up with cases where this wouldn’t work. (e.g. comments, which the
programmer may prefer not aligned relative to the syntax.).
Tabs and Tabstops
But, *gasp*, I have been a little biased in my description:
The simplest way to use tabs is strictly at the start of a line for
indentation. If used in the middle of a line, different people/programs have
different opinions as to whether the correct thing to do is to skip
tabwidth spaces, or to align to the nearest 8th column.
– To me this sounds stupid; when I was using org-mode, I noticed it used tabs
after some text as a placeholder for spaces: Emacs insisted on tabwidth being
8, while a Vim plugin insisted on tabwidth being 6.
Yet, both of these are bastardisations of the “tabstop” as used by
typewriters.:
The “tabstop” was a position set so than when pressing the ‘tab’ key, the paper
would align to that point. This helped to write Tables. (TABle, TAB).
Tab stop bar: |------V-----------------V------| Typing: Dear Sir, We are pleased to offer: French Vanilla $12.00 English Custard $ 8.50 Irish Whiskey $22.40 Sincerely, Bramble & Botts Dairy
Elastic Tabstops
I first saw mention of elastic tabstops on Neovim’s issues page.
Elastic tabstops are much closer
in spirit to aforementioned typewriter tabstops.
The GIF perhaps explains the concept best:
Although, as far as “implementation”, it seems to just render current tab(s) differently:
While editors which haven’t yet implemented the elastic tabstops mechanism may not align some text properly in files where tabs were used with elastic tabstops, the problem isn’t that bad. All leading tabs (indentation) will be okay, and the chances of text not aligning correctly diminishes as the width between tabstops increases. So if you plan on switching to elastic tabstops in the future, and wish to choose a code style with that in mind (to use now), I suggest using tabs with fixed tabstops every 8 characters (or more) across. Alternatively co-workers can use tabs with fixed tabstops of whatever size they like as long as no one tries to line up text for anything other than indentation.
Drawbacks
It seems the idea was conceived in 2006. It’s 2015. That said, Neovim is in theory going to be easier to contribute to than Vim. And it has already been implemented in some array of text-editors.. so the discipline isn’t impossible.
But this StackExchange thread makes some excellent points:
Personal preference
Technical implementation: It’s different to what most text editors have done, and isn’t widely available. This limits adoption.
Who cares?: Developers have done well enough as-is for the last however many years; people can set aside subjective disagreements if they really need to, anyway.
Impact: Compare the quote above; using leading tabs for indentation is pretty much the same behaviour as elastic tabstops; and the other adjustments aren’t all worth the novelty.
Corner cases: Considering the Python snippet:
python def foo( bar, xyzzy ): wibble()
it’s probably something elastic tabstops will mess up, without code intelligence.
– For what it’s worth, I still don’t see this as inherently more natural than the “mixed” solution.
Even so, it appears that elastic tabstops are the kind of thing which could be adopted into codebases iteratively. (I imagine this would look ugly for tools which don’t support elastic tabstops; but the same is true if a programmer assumes tabwidth to be a certain value anyway, so it’s not like the issue would be new.).