Show the OmniFocus Tasks You Did Today on your Desktop

This morning Ken Case retweeted this:

Using Automator, not TextExpander

I’ve wanted a solution to show me what I accomplished in a day for a while, but I don’t use TextExpander. Luckily Colter Reed’s script to log today’s completed OmniFocus tasks is Javascript for Automation, which can be run with the built-in OSX app, Automator, so I built an Automator workflow that runs the script, (I just pasted Colter Reed’s script into an Automator “Run Javascript” action, then made one tweak when I ran into a small problem). If you’ve never used Automator before don’t worry – I hadn’t either! Here’s my Automator workflow file, (it’ll need to be unzipped). It returns a bunch of text, which we’ll deal with next.

Put the Results on your Desktop with GeekTool

GeekTool can take text from a shell script and display it on your desktop, and you can set it to refresh that text however often you want. I created a new shell Geeklet with GeekTool with the following script:

Automator Runner ~/Developer/Scripts/omnifocus-completed.workflow | sed -e 's/^"//' -e 's/"$//' -e 's/\\"/"/g'

For some reason the Automator Runner returns the text with quotation marks around it, so the parts after the pipe remove the quotation marks, (using instructions from Stackoverflow).

When choosing your refresh interval keep in mind that the script grabs focus from OmniFocus when it runs, which will be annoying if you are working in OmniFocus and you have a short refresh interval. I also don’t know how much battery this will eat for those of us on laptops.

With some font & colour tweaking, my desktop now looks like this:


Update (October 9, 2015): This morning a bunch of tasks I did last night, but before midnight, were still on my desktop, so I went debugging. It looks like OmniFocus, (at least my version, which is a pre-release test version), is exposing the completedDate value to Javascript as a UTC date/time, but with a Timezone offset set, so things done in the evening might remain on the list of “today’s” completed tasks, (this might reverse on the other side of the world, with things you do in the morning not appearing). To fix this I’ve modified the startOfDay() function to take the Timezone Offset into account. I assume this is a bug and will be temporary, so I’m not updating the downloadable Automator action above. Here’s the updated startOfDay() function:

function startOfDay() {
// The day started at midnight this morning
var d = new Date(),
hours = 0,
minutes = 0;

if( d.getTimezoneOffset() !== 0 ) {
    hours = Math.round( d.getTimezoneOffset() / 60 );
    minutes = d.getTimezoneOffset() % 60;

d.setHours( hours );
d.setMinutes( minutes );
d.setSeconds( 0 );

return d;


Update (November 3, 2015): I used quotation marks in a task name, and they came out escaped on my desktop. I’ve updated the command line for the geeklet to strip the slashes from before double quotation marks;

Vanilla Speed

Me: I wonder how to make this cool new HTML5 feature interact with Javascript properly.


Stack Overflow Answer #1: Use this great jQuery function!

Stack Overflow Answer #2: Underscore.js is better, us it! You only need 1/2 a character of code.

Smacks desk in frustration.

I’m working on a major overhaul of an existing website that focuses on speed and a great mobile experience that has never used Javascript libraries, (it was originally written in 2007 before they were a thing), and we’re not changing that. For this website a library is a bunch of extra code to download, execute, and take up memory, which adds extra function calls between the code I write and the things that happen in the browser – more CPU cycles, more battery drain, more waiting, and no benefit to our users and customers.

If we were using jQuery I wouldn’t have spent some time looking up the differences in event creation between browsers, and I might not have spent the morning figuring out why a datalist wasn’t appearing properly in Firefox, or maybe I would have had to do that bit of debugging anyway. One thing that doesn’t help me move the project along at all is other people’s over-reliance on Javascript libraries that is so prevalent. In 2007 when I had a problem I could Google it, or post to a forum, and find an answer, (assuming it had been done before), today I experience the sequence of events at the top of this post several times every day. This is why the trio of blog posts last week, (Marco Arment’s post about PPK’s post about John Gruber’s take on Facebook Instant), have really resonated with me. PPK is right, we need to stop relying on libraries, whether it’s jQuery, underscore, or whatever. There are times when a library is the right tool, but with modern Javascript APIs, HTML5, and CSS3, and good browser support for all but the absolute bleeding-edge.

To use a Javascript library is to externalize the cost of development onto your customers and users.

Despite my frustration with the “use some library” responses on Stack Overflow questions using plain vanilla JavaScript has turned out to be an enjoyable learning experience. I’ve been able to make everything work, (so far), with way less code than was needed in 2007. Of course, if your browser can’t handle the project’s Javascript requirements the JS is not loaded at all and you get the plain HTML experience, which isn’t so bad either.

For more on choosing not to burden your users and customers with unneeded slowness, see the ALA article Choosing Vanilla Javascript, which is 15 months old now, and things have just gotten better since it was published!

Historical & Future Writing Patterns

Let’s have a look at the what content has been the most popular here on over the past several years, what I’ve written the most of, and what I’m hoping to write more of, (this is part of the 10 Days to a Better Blog series I wrote about on Sunday, and is a bit introspective).

The two posts that are by far the most popular are ancient: Using VLC to transcode an Axis Camera’s video stream, and stream it out again from 2008, and Transferring OS X and Boot Camp to a New Hard Drive from 2011. In the case of the streaming post, transcoding or transforming video streams from IP cameras for public viewing on the web was a new concept, using VLC, which is free, to do it was very attractive, and there was very little information available on the web about how to turn the stream from an IP camera into something consumable in a web browser. As for the post about transferring to a new hard drive, the post is a detailed step-by-step, and there’s a large audience of people who buy new macs and want to transfer their info. These are one-hit-wonders, though, I could update them, but they would no longer be new. In the case of streaming the answer was “Use Wowza” even when I wrote the post.

Let’s look at content categories that have done well. “How To” content is popular, probably because that’s most of what’s here, but things I write about most often, like WordPress and Javascript, are not consistent leaders. Some WordPress posts have good traffic numbers, but it’s the weird posts like Improving Trac’s Tickets by Milestone Report or How to Update an Updated Subversion Repository from a Working Copy that have generated the most comments, excluding the two hero posts discussed above.

I’ll keep writing How To content for myself, I have some sketched out already, but I should explore writing about weird things a bit more. There are a couple of new categories that might show up here as well: Comment on social issues, (I touched on exclusion of women on Monday), and sometimes Photography, which used to be a lot more active than it is.


Accidental Exclusion

I often listen to the Accidental Tech Podcast while washing dishes, and this week they had a discussion sparked in part by a tweet by John Siracusa about what they can do to get more women to listen to the show. One of the responses to John’s tweet discussed on the show is that the sponsor reads sometimes feel like they cater exclusively to men, and John and Marco discussed the merits of dropping sponsors that cater only to men vs. trying to modify the ad read in a way that it’s inclusive, even if the sponsor sells a male-focused product.

The discussion was mostly about Harry’s, a shaving company, and the most obviously male-oriented recurring sponsor of the show, and in the discussion Marco stated that he felt the script was pretty neutral, with the exact words “I don’t think the script is really the problem.” Because Marco seems like a considerate man who genuinely wants to include everyone I’m pointing out how last week’s seemingly-innocent sponsor read for Harry’s excludes women.

Numerous comparisons, in quality, price, and comfort, to the Fusion line of razors, suggesting the style is Mad Men-inspired, and, and the statement that Harry’s “was started by two guys who wanted a better product” leave no doubt that these are razors being made for men, not women. Saying that the blades provide “a better shave that respects your face” leaves little doubt that Marco is speaking to the men in the audience, not the women.

The short phrase “respects your face” excludes women. If it read “a better shave that respects your skin” or “a better shave that respects the face” then women would not be excluded. John suggests going even further and trying to include women, but the point of this post is to show how easy it is to exclude a group without even realizing it.

Posts two days in a row. Why?

After many months of silence this is the second day in a row that a post has appeared here. Why?

The story starts on May 1 when a tweet by Tim Ferriss about, caught my eye, (he’s an investor). I downloaded the app and am trying the “Habit of Waking Up On Time” challenge. One of the suggestions is to replace the habit of sleeping in or hitting snooze with a new habit, which brings me to John Saddington, the programmer behind Desk app. In November John posted 10 Days to a Better Blog! — a series of exercises to get people blogging. I’ve had it bookmarked, and blogging exercises are much more productive than sleeping, so I’m working through the exercises when I wake up. Today’s exercise is to post about why I write. I’ve read ahead and some of them are a bit navel-gazing, like this one.

So why do I write?

I write to avoid forgetting. There’s a sweet spot where I use a technique a few times a year, but not all the time, and it requires some almost-repeated code, often SQL. I like to get those things into a blog post so the queries are easy to find, such as analyzing web server logs in MySQL. Sometimes I solve difficult problems and I don’t want to forget how. My posts on transferring a Boot Camp partition to a new hard drive and transcoding live video streams from IP cameras are examples of these.

There’s a second reason I write: to rant, hopefully constructively. This doesn’t happen often, but it has, this is a blog after all.

The third reason I write is to try to refine ideas. This kind of writing rarely ends up anywhere public, but writing, then editing, helps me figure out things I’m having problems with, from code to business to gardening and beyond.