So, I was finishing off the list of programs I use on my Mac, which started off just as bullet-pointed plain text (I typed each program in as I installed it). This being the interweb, I figured it'd be a bit flash if you could click on the program names and be shown their web sites.

Half way down the page, doing this by hand, I got very bored.

Goal: I want to select a URL, select Shiira > Services > Markdown URL and have the title of the page at that URL used as the name of a Markdown link. (For some reason, I started using Markdown, not Textile.)

Easy? Well it is if you know how.

First go

First up was TextWielder. This lets you do find-and-replace pattern matching on highlighted text. Except, you have to write the replace bit in JSP(!). However, you can also make it run the replace bit as an AppleScript, so I started there - AppleScript is for people who failed VB.net 101, so seems like an easy route.

About two hours later, I realised there is no simple way to fetch a web page in AppleScript and extract the title tag (or any documentation written this millenium (seriously!) that might explain how.

Second go

Sticking with the TextWielder thing, I decided to do it in JSP. That's ok, I use a sheep strapped upside down in a crane-supported harness to wash my car, so I'm used to tools being not quite right for the job.

Man alive, now I remember why I stopped using Java!!!

Another half hour of pain and I decided to cut my losses. I knew how to do the actually HTML processing bit in Ruby in about 3 lines, so I adjusted my search keywords and found...

Third go - Bellhop!

Bellhop lets you write Mac OS X services in dynamic languages, which is a slightly more appropriate range of tools than JSP. You get to pick from AppleScript (maybe not), Python, Perl, F-Script and... Ruby!

There's a slight obstacle, namely that unlike, say, svnX, Bellhop does not allow you to specify the location of the binaries it calls, and I wanted to use my MacPorts install of Ruby so I could install Hpricot. Before any of this will work, then, you have to replace the Apple Ruby with the MacPorts version. Open a Terminal window and do this:

    $ cd /usr/bin
    $ sudo mv ruby ruby-apple
    $ sudo ln -s /opt/local/bin/ruby .

Next, I used a couple of gems, namely Hpricot, a fast and delightful HTML parser, and HTMLEntities to catch any wacky characters:

    $ sudo gem install hpricot
    $ sudo gem install htmlentities

The final service handler, which you can install in a new Bellhop file, looks like this (haven't yet worked out how to do Ruby syntax highlighting in Mephisto - I have now :) ):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
require 'rubygems'
require 'hpricot'
require 'open-uri'
require 'htmlentities'

def title(page_location)
  doc = Hpricot(open(page_location))
  entity_coder = HTMLEntities.new
  entity_coder.decode((doc/:head/:title).inner_html.strip)
end

def runService(aPasteboard)
  url_string = Pasteboard.readData(aPasteboard, NSStringPboardType)

  markdown = "[#{title(url_string)}](#{url_string})"

  Pasteboard.declareTypes(aPasteboard, [NSStringPboardType])
  Pasteboard.writeString(aPasteboard, NSStringPboardType, markdown)
end

And that's it! If I'd known to try that first, I would've been done several hours ago. Now I know how, though, I might find myself writing more services in future. Just not in AppleScript.

Leave a Reply