Lucky linking

Today I saw the TextMate Search and Hyperlink screencast, and was impressed with how the URLs for Markdown links were automatically inserted using Google’s “I’m Feeling Lucky” magic. “How the hell did they do that?” I thought. So I went to Haris Skiadas’s blog and saw what a clever bit of coding he’d done to make it work (Haris and clever are redundant).

Unfortunately, Haris used his genius for evil instead of good, as he had his code create inline links instead of reference-style links. I hate Markdown’s inline style of linking, because the inserted URL breaks up the flow of the text. I’ve already done three separate posts on creating reference-style links in TextMate, but now feel an acute need to do a fourth. incorporating an automatic URL. Here goes.

First, I made a command-line program, which I call glucky, taken almost verbatim from Haris’s post (I just broke up a couple of the long strings):

#!/usr/bin/env ruby

require 'net/http'

prefix = ""
suffix = "&btnI=I'm+Feeling+Lucky"
goodURL = URI.escape(prefix + word + suffix)
response = Net::HTTP.get_response(URI.parse(goodURL))
print response.to_hash['location']

I saved this file in my ~/bin directory, which is in my $PATH, and made it executable. Now if I type echo markdown | glucky into a Terminal session, it happily spits back, which means my little edits didn’t mess up Haris’s code. Good.

In TextMate, I opened the Bundle Editor and made three commands, one for running the glucky program on the selection and putting the result on the clipboard, one for bracketing the selection, and one for inserting a snippet.

Here’s the command for putting the “I’m Feeling Lucky” URL into the clipboard:

echo -n "$TM_SELECTED_TEXT" | glucky | pbcopy

In the Bundle Editor window, this command is set to take the Selected Text or Nothing as its Input and Discards its Output. I called it “glucky,” but its name isn’t important.

Here’s the TextMate command for bracketing the selection:

echo -n "[$TM_SELECTED_TEXT]"

As you might have guessed, I called this command “bracket,” set its Input to Selected Text or Nothing and its Output to Replace Selected Text.

Here’s the command for inserting a snippet:

use List::Util qw(max);

# Get the highest-numbered reference.
@nums = $text =~ /^\[(\d+)\]: /mg;
$n = max(@nums) + 1;
# Escape special characters.
$text =~ s/([\$\\`])/\\$1/g;
# Insert the snippet.
print '[${1:' . $n . '}]$0'.
       $text . '[$1]: ' . `pbpaste` . "\n";

I called it “Reference link selection lucky.” It has an Input of Selected Text or Nothing and an Output of Insert as Snippet.

If you looked at my previous posts on reference-style links, you’ll see that what I’ve done here is just a small variation on my previous work.

These commands are tied together with a macro. I opened a new text file, typed in the word that will act as the link (I chose “markdown”), added a few newlines to the end, and selected the link word. I then started recording a macro and did the following:

  1. executed the “glucky” command;
  2. executed the “bracket” command;
  3. pressed the rightarrow key to move the caret to the right of the closing bracket;
  4. pressed Command-Shift-downarrow to select from the caret to the end of the document;
  5. executed the “Reference link selection lucky” command.

I then stopped the recording and saved the macro in my Markdown bundle with the name “Reference link selection lucky” (yes, the same name as the command—it’s OK). I set its Scope Selector to “text.html.markdown” and its Key Equivalent to Control-Option-Shift-L.

Now I can select the text I want to turn into a link, hit Control-Option-Shift-L, and the text is turned into a reference-style link with the “I’m Feeling Lucky” URL. Wheeee!