TextMate and links, again

Last week I mentioned a lost post (my stupidity, not the fault of any software) in which I described how I set up TextMate to do reference-style links in Markdown. I had planned to redo the post the next day, but life and work got in the way. I hope the post is better for having sat in the back of my head for a week.

The setup consists of:

  1. A command, written in Perl, that takes some text and outputs a TextMate snippet with tabstops before and after the original input text.

  2. A macro that selects the text from the current caret position to the end of the file and passes that text to the command described above.

Here is the command:


$text =~ s/([\$\\`])/\\$1/g;
print '[${1:description}][${2:id}]$0'. $text .
      '[${2:id}]: ${3:http://}' . "\n";

To make it available to TextMate, open the Bundle Editor (you’ll find it in the Window menu), create a New Command from the + popup menu near the lower left corner, and paste in the text you see above. The Save option should be set to Nothing, the Input option set to Selected Text or Nothing, the Output option to Insert as Snippet, and the Scope Selector option to “text.html.markdown.” Give the command a name—I call it “My Link.” When you’re done, the Bundle Editor window should look like this

(Click on any of the screenshots in this post to see the full-sized version.)

To create the macro, you need to have a file open and set to the Markdown language, which you choose from the Language popup menu in the status bar at the bottom of the indow. It helps if you start with some text in the file and the caret somewhere before the end of the file. Then

  1. Choose Start Macro Recording from the Automation menu.
  2. Hold down the Command and Shift keys as you press the Down Arrow key. This will select from the current caret position down to the bottom of the file.
  3. Choose the My Link command from the “gear” popup menu in the status bar. This will run the command and insert the tabstop placeholders at the caret and at the bottom of the file.
  4. End the macro by choosing Stop Macro Recording from the Automation menu.
  5. Use the Undo command to get rid of the tabstop placeholders and deselect the text.
  6. Choose Save Scratch Macro… from the Automation menu. Give it a name—I chose “My Link” again because commands and macros are allowed to have the same name—move it into the Markdown section, set the Scope Selector option to “text.html.markdown,” and give it a Key Equivalent or Tab Trigger activation. I chose a Key Equivalent of Control-Option-Command-L.

When you’re done, the Bundle Editor window should look like this

Now hitting Control-Option-Command-L will stick a template for reference-style links into your document and you’ll be able to tab from one field to the next as you fill out the template. The last tab will take you back to where you left off typing.

As an example, I’ll show you what this document looked like when I got to this point and I wanted to enter this link.

Immediately after hitting the Key Equivalent sequence it looked like this, with the snippet inserted and the link text preselected:

After entering the link text and hitting the tab key the link reference ID is selected:

After entering the reference ID and hitting the tab key we bounce down to the bottom of the file, where the reference ID is already filled in for us and the URL excerpt is selected:

A final hit of the tab key after entering the URL put the caret back at the end of the link and I could continue typing. I should mention that this system works best if you stick a blank line or two at the end of your file before entering any links. This keeps the URLs in their own little section at the bottom of the document.

This setup was based on suggestions made by Charilaos Skiadas and Allan Odgaard in response to a question I posted on the TextMate mailing list. I thank them for helping make my workflow a little smoother.

Update: The ever-helpful Haris Skiadas (who should probably be working on his thesis instead of haunting the TextMate mailing list) mentions in the comments that the source of the command is saved in the macro, so you can delete the command after the macro is saved. One consequence of this is that the macro runs the command as the command existed at the time the macro was recorded. If you go back and edit the command, you’ll have to re-record the macro to get it to run the new version of the command.