Archive messages with a single keystroke in Mail.app

Aug 2011 Lion update: the script works but is quite slow in Lion (it’s zippy in Snow Leopard). I’m looking for a workaround, but this appears to be a Mail.app bug.

TL;DR version: Archive Mail messages with a single keystroke:

  1. Download this script and Fastscripts (free for up to 10 hotkeys)
  2. Move the script to ~/Library/Scripts/Applications/Mail/
  3. Set your hotkey in Fastscripts (Using a letter key is possible but not recommended. Try another character like `\/=- or an F-Key.)

The script will then move selected message(s) to a folder named “Archive”.

More information:

Existing shortcuts to file messages in Mail.app get you down to two or three keystrokes, but that just isn’t good enough for someone who has tasted the sweet, sweet bliss of single-keystroke archiving in Postbox or Gmail.

In my original reply to this superuser thread, I suggested using an AppleScript to move selected messages to an archive, and triggering the script using a single-key shortcut using Fastscripts. That script is simple and straightforward, but it has a major shortcoming: it leaves you hanging with no next message selected, so you have to manually select your next message. Not ideal.

My new script archives messages with a bit more smarts. Here’s what it does:

  • If a mailbox is in the foreground, the script moves selected messages to the folder named “Archive” and selects the next available message. Boom.

  • But you don’t want to accidentally archive messages whenever you hit your archive key. If the frontmost window isn’t a mailbox, the script will ignore the archiving functions and (optionally) type some text wherever you are. This is useful if you use a single key to trigger the script; without this function, you would never be able to type that key into a mail message because it’s intercepted by FastScripts before getting to the Compose window.

For interested scripters, here were some challenges:

  • Select next message: The solutions I found online select the next message by sequential Message ID, which usually means that it only works if your mailbox is sorted by Date Received. Using visible messages gets messages in the order in which they’re displayed. Watch out, though: if message threading is turned on, the top-level thread item is not selectable. See my workaround in the script.

  • Enter the keystroke that was captured: Merely telling System Events type the character that triggered the script will trigger the script again, resulting in a virtual infinite loop. I used a paste routine to work around this.

That’s it… happy archiving!

22 Mar 2011 update: fixed bug that caused selection to be lost when only the topmost message in a mailbox is selected.

applescripticon.gif

Download: Archive Selected Messages

Tools of the Trade: Learning Objective-C from Scratch

Learning a new language is never a simple task, but the process itself shouldn’t be difficult. For my Master’s final project, I’m teaching myself Objective-C. (More on our decision to go native here.) For those facing a similar task, here are some tools I’m using using to facilitate this process.

Learning Materials

I researched several learning resources that had been recommended on Quora, including Big Nerd Ranch’s iPhone Programming and Craig Hockenberry’s iPhone App Development: The Missing Manual.

In the end, I decided to “take” the Stanford iPhone Application Development course, which is available in its entirety on iTunes U. (Note that iTunes U has both the 2009 and 2010 courses. I chose the 2010 version because a) it’s geared for a newer iOS SDK, and b) all the supporting materials are still (as of Spring 2011) available on Stanford’s course website.

iTunes handles the lecture downloads, but I watch them with QuickTime Player for two reasons: it uses less screen real estate, and you can speed up playback by option-clicking the fast-forward button. A text editor is ideal for notes (particularly one that handles Obj-C syntax highlighting), and it’s always handy to keep the lecture slides open as well. Here’s my typical “class time” screen:

Screen shot 2011-02-27 at 10.29.51 PM.png

Helpful shortcuts:

  • Setting up the screen like this is a snap with Divvy. I set up shortcuts to move windows to each half or quadrant of the screen, so they can fly to any position with a keyboard shortcut. Priceless.
  • A series of quick-and-dirty AppleScripts—which can be quickly invoked with FastScripts—makes it easy to work the lecture files. Scripts I use (available on Github) include:
    • launch the current iTunes file in QuickTime Player (or vice-versa), retaining the current playback spot
    • jump to an arbitrary playback position in QuickTime Player (especially helpful if I’ve been watching a video on my iPhone)
    • jump backwards or forwards in QuickTime Player

Notekeeping

Right now I keep two types of notes: course notes and error notes.

Course notes—general notes from the lectures or books—go in a single text file that’s easily searchable. I type or copy most of the lecture slides into this document because it’s easier to have it all in one place.

Error notes, which detail all the build errors I get in Xcode, live in Notational Velocity (tagged with “ObjC” and “Error”). Each error note contains the following sections:

  • Error message
  • Context (anything that might help)
  • My code (specific code throwing the error, and which file)
  • Problem explanation (interpretation of what went wrong)
  • Solution (fixed code)

These error notes are a personal history of the mistakes I’ve made. My expectation is that this practice will have value both now and in the future, but as the good folks at Field Notes say, “I’m not writing it down to remember it later, I’m writing it down to remember it now.” The more I can internalize beginner’s mistakes, the less likely I’ll be to repeat them.

My only complaint w/r/t using Notational Velocity for this purpose is that it doesn’t have syntax highlighting. A relatively minor inconvenience, but I’m hopeful that a future NValt build might include this.

Helpful shortcut: I use a TextExpander shortcut to pre-fill each error note before I start adding data. It simply adds each section’s header—something that might not seem that important, but it saves a little time and helps me be consistent in this practice.

Troubleshooting

Stack Overflow is an indispensable Web site for programming questions/answers. I should probably get better at perusing Xcode documentation, but often it’s faster to search Stack Overflow. (I’ve noticed that most of my problems are answered in Stack Overflow questions with no upvotes, meaning that they’re beginner errors. I’ll know I’ve arrived when I graduate to more popular questions!)

Helpful shortcut: Searching Stack Overflow is nearly instantaneous using a LaunchBar search template set to search StackOverflow with the [Objective C] tag pre-filled. Once it’s set up, ⌘[space] → “so” → [query] gets it done pronto.

Zenburn theme for OmniFocus

Here’s a draft Zenburn-based theme for OmniFocus. Due to some limitations of the theming engine, some of the status indicators (repeating, flagged, etc.) are displayed as grey-on-grey and are therefore somewhat difficult to read. Otherwise it’s quite usable. Download it here.

Zenburn.png

Stata bundle for TextMate

Rumor has it that there’s an extant Stata bundle for TextMate. The original package link is a dead, but Gabriel Rossman was kind enough to send me a copy of his installed bundle.

With thanks to the author, Timothy Beatty, here’s the original bundle:

Download Stata Bundle

Stata bundle (original)

For those wanting a little extra functionality, George MacKerron described a method to add tab-completion for Stata variables. I’ve added his code to this version of the Stata bundle. (N.B. If your Stata application is not named “Stata”, you’ll need to make one small change. Open TextMate’s Bundle Editor; then, in the Stata bundle’s Complete Variable command, change the “appname” variable in line 6 to reflect your app’s true name, e.g. “StataMP”.)

Download Stata Bundle with tab-completion

Stata bundle (with tab-completion)

Update: I’ve learned that two forward slashes can also be used in Stata for comments, including inline comments. To properly highlight this in Textmate, open the Bundle Editor > Stata > Stata. At the end of this file is the ‘comment.line.star.stata’. Change the match line to this:

match = '((^|\s)*|//).*$';

(N.B. As Sean points out below, make sure the single-quotes are straight, not curly, when you paste this line. Otherwise TextMate will throw an error.)

Billion Day

While studying in Oxford seven years ago—most likely in a fit of procrastination—I determined that the word billion can be spelled on a telephone keypad with the number 245-5466. As it turns out, 2455466 was also the Julian date of a certain September day in [the then-distant future year] 2010. I put a reminder in my Palm V and forgot about it. Thanks to an electronic calendar that doesn’t forget, I was just reminded…

That day is today.

Happy Billion Day, everyone!

(One could discount this event by pointing out it’s only the coincidence of a) Julius Caesar’s arbitrary selection of the calendar’s start date, as well as b) the arbitrary—though now standardized—mapping of Latin letters to the 10-digit keypad. I suppose we could also cite the rise of the decimal numeral system in this celebration as well; who knows what billion would map to on a hexadecimal phone keypad, or if we’d even care since 1,000,000,000 is much less elegant as 3B9ACA00 in hex. Then again, many of our declared holidays aren’t much less arbitrary.)

OmniFocus script: Schedule selected items for this weekend

Here is an AppleScript that schedules the selected OmniFocus tasks for the coming weekend. If a weekend (as defined by you) is in progress, items will be scheduled for the current weekend.

In concept, the script really lets you to set start/due dates based on a relative weekly schedule. Simple modifications include:

  • Changing your “weekend” to a different day/time range is as simple as modifying the settings at the top of the script. You could easily make a copy for “this week”, “next week”, “next Friday”, “next Thursday from 4:00-6:00”, etc.
  • Un-commenting one line will bump it forward a week (think: “next weekend”).

Download it here

Mail.app script: Find selected messages in Fastmail

For Fastmail users who also use Mail.app, here’s a script that searches for the selected messages (in Mail.app) in the Fastmail web interface.

Why would you need such a thing? One reason is that Fastmail lets users specify an infinite number of aliases which they can give to an infinite number of websites (and subsequently block, if an infinite amount of spamming ensues). Mail.app doesn’t offer a good way to change your reply address, but replying from the Fastmail web interface does the trick nicely. (Thunderbird users can use the Virtual Identity plugin for this as well.)

Here’s the script:

--Searches for the messages selected in Mail.app using the Fastmail web interface
--By Dan Byler (http://bylr.net)

tell application "Mail"
    try
        set selected_messages to selection
        set remaining to count of selected_messages
        set the_url to "https://www.fastmail.fm/mail/?MLS=MS-*;MSS=!MB-*;SMB-CS="
        repeat with the_message in selected_messages
            set remaining to remaining - 1
            set message_id to the message id of the_message
            set the_url to the_url & "msgid%3A%22" & message_id & "%22"
            if remaining > 0 then set the_url to the_url & "%20OR%20"
        end repeat
        set the_url to the_url & ";SMB-SearchAll=on;MSignal=*P-1"
        open location the_url
    end try
end tell

Or download it here.

Bringing the backchannel to the foreground at InfoCamp

It is becoming well known that social media hashtags form a de facto backchannel wherever a critical mass of tech-savvy people congregate. At InfoCamp Berkeley, we wanted to encourage the Twitter/Flickr backchannel and bring it to the fore as much as made sense. Our hope was that this would encourage attendees to tweet and post photos during the event.

There were no tagged Flickr photos at the beginning of the event, so we displayed tweets as they came in using an AIR-based app called TwitterCamp. (As it happens, Twittercamp was developed for a BarCamp, so it made an appropriate home with us at InfoCamp.) TwitterCamp is not being developed or supported, but it works fine and is open source. When customized with our logos, it looked like this:

Twittercamp

Twittercamp

By mid-afternoon, Flickr had a amassed a good selection of event-tagged photos. We switched to Twitterfountain, which can display tweets against a Flickr slideshow. Here’s a still shot with Twitterfountain in the background:

Twitterfountain

Twitterfountain

Twitterfountain looked great, and at a slow speed it wasn’t too distracting. Unfortunately, though, it tended to loop over a small selection of photos instead of iterating through the entire tagset.

To see our Twitterfountain instance in action, click* here:

And that’s about it. We kept the backchannel onscreen during announcements and between sessions—not during, to avoid undue distractions. Although there is, of course, no way to judge the “success” of these tools, we felt they added some good buzz to the room.


*Disabled by default because it’s a bit of a CPU hog.