The Pug Automatic

Modifying the Transmit widget to copy URLs to clipboard

Written July 21, 2006. Tagged JavaScript, Ruby, OS X, Dashboard widgets.

Yet another clipboard hack. I should just rename this blog "Copy and pug". ;)

The FTP application Transmit comes with a Dashboard widget, on which you (drag-and-)drop files to transfer them to whatever server and directory you've configured.

I missed one feature, though – having the resulting URLs of the files automatically copied to clipboard. I've posted a feature request to the Transmit people, but whipped up my own solution to stay me until they get around to it, if they do at all.

Update 2007-10-26

I had to make a tiny fix to the widget for it to work with Leopard (using /bin/echo without the -e flag rather than just echo with the -e flag), so I took the opportunity to

  • make this an unidiff;
  • remove the stuff about adding <key>AllowSystem</key><true/> to the Info.plist, since the widget seems to have that already these days; and
  • sort-of-fix an encoding issue, so characters in Latin-1 (not just ASCII) are handled correctly.
  • The post has been updated with this code.

When the widget is installed, edit /Users/username/Library/Widgets/Transmit.wdgt/Transmit.js per this patch.

Adjust the section and url bits to taste. The url is what goes before the filename. In my case, I have two widgets that upload to the directories "henrik.nyh.se/foo" and "henrik.nyh.se/bar" respectively, so the section line extracts the directory name and tacks it onto the rest of the url.

Copy on drop or on completion?

I prefer to have the URLs copied immediately after dropping files on the widget, rather than when the files have finished uploading. That way, my clipboard will be replaced as an immediate reponse to something I did, rather than at some unexpected time in the future, when I might have forgotten all about the upload and copied something import to clipboard. The downside is that I will have the URL before it actually points to something.

You could just hook the code into uploadFinished() instead, if you'd prefer to have it copy when finished.

Turning the URLs into tags

This could, of course, be combined with commands to transform the clipboarded URLs into link or image tags in HTML, BBCode, Markdown or whatever. The command might be triggered with Quicksilver similarly to Batch-open URLs from clipboard.

A Ruby script for making BBCode links out of raw URLs follows, with only minor and (hopefully) obvious changes necessary to instead copy to another format.

#!/usr/bin/ruby
require "cgi"

url_pattern = %r{https?://\S+}i
url_antipattern = %r{(.+?)([^\w/]*)$}i

fixed = `pbpaste`.gsub(url_pattern) do |url|
match = url.match(url_antipattern)
url, tail = match[1,2]
link = CGI::unescape((url =~ %r{.+[^/:]/(.+)}) ? $1 : url)
"[url=#{url}]#{link}[/url]#{tail}"
end

IO.popen("pbcopy", "w") { |copier| copier.print fixed }