A Greasemonkey Christmas #

Update on 1/23/2006: The label colors script exposed a XSS vulnerability. It has now been updated to remove this hole - all users are encouraged to install the latest version of the script.

After many delays, I've finally gotten around to updating my Greasemonkey scripts so that they run under Firefox 1.5 and Greasemonkey 0.6.4. In fact, these scripts will most likely not work in older versions, and I will not be supporting Firefox 1.0.x or Greasemonkey 0.3.x.

Conversation Preview Bubbles (script) was the most straight-forward, since I had already done some work to make it compatible with the unreleased Greasemonkey 0.5.x releases. In fact, it seems to work better under FF 1.5/GM 0.6.4 - before the script did not trigger for label and search results views, but now it does. Saved Searches (script) required a bit more work, and in the process I decided to clean it up a bit. The result count functionality was removed, since it was not that useful. The fixed font toggle feature was spun off into a separate script since it didn't make any sense for it to be bundled.

Gmail macros screenshot I'm also taking this opportunity to announce two scripts that I had previously written and never gotten around to releasing. Gmail Macros adds additional keyboard shortcuts to Gmail. Some are obvious (and have been done by other scripts) such as "t" for move to trash and "r" for mark as read. However, I strove to provide a bit more functionality. For example, "p" both marks a message as read and archives it, when you really don't want to read something (the "p" stands for "purge"). Additionally, the shortcuts can be easily customized by editing the HANDLERS_TABLE constant. More than one action can be chained together by providing a list of action codes (which are contained in the script and were extracted by looking at the generated "More Actions..." menu in Gmail). The other novel feature is for label operations. Pressing "g" brings up a Quicksilver-like display that allows you to begin typing in a label name to go to it (special names like "Inbox" and "Trash" work too). Similarly, pressing "l" allows you to label a conversation with the label of your choosing.

Gmail label colors screenshot The other script is Gmail Label Colors. In the much-quoted Walt Mossberg article on Gmail and Yahoo Mail, he claims "Gmail doesn't allow folders, only color-coded labels." Ignoring the folders vs. labels debate for now, this sentence is not actually true, since labels in Gmail cannot be color-coded. This script adds that functionality, since it turns out to be very useful (if used sparingly, otherwise too many colors can get overwhelming). To specify a color, simply rename a label to "Labelname #color" (e.g. to make the label "Foo" be red, use "Foo #red" and to make the label "Bar" be orange-ish, use "Bar ##d52"). It works in a similar way to the conversation bubble script, in that it overrides the JavaScript function through which Gmail receives data. It has to jump through some hoops to avoid the HTML escaping that Gmail does; intrepid Greasemonkey hackers may want to look at the source.

If you're wondering why so many of my Greasemonkey scripts are Gmail-related, it's because it's the application where I spend a significant part of my day, thus every bit of productivity improvement counts. Not only do I use Gmail for my personal email, but I also use an internal version for my email needs at Google (as do most of the other Googlers - this constant dog-fooding helps to make Gmail a better product).

(the usual) Disclaimer: I happen to work for Google. These scripts were produced without any internal knowledge of Gmail, and they are not endorsed by Google in any way. If you have any problems with them, please contact only me.

ChainShot ColorJunction Lives! #

Almost a couple of years ago I released ChainShot, a Konfabulator Yahoo Widgets Widget. When the Google Homepage API was announced internally, a contest was held to develop sample modules in time for launch. I decided to port ChainShot, partly due to a lack of any better ideas, but also because I was curious how the two systems compared. As it turned out, my game (since renamed to ColorJunction) was selected for external release (you can find it in the directory).

If you're looking to make your own module, the documentation is pretty thorough. The sample modules all have unobfuscated source code, so they should serve as good starting points. There's a pretty powerful JavaScript API (e.g. we provide you with a proxy so you can jump across the same-domain limitation of XMLHttpRequest) and a descriptive XML language. But in the end, all your AJAX-y/HTML/CSS/JavaScript skills can be used pretty much as is (an advantage the Homepage API shares with Apple's Dashboard).

N.B. ChainShot/ColorJunction is a clone of the 80s Japanese game of the same name.

Greasemonkey Hacks #

I finally received my complimentary copy of Greasemonkey Hacks. I'm also glad to see that my saved searches user script was selected as one of the sample ones. Reading the contributors section was somewhat amusing due to the homogeneity of the entries (e.g. more than half mentioned blogs). The book is also already out of date, with Greasemonkey and Firefox both having undergone major releases. I also doubt the wisdom of printing the full code behind each hack - especially some of the longer ones that were already online. Commentary attached to interesting snippets might have worked better. However, as a whole the book seems very well put together and it brought to attention some scripts I hadn't heard of before.

As a side note, I realize that with the recent release of Firefox 1.5 and Greasemonkey 0.6.4 most of my user scripts have suffered some code rot. I hope to bring everything up to date in the next few days.

More Scraped Feeds #

Some time ago I posted about scraped comic feeds. Some time in the past few months, the one for Frazz disappeared. I have therefore taken it upon myself to produce an unofficial Frazz feed. Comics.com doesn't make it easy to do this, since they embed a hash (unless I'm missing some pattern) in each day's comic image. Still, it was reasonably easy to parse the archive pages with Python's htmllib and scrape the necessary URLs.

In a similar vein, I've created a feed for recordings of Stanford's Computer Systems Laboratory Colloquium. Some interesting speakers come, and the entire lecture is available online. The schedule is available, but checking it by hand is tedious. Items tend to show up early, so the scraper script actually checks for a valid video URL before including it in the feed.

Update on 11/9/2005: It occurred to me that I never like how to the source for these scraping scripts is unvailable, since if one of them stops working, someone else willing to pick up the ball has to start from scratch. I've therefore uploaded the Python code that generates these scraped feeds.

Google Reader #

About a year ago I switched from NetNewsWire to Bloglines. I was on an extended trip and had only brought my PC laptop with me, and Bloglines seemed like the least hassle to set up. Surprisingly enough, when I got back from the trip I never switched back. While the Bloglines UI wasn't quite as slick as NetNewsWire's, the sheer convenience of being able to access my subscriptions anywhere outweighed all other cons. This of course is not news to anyone that has switched from a desktop mail application to Gmail, from a traditional photo software to Flickr, and so on.

That being said, the Bloglines UI is not as good as it could be, even given the constraints of web applications. I initially attempted to remedy this with some Greasemonkey scripts, but that didn't seem quite satisfying enough. I therefore jumped at the chance to work on what would eventually become Google Reader. Ben, Chris, Jason, Laurence and I played around with many prototypes, did usability studies and in general tried to come up with a product that all of us (and all of you) would use.

Google Reader launched this past Friday at Web 2.0. I'm very glad it's out there since we can now begin to iterate and react to user feedback. I think the ideal feed reader user interface still hasn't been discovered*, but I hope that we can explore some more avenues with our work with our experimentation. There are some elements of a River of News reader, while at the same time we still wanted to allow users to control their reading via labels and ranking options.

On the launch day I found that the best way to gather feedback was to be subscribed to a [google reader] search on Google Blog Search and Ice Rocket. This allowed us to find out quickly what the top issues were (speed, OPML import, new subscription notifications) and quickly fix them without having to wait for a full support mail/filtering/prioritization cycle. I'm still subscribed to those feeds, so blogging about the product is the easiest way to make sure that at least one engineer sees feedback.

* Then again, considering that applications like Zoë and Gmail continue to push the bounds of mail client UI design 30+ years after the creation of email, I wouldn't be so sure of settling on a design any time soon.

Movable Type 3.2 and Comments #

I've been wanting to enable comments on this site for a while. Unfortunately I was running Movable Type 2.64, i.e. a version from over two years ago that doesn't cope well with comment spam. The release of Movable Type 3.2 seemed like a good time to upgrade. Although Six Apart has a decent migration strategy in place, my old MT installation was pretty heavily customized (see early 2004 meta postings). I chose to do a "clean" installation, where I started with a new MT directory and migrated my plugins one-by-one, as need arose. I was able to get rid of a couple of them, since their features had been incorporated into MT itself.

I must say, for two years of development, MT 3.2 doesn't blow me away in comparison to the version I was using. More UI polish is definitely apparent, but there are still parts that feel clunky (e.g. the need for nearly identical comment entry forms on the entry and preview templates). The mt-search integration is still very crude (a separate template directory that's not accessible through the GUI). One of the use cases of MT (as opposed to LiveJournal or TypePad) is a techy user who uses their site as a knowledge repository (e.g. me) - in this case having decent search is very important.

Going back to what caused this upgrade, comments are now enabled. There's still some playing around to be done with CSS and I still haven't figured out what approach to spam I'll take (e.g. moderation vs. requiring TypeKey).

Update on 9/28/2005: Email addresses are no longer required. TypeKey authentication should now actually work (the trailing slash in blog URLs on the profile page is key).

As Evan mentions, Movable Type 3.2 supports OpenID authentication (albeit only as an extra). Supporting both TypeKey and OpenID makes the comment form a bit overwhelming. Since TypeKey is now an OpenID server, the latter should be enough, since it has a superset of the functionality. However, I think TypeKey still has more user awareness (and entering your TypeKey profile URL is not exactly user friendly), so for the time being I have both up.

Google Blog Search Filtering Trick #

Scoble's blog is too high traffic and occasionally too kool-aid-y for me to read, which is why I unsubscribed a few months ago. However, I do want to know when he posts about Google*. Using the recently launched Google Blog Search I can perform a search for all his posts that contain "google" and then subscribe to that search's feed. Now I have my very own filtered Scobleizer.

It appears that this is possible in IceRocket too, but the process is more convoluted. They support a blogId: restrict that could be used to only show results from a blog. The question is, what is Scoble's blog ID? To find that out, I had to search for a recent phrase from his blog. With that, we see that his blog ID is 413, and can set up the equivalent search. Feedster can do it with the inrss parameter, but it expects a feed URL, which is slightly less user friendly than the blog URL. As far as I can tell, Technorati lacks a site/blog restrict operator.

Update: Amit points out that Technorati has a site restrict, so for example this search is equivalent to those above. However, I am not able to determine how to get the from argument into a watchlist, thus there's no way to generate a feed out of it.

* The irony is that about half his posts seem to be about Google nowadays, thus the value of the filter is diminished.