Scheduling to-dos

Geez, it’s been a while since I last posted an original script here, so let’s fix that.

One of the things I miss about OmniFocus is its ability to hide tasks until a given date. The advantage of being able to do this is that you can add the task when it comes to you, but you won’t see it as part of your regular to-do list until the time is ripe. My favorite example is the recurring task of changing my furnace filter, which I do every 3-4 months. I liked how OmniFocus allowed me to enter this task but kept it out of my Next Actions list until a week or so before I was supposed to do it.

TaskPaper, my current to-do-list manager, doesn’t have this feature. TaskPaper’s greatest strength, and the reason I actually use it, is its simplicity, but this is one area where a little complexity would help. Since TaskPaper’s “database” of to-dos is just a simple text file, it’s easy to write scripts that extend its features (like this one), and last week I started planning a script that would automatically add scheduled tasks to my main to-do list. After a bit of thinking, though, I stopped.

Here’s the thing: I’ve never stuck with any particular task managing system, software- or paper-based, for more than a year at a time. As much as I like TaskPaper now, why should I assume I’ll still be using it a year from now? Why should I invest the time in writing a script that will be used for only a small percentage of my to-dos and may never be used after Christmas? I decided to go for a longer-lasting solution.

I’ve been using iCal and Mail continuously for over five years, ever since returning to the Mac from Linux. If I’m at my computer, they’re running. So the most robust system, it seemed, would be one that emails me a reminder when it’s time to add a task to my to-do list. Although this system won’t add the entry automatically, it will work no matter what task manager I use.

First, I created a new iCal calendar called tasks.

Every entry in this calendar will be an item that should go into my to-do list on the specified date. I keep this calendar unchecked, and therefore invisible, except when entering a scheduled task, because these aren’t part of what David Allen calls the “hard landscape,” and so, according to GTD orthodoxy, shouldn’t be in my calendar at all. In fact, I don’t consider the tasks entries as part of my calendar, per se—they’re merely using iCal as a convenient mechanism for running scripts on a schedule.

Here’s my entry for replacing the furnace filter.

It’s a recurring event that appears quarterly on the morning of the first day of the month. The summary, “Change furnace filter,” is the task to be added to my to-do list on that day. When the scheduled time arrives, it runs an AppleScript called Email Scheduled Task:

 1:  set rightNow to current date
 2:  set fiveMinutesAgo to rightNow - 5 * minutes
 3:  set fiveMinutesFromNow to rightNow + 5 * minutes
 4:  
 5:  tell application "iCal"
 6:    set theEvents to every event of calendar "tasks" whose start date comes after fiveMinutesAgo and start date comes before fiveMinutesFromNow
 7:    set theTask to the summary of item 1 of theEvents
 8:  end tell
 9:  
10:  tell application "Mail"
11:    set theMessage to make new outgoing message with properties {visible:true, subject:"Scheduled Task", content:theTask}
12:    tell theMessage
13:      make new to recipient at end of to recipients with properties {name:"Dr. Drang", address:"user@example.com"}
14:    end tell
15:    send theMessage
16:  end tell

The script does three things:

  1. It gets the current time and sets up a ten-minute window around it.
  2. It looks through the tasks calendar for entries within that window of time and gets the summary of the first one.
  3. It sends an email to me with that summary as the content and “Scheduled Task” as the subject.

A time window of some sort was needed because the script’s call to current date will almost certainly not be exactly equal to the entry’s start date. A window as wide as ten minutes is probably unnecessary, but I was feeling generous. As long as I don’t create entries with overlapping windows—a very easy restriction to satisfy—the theEvents list returned by Line 6 will have just one item, and therefore Line 7 will grab only the task that triggered the script.

(If you’re wondering why there isn’t an easier way to get the event that triggered the script, join the club. I couldn’t find one.)

I learned how to do the date math in Lines 2 and 3 from the AppleScript Language Guide and how to set up and send an email message from this MacTech article.

On the morning of July 1, the message “Change furnace filter” will be in my inbox when I get to work. I’ll select and copy the content text and paste it into TaskPaper (or whatever I’m using by then). Presumably, I’ll change the filter shortly thereafter and scratch it off my list. Repeat on October 1, January 1, etc.