Self-Opening AppleScript Droplets

September 11th, 2005

Most of the AppleScripts I use are “plain scripts.” That is, they require a host application in order to be run. AppleScript also supports the notion of a script application, which can optionally accept “dropped” items directly to the script’s icon. These script applications are commonly referred to as “droplets.”

Most of my droplets are “pure droplets.” By that I mean, they are completely useless to me unless I have actually dropped something on to them. Because of this, and because of the fact that I’m in the habit of double-clicking “plain scripts” in the Finder to bring them up in Script Editor, I often find myself accidentally double-clicking my droplet scripts in an attempt to edit them. This has the unfriendly result of my script simply complaining that it didn’t get anything dropped on it. I then have to go find the Script Editor and drag the droplet to it in order to edit it.

It occurred to me today that I could use the script itself to achieve the desired result. Instead of responding to a double-click launch with no “dropped items” by failing, why not just do what I want it do? I added code to the top of one of my pure droplets, which yields the desired effect:

tell application "Script Editor"
    activate
    open (path to me)
end tell
return

on open (dropArgs)
	-- Droplet code goes here
end open

Now when I double click the droplet, it kindly asks the Script Editor to open itself for editing. This extra code has no impact on the “useful” droplet code, because a droplet’s code is reached through an “on open” handler, which means the implicit “on run” code at the top-level of the script is never run except when the item double-clicked.

Safari Link Sniffing

September 9th, 2005

Keeping with the Javascript theme of my last entry, I’d like to share one of the ways I’ve used Safari’s AppleScript accessible javascript model to improve the quality of my web browsing experience.

It occurred to me one day while reading some long article on Salon.com that something had been bothering me for a long time. The way that web sites often force you to split up your reading into several pages, and the fact that almost every web site seems to have a different link name, location, etc., for performing this simple and extremely frequent task.

Why isn’t there a standard way to “go to the next page” in a web browser? We have forward and backward, but we have no way to get to the forward part of that equation unless we’ve already been there! Useless!

I decided to try my hand at automatically detecting the location of the “Next” button, and clicking it on the user’s behalf. Why should I, a human being with precious little time on this planet, have to waste huge chunks of it hunting around for links named “>>” or “Next >” or “Page “?

My solution hinges on the fact that javascript exposes a given web document’s links in the form of a “document.links” array. Not familiar with Javascript? Try typing the following into your browser’s address bar and press return:

javascript:alert(document.links[0]);

A dialog should appear showing you the location of the first link on this page. OK, good. But that’s useless for my purposes. I need to know what the link looks like to the user. Does it look like a “next” link? Try this javascript command next:

javascript:alert(document.links[0].innerText);

This bad boy will pop up the text as it appears (more or less) to the user. Great! So all I have to do is iterate through *all* the links on the page, look at their innerText, and if it looks like “Next” or any of the bajillion other variations on “go forward” that are currently in use on the web, then I’ll follow the link.

This approach basically works, and after collecting a number of examples from around the web, I came up with a pretty good, general purpose script for doing exactly what I wanted.

I shared the script through MacScripter.net and have found quite a few satisfied users who have also contributed by pointing me to sites that were not previously supported. The script now looks not only for links with names like “Next >” but also for graphical links whose files are named “next.gif”, etc. The result is a script, free for your use, which can take the tedium out of “going to the next page” for lots of the sites you access in Safari. It works best with a keyboard shortcut. For instance, I set mine up to trigger when I am in Safari and hit “cmd-right-arrow.” You can download Safari Next Page from the Red Sweater Scripts page. In addition to long stories on the web, it’s also great for search engines that return dozens of pages that you need to cruise through quickly.

If you use it, let me know when you find sites that can’t be tricked by it. I will do my best to add support in a general way that fixes it for the site in question and hopefully many others.

Update: Following a clue posted by Faried below, I found a rather more extensive version of this project for the Firefox browser. There are two similar projects both worked on by the same folks: Link Toolbar and LinkIt. Unfortunately, the Link Toolbar seems firmly entrenched in MPL/GPL/LGPL licensing restrictions. I can’t tell yet whether the LinkIt accumulated wisdom could be shared or not. I am impressed by the fact that they’re using regular expressions to do the comparisons. Much slicker than my brute-force method.

Escape from All Code Trash

September 6th, 2005

URL Escaping is what causes those yucky percent-signs and numeric digits to show up sometimes in the middle of your otherwise perfectly legible URLs. These percent-escaped values are necessary because the list of allowed characters for a URL doesn’t cover many of the common punctuation marks we like to use, and also fails to cover the Unicode characters that are more and more common in the international world-wide web.

I was explaining to a client some of the finer details of escaping, and trying to foster an understanding for what needed to be escaped and what didn’t, when it occurred to me that they, like almost everybody reading this post, has at their disposal an excellent reference on URL Escaping: the JavaScript interpreter built into their browser.

Since I discovered the built-in escaping and unescaping functions of JavaScript, I have from time to time taken advantage of them by typing something quickly into the address bar of Safari when I needed to get a quickly readable version:

javascript:alert(unescape(‘Escape%20from%20All%20Code%20Trash’))

To make this is as easy as possible for everyday users (my client, in this case) to take advantage of, I decided to put together a couple “button-bar” compatible JavaScript URLs. Now I keep these in my own toolbar for quickly encoding and decoding URL strings as necessary.

To try them out, just click on the link (from a web browser). To install them, drag them, one at a time, to your bookmarks bar.

Escape URL

Unescape URL

I%20hope%20you%20enjoy%20these%20S%FCper%20Kewl%20Scripts%u2122%21, and please let me know if you have any suggestions for improving them.

Bonus bugs with GDB

September 2nd, 2005

I guess the last bug report got me in the mood, and since it’s 11:55 here in Somerville, I have time to write up a quickie that I just noticed again, while investigating the other bug I reported tonight!

This is an obscure bug, but part of my reason for sharing it in a post is that some of you may not be familiar with the particular feature of gdb where this bug rears its head. The feature I speak of is the “info sharedlibrary” extension Apple was kind enough to add several releases ago, which allows the debugger (that’s you!) to easily match up an address in code memory with the shared library from which it was loaded. I thought some of you might not know about it, and the next time you’re digging around through somebody else’s code, you might find it handy.

In the old days (haha! old, meaning like, 2001), if we ran across a mystery chunk of code in gdb, we had to do a plain “info shared” and then scan through the list of libraries, forcing our brains into hex overdrive as we tried to match the address with the ranges of addresses attributed to the bazillion libraries that had inevitably been loaded into the process.

In the new days (haha! new, meaning like, 2003), Apple added the obvious argument to this utility, which allows you to specify the particular address your interested in, and have gdb handle the hard searching for you:

(gdb) info shared 0x52240
  1 Finder                     - 0x1000            exec Y Y /System/Library/

Sweet! Love that taking away the pain functionality. The only problem is, when a nice new feature comes along, you expect it to do everything wonderfully and perfectly. In the case of “info shared”, a major drawback has plagued it since its inception. Sure, it lets you find the associated shared library for an address, but it fails to extend this concept in the most freaking obvious way imaginable. It doesn’t accept variable arguments! If I’m stopped in gdb, and I want to know where I’m at, my feeble little brain still expects “info shared” to do the right thing, so I inevitably do something like the following:

(gdb) info shared $pc
[unknown]
(gdb) ugh!
Undefined command: "ugh".  Try "help".
(gdb) p $pc
$6 = 336448
(gdb) info shared 336448
  1 Finder                     - 0x1000            exec Y Y /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder (offset 0x0)
(gdb)

That’s no way to live! It’s time that this wonderful little helper got with the program. Any reasonable expression that evaluates to “a number” and can be passed to any other command in gdb should also be accepted by this little gem. Radar #4243991.