Custom Quicksilver Actions in Ruby

Posted 16 August 2007 under , , , ,

And now, a neat trick I picked up at the Ruby Hoedown last weekend, combining my favorite language with my favorite app launcher/file appender/iTunes controller/ninja throwing star, Quicksilver. By placing Ruby (or any scripting language, I suppose) code in ~/Library/Application Support/Quicksilver/Actions, Quicksilver will make the script callable as an action, passing the selected item as a command-line argument. To illustrate, I wrote the following bit of code, which takes a URL and creates a bookmark in my Bookmarks folder.

require 'open-uri'

title = ''
url   = ARGV[0]
file  = open(url)

open(url) do |page|
    page.each do |line|
        title = line[/\<title\>(.*)\<\/title\>/, 1]
        break unless title.nil?
title ||= url.gsub('http://', '').gsub("\/", '|')"/Users/deisinger/Dump/Bookmarks/#{title}.webloc", "a") { |f|
    f << %Q{<?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "">
        <plist version="1.0">

system "/Developer/Tools/SetFile -a E \"/Users/deisinger/Dump/Bookmarks/#{title}.webloc\""

This simple script takes a URL from the command line, and opens it using the open-uri library. We want the filename of the bookmark to be the title of the page, so we parse through the document until we find it. If no page title is found, we’ll just use the URL of the page, with some illegal characters removed. Next, we open a file with the appropriate filename, and write the XML information for the bookmark. The last line simply hides the ugly “.webloc” file extension.

I put this script, named bookmark.rb, in /Users/deisinger/Library/Application Support/Quicksilver/Actions, and after restarting Quicksilver, the following action is available:

To take it a step further, I wired up a Quicksilver trigger so that Control+Command+B takes the contents of the clipboard and runs it through this script, like so:

Pretty slick stuff, huh? There’s a lot you could do with this; I can imagine writing some Ruby code to manage a to-do list using a SQLite database, or to generate and display test coverage information using RCov. In other words, I could waste a lot of time in the name of increased productivity.

  1. I’ve been using Hpricot to do a lot of my HTML parsing nowadays… try this out:

    @title = (Hpricot(open(url))/:title).inner_text@

    Alpha Chen · Aug 16, 06:50 AM · #
  2. Wow! That’s totally cool. I knew there had to be a more idiomatic way to pull the title out.

    David · Aug 16, 07:02 AM · #
  3. Another thing I like doing is using Builder for XML, though in this case, it’s probably overkill. (Unfortunately, I can’t figure out how to get it formatted correctly in the comments, but you can figure it out.) =>“foo.xml”, “w”), :indent => 2).instance_eval do
      declare! :DOCTYPE, :plist, :PUBLIC, “-//Apple…”
      plist :version => 1.0 do
        dict do
          key “URL”
          string url
    Alpha Chen · Aug 16, 09:56 AM · #
Leave a Comment (please be nice/human)
Textile Help

About David

pic of david David Eisinger is a Web Programmer in lovely Durham, North Carolina, specializing in Ruby on Rails and Javascript. Take a look at (most of) his online activities, or feel free to contact him.

Status (via Twitter)

Played through 'Monument Valley' for iPad the other night. Great puzzles, great visuals. Just great all around.

Recent Photos (via Flickr)