TextMate

By: James Reynolds - Revised: 2014-01-23 richard

Introduction

TextMate is 2 years old (this month). It was created based on the desire for a Mac OS X like vim/emacs editor.

TextMate 1.5 won the Apple Design Award for best developer tool in 2006.

Notable features, some of them unique to TextMate, include tab completion, folding code, flexible text editing, shell integration, and an extensible bundle system that allows you to record macros, snippets, add language coloring, templates, commands, and more.

BBEdit is a truly Mac application. It has windows, buttons, preferences, documentation, and a company to back it. TextMate is a UNIX application. It has commands, plugins, configuration files and a community to back it. Of course, I’m simplifying a bit but, at much every level, from feature set to interface through support, both applications come from two very different worlds. In that, they will appeal to different users.

by Francois Joseph de Kermadec (emphasis added by James Reynolds)

TextMate’s history is fairly interesting. When it was first released, it couldn’t print and didn’t have preferences. It got some very colorful reviews.

TextMate’s Ruby and Ruby on Rails bundle support is exceptional because most of Rails’ core developers use Macs and TextMate including the Rail’s creator.

The author of TextMate is a guy in Denmark who is actually a few years younger than me. Boy I feel old… Anyway, and before he started using OS X in 2001, he was an Amiga user. In my book, that says a lot.

Another really cool thing about TextMate is the abundance of information about it. It has help files, it has its own WikiPedia page, and there are many screencasts that can be watched, or if you follow along, serve as valuable training materials.

I followed along when I watched them, even if I didn’t know anything about or care about the language being discussed (LaTeX). At first, of course, I just watched them to see if it would even be worth my time. But after I was convinced, I followed along, and now feel confident that TextMate isn’t really that hard, and I can give a decent presentation about it, even if I’ve barely even used it.

Notable Features

Here is a rundown of the non-bundle notable features
  • Clipboard history
  • Text editing (Edit menu)
    • Freehand mode, overwrite mode
    • Select word, line, paragraph, scope, etc.
    • Column selection - select the columns you want, then press option key. Anything allowed with a normal selection is possible with a column selection.
    • Text Completion (esc key)
    • Move selections (located in Text menu)
  • Regular-expression-based search and replace
    • $1 instead of  in replace
  • Folding markers (View menu)
  • Shell integration (Text menu)
    • Execute line (ctrl-r) and replace (ctrl-opt-r)
    • Filter through command
  • WebKit-based html view window (cmd-opt-ctrl-p)
  • Function pop-up (bottom right of window)
  • Project support with tabbed views
  • Text pairing - “{[()]}” (creating and deleting) Selecting text and then pressing one of those keys will pair the text as well.
  • Command line tool: mate

Problems

Here are some problems
  • Undo reverts changes letter by letter, rather than a set of changes
  • TextMate does not have built in (S)FTP support, but works through a client app (like Transmit)
  • Large (many megabyte) files can slow TextMate considerably
  • Editing files on a remote filesystem can stick TextMate because it polls
    (if I understand the issue correctly)
  • No way to recursively search a directory, only open files or an open project

Bundle Features

So most of the features that ship with TextMate are pretty standard text editing stuff. If BBEdit lacks the features, then they shouldn’t be hard to add. So based on the preceding features alone, TextMate is just a nice editor. What makes it stand next to BBEdit and hold its own are TextMate’s bundles.

TextMate ships with 36 bundles. There are some about 88 other bundles that can be downloaded. The shipping bundles include programming languages like ActionScript, AppleScript, C (includes C++), CSS, HTML, Java, JavaScript, LaTeX, Markdown, Objective-C, OpenGL, Perl, PHP, Python Rails, Ruby, Shell Script, SQL, Subversion, Textile, XML, and YAML.

Some “other” bundles that ship with TextMate include for Apache, Blogging, Diff, Mail, Math, PHPDoc, Property List, Source, Text, TextMate, TODO, Transmit, Web Searches, and Xcode. I’m still not sure what all of these do. But I’m assuming Apache deals with Apache config files, Blogging allows you to easily blog, Math includes stuff to make math easier to perform on the spot (a built in calculator?), etc. For example, if I select the text “1 + 1” and choose “Evaluate Selection” in the Math bundle, I get “1 + 1 = 2”.

To choose “Evaluate Selection”, I can click on the action button at the bottom of the editor window, click the “Bundles” menu, “Math”, then “Evaluate Selection”, or press ctrl-shift-C, which will open a popup of several math commands, and I can choose the one I want. The keyboard shortcut is called a key equivalent. Any key can be a key equivalent, even “return”. And using return for a key equivalent actually makes sense when used with scopes, which I’ll show shortly. The final way to activate a bundle item is with a tab trigger (hitting the tab key after typing some letters).

If you can’t remember the key equivalent, tab trigger, or there just isn’t one, you don’t have to go to the menus. Just use cmd-ctrl-T to open a search box and type in the command you want.

Each bundle represents a collection of language grammars, commands, macros, snippets, preferences, and file templates. “Evaluate Selection” is a command, and with the Bundle Editor, I can see exactly what it does, this:

printf " = %s" `{ tr -d ,; echo; } | bc -l`| perl -pe 's/(.[^0]+)0+$|.0+$/$1/'

Wow. Ok. So here are descriptions of the things that come in bundles.

Language Grammar

As you are probably aware, most quality text editors can colorize code. To colorize code, the application has to be able to read it and know what is a string, a comment, a language reserved word, a variable, a block of code, etc. The way TextMate does this is with language grammars.

You can define your documents grammar in a popup at the bottom left of the file. If I were to change this file’s grammar to php, then the following text will be colorized:

<?php

for ( $n = 0; $n < sizeof($someArray); $n++ ) {
  print $someArray[$n] . "<br >";
}

?>

Here is an example of the AppleScript language definition file:

{   scopeName = 'source.applescript';
    fileTypes = ( 'applescript', 'script editor' );
    foldingStartMarker = '(?x)
        ^s*
        (tell s+ (?! .* to) .*
        |using s+ terms s+ from s+ .*
        |if .* then .*
        |repeat .*
        |( on | to ) (?!s+ error) .*
        |try
        |with s+ timeout .*
        |script .*
        |( considering | ignoring ) .*
        )s*$
    ';

I can’t tell you exactly what this does, but it looks like it finds tell, using, if, repeat, on or to, try, with, script, and considering or ignoring` and then sets that as the start of a code block. I hope that makes sense. If you’ve written a parser or studied them, then it should make sense.

Scope

The language grammar does something else important for TextMate. It sets the scope. The AppleScript example above sets the scope to source.applescript. Scope is basically giving each type of code a name, like source.applescript. Using the name as part of a trigger qualifier, it is possible to do certain actions only when your cursor is in a particular scope.

A perfect example of this is shown in a screencast that shows how to get the return key to make C comment blocks very easy. For example, here is a common way to notate a comment block:

/*
 *
 *
 */

Well, if I pressed return in after the first line, I would get this:

/*

 *
 *
 */
 
By redefining the return key to print this instead:

*

It is possible to get this by just pressing return repeatedly:

/*
 *
 *
 *
 *
 *
 *
 */

Outside of the comment block, the return key does its normal thing.

You can find your scope anywhere by pressing ctrl-shift-p.

Commands

The “Evaluate Selection” I showed above was a command found in the Math bundle. That is exactly what a command is, a script. The scripts can be in any language you want, but default to shell.

It has some really cool features besides just running scripts. You have these choices for input to the script: the whole document, nothing, or selected text. If you choose selected text, if you have no selection, you can instead use character, word, line, paragraph, scope, or document. That is some powerful input options.

Then it has various output options: discard, replace selected text, replace document, insert as text, insert as snippet, show as html, show as tool tip, and finally create new document.

So a command can be a simple: say hi or it can be pages and pages of code that searches Google for th, parses the output of the Google results, and then replaces the text you had selected with a link to the first hit that Google finds. For example, a script that does this would take the selection “James Reynolds” and convert it to: “James Reynolds”. Unfortunately, that isn’t my webpage. :’(

Anyway, there is already a command to do this in the HTML bundle:

#!/usr/bin/env ruby
require "#{ENV['TM_SUPPORT_PATH']}/lib/progress.rb"
require 'net/http'
TextMate.call_with_progress("Asking Google for the link") do
  phrase = STDIN.read
  response = Net::HTTP.get_response(URI.parse(URI.escape("http://www.google.com/search?q=#{phrase}&btnI=I'm+Feeling+Lucky")))
  url = response.to_hash['location']
  print %{<a href="#{url}">#{phrase}</a>}
end

If you remember earlier I mentioned that there are many TextMate users who use Ruby. That will explain why many of the commands in TextMate are programmed with Ruby.

Drag Commands

Drag commands are just like commands, but are activated when you drop a file into an editing window. You specify the file extension that triggers the command. The output is always “Insert as snippet”.

Snippets

Snippets are pieces of text to include into your document. This is kinda the compliment to command. Command will run a script and can insert text. A snippet is just plain text that is inserted. And it can execute commands and variables.

Snippets are activated just like everything else in a bundle, a tab trigger or key equivalent. I believe all of them will have scopes that limit when they are activated. This way, you can have the same tab trigger in HTML as Java, and they produce totally different snippets.

Macros

Macros are recordable actions that can be saved and played back. To start and stop recording: alt-cmd-m, to playback: opt-cmd-m, to save ctrl-cmd-m.

Saved macros can be activated just like everything else (tab triggers, key equivalents).

Templates

Templates are like commands, except they take no input, and the only output is a new file.

Preferences

Preferences tells TextMate to change its text editing behavior when using different bundles. For example, different languages use different keywords to indent code. A preference would tell TextMate what those are. Same goes with text pairing: “{[()]}”. That can be defined in a preference.