[TxMt] A Hack to Handle Files that Mix Tabs and Spaces for Indentation

Kornelius Kalnbach murphy at rubychan.de
Mon Nov 20 16:43:23 UTC 2006


hi list!

I may have found a workaround to solve this old problem:
http://one.textdrive.com/pipermail/textmate/2004-December/002039.html


PROBLEM

Sometimes, coders choose to use an indentation width different from the
(hard) tab width. An example C file may look like this:

static VALUE
rb_str_insert(VALUE str, VALUE idx, VALUE str2)
{
[4 SPACES] if (pos == -1) {
[TAB] pos = RSTRING_LEN(str);
[4 SPACES] }
[4 SPACES] else if (pos < 0) {
[TAB] for(i=pos;i--;) {
[TAB][4 SPACES] ...

Emacs and Vim allow this (eg. :set sw=4 ts=8). Of course, nobody should
use this, but there *are* some codes in that style (notably the Ruby
source code), and I want to use TextMate to edit them.

Changing tab width doesn't work here:
- setting it to 4 spaces makes the code unreadable;
- setting it to 8 spaces makes automatic indentation indent everything
   twice as deep as the original code, thus breaking the style.

Converting all the tabs would break the version history and make diffs
harder.


SOLUTION

So I wrote two little Ruby one-liner commands to convert back and  
forth between
both styles.

Convert TAB -> 8 SPACE:
"${TM_RUBY:=ruby}" -pne 'gsub(/^\t+/) { " " * 8 * $&.size }'

Convert 8 SPACE -> TAB:
"${TM_RUBY:=ruby}" -pne 'gsub(/^ {8}+/) { "\t" * ($&.size/8) }'

Both:
   Input: Selected Text or Document
   Output: Replace Selected Text
   Activation: Option-Command-X

When I have a code like the one above, I just:
- set the tabs size to Soft-Tabs: 4,
- use "Convert TAB -> 8 SPACE",
- edit, compile, and test with spaces only
- convert it back with "Convert 8 SPACE -> TAB" before a diff or commit.

I think this covers most cases; you can easily modify the commands to
your needs.

LIMITATIONS

Of course, the scripts don't handle cases where you explicitely want  
tab or spaces,
like in heredocs or something. Your version system should save you.  
Or you can
select only the part you want to convert and run the commands on it.

Oh, and I didn't test it much yet. But it seems to work ;)

I hope this makes Patching Ruby easier for TextMate users!

Enjoy :)
[murphy]



More information about the textmate mailing list