Close and Go BackBack to Viget

Out, Damned Tabs

David Eisinger
David Eisinger, Web Developer, April 09, 2009 9

Like many developers I know, I’m a little bit OCD about code formatting. While there are about as many ideas of properly formatted code as there are coders, I think we can all agree that code with tabs and trailing whitespace is not it. Git has the whitespace = fix option, which does a fine job removing trailing spaces before commits, but leaves the spaces in the working copy, and doesn’t manage tabs at all.

I figured there had to be a better way to automate this type of code formatting, and with help from Kevin McFadden’s post, I think I’ve found one, by configuring TextMate to strip off trailing whitespace and replace tabs with spaces whenever a file is saved. Here’s how to set it up:

  1. Open the Bundle Editor (Bundles > Bundle Editor > Show Bundle Editor).
  2. Create a new bundle using the “+” menu at the bottom of the page. Call it something like “Whitespace.”
  3. With your new bundle selected, create a new command called “Save Current File,” and give it the following settings:

    • Save: Current File
    • Command(s): blank
    • Input: None
    • Output: Discard
  4. Start recording a new macro (Bundles > Macros > Start Recording).
  5. Strip out trailing whitespace (Bundles > Text > Converting/Stripping > Remove Trailing Spaces in Document).
  6. Replace tabs with spaces (Text > Convert > Tabs to Spaces).
  7. Save the current document (Bundles > Formatting > Save Current Document).
  8. Stop recording the macro (Bundles > Macros > Stop Recording).
  9. Save the macro (Bundles > Macros > Save Last Recording). Call it something like “Strip Whitespace.”
  10. Click in the Activation (Key Equivalent) text field and hit Command+S.

Alternatively, we’ve packaged the bundle up and put it up on GitHub. Instructions for setting it up are on the page, and patches are encouraged.

How About You?

This approach is working well for me; I’m curious if other people are doing anything like this. If you’ve got an alternative way to deal with extraneous whitespace in your code, please tell us how in the comments.

Kevin McFadden said on 04/09 at 12:46 PM

Just a heads up for the (occasional/rare) problems with this method.  Every now and again you will experience either your entire file duplicated multiple times within the document (not sure if it is related to having highlighted text while saving or not), or TextMate not being able to save anything at all, requiring a TM restart.  YMMV.

Jerry Cheung said on 04/09 at 04:25 PM

I think the most helpful thing I did was to chat with my coworkers about their coding style.  By yielding a little bit to everyone’s style, we end up with readable code that everyone is happy with.

I use emacs, and whenever I see some poorly indented legacy code, I run the following function:

;; http://www.emacsblog.org/2007/01/17/indent-whole-buffer/
(defun iwb ()
“indent whole buffer”
(interactive)
(delete-trailing-whitespace)
(indent-region (point-min) (point-max) nil)
(untabify (point-min) (point-max)))

David Eisinger said on 04/09 at 04:33 PM

Kevin - I’ve run into that first problem you described a few times, but it seems to go away if I make sure there’s an empty line at the end of the file.

Jerry - You’re right, the best solutions are probably non-technical :)

Andy Jeffries said on 04/10 at 11:11 AM

“I think we can all agree that code with tabs”

Err, no, we can’t!  I prefer tabs and for good reason…

For example, enforcing that 2 spaces for tabs* is the one true way means that others who prefer their code more spaced out can’t operate comfortably.  If you actually use tab characters it can be configured in the editor to display with your preference.

The only problem comes to continuation lines.  In that case the answer is tab for indentation to the block level, then spaces to replace each character to line up with the line above.  For example:

{tab} if (foo ...
{tab} bar ...

Tabs aren’t evil, they’re useful in allowing developer flexibility while maintaining consistency.

* Personally I use a 2 space per tab indentation level for Ruby.

Jerry Cheung said on 04/10 at 01:38 PM

@andy For me, I just want the coding style to stay consistent within a project.  I don’t want to see a combination of real tabs, soft tabs (spaces), unix newlines, and dos newlines.  Pick one style, and make everyone stick with it.

David Eisinger said on 04/13 at 08:56 AM

Andy - You make a good point about allowing individual developers to view the same code differently, depending on personal preference. For me, it’s much more important that the code look the same across various platforms—TextMate, the terminal, GitHub, etc. You could use the same macro I described, substituting “Tabs to Spaces” with “Spaces to Tabs.”

Erik Ostrom said on 04/18 at 01:00 PM

I actually don’t like my editor to change a whole file’s whitespace automatically, because it makes it hard to interpret source code history. If I make a change that’s a few lines, but my editor also changes 90% of the whitespace in the file, it makes it harder for future developers to figure out what the actual change was.

I guess git diff and blame make it easy to ignore whitespace changes, so maybe I’m just being superstitious, but I’d still rather make whitespace changes in a separate, volitional commit.

I do turn off Emacs’s “indent-tabs-mode”, so that tabs never creep into code I’m editing in the first place. I assume most editors have an equivalent; what they all lack, I guess, is a remote facility I can use to configure everyone else’s editor to do what I want.

Mark Kahn said on 04/25 at 03:07 AM

Um, I -strongly- prefer tabs to leading spaces, and for a good reason.  I decrease my tab-width to two characters, and I know other people that prefer 4, I even know a person that has it set to 6.  Using leading tabs allows people to do whatever they want in this regard without affecting -anyone-.

I’ll go even further and be anal about how you should properly indent subsequent lines:

\t\t\tsomeIndentedFunctionCall(arg1,
\t\t\t........................arg2,
\t\t\t........................arg3);

where all the .’s are spaces.  Yeah, it seems weird but it’s the only pattern that allows indenting AND tab preferences to be preserved.

Hate me if you will, I’m right :)

Iaman said on 04/27 at 12:31 PM

Yeah, I gotta say, I don’t see where the tab hate is coming from.  I mean, it makes a lot more sense to me than putting spaces in, for a few good reasons:

1) Obviously, as has been pointed out, different people can view it differently by changing their tab-width.  This helps keep each person happy with the document without upsetting anybody else.

2) While this is a small thing, I feel it still warrants a bit of a mention: one tab takes up less space in a file than multiple spaces does.  Sure, it’s a very minimal reduction, but, hey, if you can get code looking good and taking up less bandwidth, why not?

3) Programmers have been using tabs for a very similar use for decades, I think they’re probably on to something.

Commenting is not available in this weblog entry.

We're the Developers

at Viget Labs. We write about web development trends, tips, best practices, industry events, and our projects — all with an emphasis on Ruby on Rails.

Contact Us

Have any questions, comments, ideas, or secrets to share? Let us know.


How many hours in a day?

Sorry, you need to have Javascript enabled to use this form. (Don't blame us, blame the spammers!) If you'd like to contact us, please visit our Contact page.