TextMate — the missing editor for Mac OS X

To enable the functionality offered for a given file type, it is important that TextMate actually detects it.

In this post I will go through the 3 steps used to detect your file’s type and then answer the question of how to make TextMate automatically recognize rspec files (for those who have bound .rb to Ruby on Rails).

Finding the File Type

TextMate will go through 3 steps to figure out the type of your document, the first step that produce a result, will be used:

Check if you have a manual binding to the current file’s extension. Each time you use the language pop-up in the status bar to change the type of the current file, you make a manual binding. For example if you open test.h and change the language from C to Objective-C++ then you manually bind all .h files to be of type Objective-C++. You can inspect your manual bindings by running the following line from Terminal:

If you wish to get rid of all your manual bindings you can run the following line (while TextMate is not running):

defaults delete com.macromates.textmate OakLanguageFileBindings

Check if the first line of the file you open matches any of the first line patterns in the various language grammars.

For example if you select Bundles → Bundle Editor → Edit Languages… and locate the Ruby language grammar you will find that it has the following line:

firstLineMatch = '^#!/.*\bruby\b';

This is so that files starting e.g. with the following, will be recognized as Ruby files (despite extension):

#!/usr/bin/env ruby -wKU

Path (suffix) comparison. The last check, but most commonly used, is to compare the file types specified for each grammar, against the suffix of the file you open. Again if you open the Ruby grammar you will find this line in its language grammar:

So if you open test.rb it will see the rb extension and pick Ruby as the language grammar. This extension match is actually a broader suffix match, but it needs to be anchored either at a period, slash (path separator) or underscore. So this means that you can, as file type, give .ssh/config or spec.rb.

Changing the Defaults

Generally the way to change the default binding is to use the language pop-up in the status bar.

E.g. if you open test.rb and the status bar shows Ruby, but you are working with Ruby on Rails, then you should select Ruby on Rails from the status bar to associate all .rb files to Ruby on Rails. Presently there is no way to make the binding only for Rails projects, but as the Ruby on Rails grammar is a superset of the Ruby grammar, it shouldn’t be that big a problem.

Recently though, RSpec files have entered the scene, and these also use an .rb extension. Though the entire name will have a _spec.rb suffix, and the RSpec grammar does match that, so out-of-the-box if you open test_spec.rb (and have the Ruby RSpec bundle installed) then you will see RSpec in the status bar.

The problem appears if you have manually bound .rb to something, as we just did above in the example. Then when you open test_spec.rb TextMate will treat the file according to your manual binding (which says it has an .rb extension, and thus is Ruby on Rails).

So the trick to overcome this problem is to not do a manual binding for .rb files (if you want _spec.rb files identified as RSpec).

If you already did such manual binding you should be able to either:

Delete all your manual bindings with:

defaults delete com.macromates.textmate OakLanguageFileBindings

Open /tmp/test.rb and switch language back to Ruby. Since your manual binding is now the same as what TextMate would do by default, it records no binding at all. You can inspect the manual bindings recorded as shown at the start of this post.

When you have cleared the manual binding, then pick Bundles → Bundle Editor → Edit Languages… and add rb to the Ruby on Rails grammar’s fileTypes array so that it reads:

fileTypes = ( 'rxml', 'rb' );

Additionally remove rb from the Ruby grammar’s fileTypes array, so that there is no ambigiouty about which language owns the rb extension.

After doing these two steps, try test the bindings by looking in the status bar of the document which opens when you run these two commands from the Terminal:

11 Comments

I think my other comment got swallowed in the ether… if there is two posts, I apologise.

Thanks Allan for this, it is perfect!

I have never gotten such great support from a software product before. Allan loves his product and it really shows in the help he gives his users.

Why am I saying this?

Yesterday I had an annoying problem, that was, Textmate wasn't remembering that some of my files were RSpec and some were Rails… every file change with Ctl-Shift-Down was followed by a Ctl-Escape to change the file binding.

Frustrating.

I went into IRC, asked around and Allan came back and fixed my problem then and there! He also said there would be a blog entry on the page.

Well, in under 12 hours, there is the blog entry! With full details on how and why the fix works.

This is the second time I was helped directly by Allan to fix, really, was a configuration error on my end.

If you are thinking about buying Textmate, just do it! It will be the best investment to your ability to produce ever!

When I go into the Ruby language definition, and erase the 'rb' suffix from the fileTypes array, it doesn't get saved. When I quit and reopen Textmate, the 'rb' is still listed at the start of the array. Any clues?