Quick shell commands with Alfred, AppleScript, and Growl

I need to track time on my current project, so I started using the timetrap gem. It’s pretty great. Briefest possible synopsis of what you get:

1
2
3
4
5
6
7
8
9
10
11
12
$ t in 
  Checked into sheet "important project".
$ t out
  Checked out of sheet "important project".
$ t d
  Timesheet: important project
      Day                Start      End        Duration   Notes
      Wed Feb 11, 2015   08:30:37 - 10:25:39   1:55:02    
                         10:36:49 - 11:59:00   1:22:11    
                                               3:17:13
      ---------------------------------------------------------
      Total                                    3:17:13

Quick and easy! Except my workflow becomes:

  1. Open a new terminal window
  2. Type two or three characters
  3. Close the terminal window

which starts to seem silly kinda quickly. One solution is to use Alfred to type shell commands without opening up a new window. Seems promising, but this isn’t much better since you’re still left with a stray terminal window—or worse, a new fullscreen terminal window that’s slow to open and slow to close due to the laggy Mission Control transition speed.

A Solution

My solution is to get fancy and use AppleScript to run the command and send the output to a Growl notification. So let’s start with the result. In the end, I want to type this:

Alfred usage

and end up with a growl notification that looks like this:

Growl notification

How do we accomplish that? I’m just going to quote my code without explanation. There’s not much to it. I don’t even know AppleScript. I mostly just merged the built-in Alfred Terminal command code and code from the Growl AppleScript Documentation page. My addition is that it runs a bash command, sourcing the bash profile and redirecting stderr to stdout. It then sends the output to either a Growl noficiation or a plain old alert box, depending on whether Growl is available.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
on outputResultRoutine(growlDescription, growlContent)
  tell application "System Events"
    set isRunning to ¬
      (count of (every process whose bundle identifier is "com.Growl.GrowlHelperApp")) > 0
  end tell

  if isRunning then
    tell application id "com.Growl.GrowlHelperApp"
      set the allNotificationsList to ¬
        {"Shell output"}

      set the enabledNotificationsList to ¬
        {"Shell output"}

      register as application ¬
        "Alfred Shell Command" all notifications allNotificationsList ¬
        default notifications enabledNotificationsList ¬
        icon of application "Script Editor"

      notify with name ¬
        "Shell output" title ¬
        growlDescription description ¬
        growlContent application name "Alfred Shell Command"

    end tell
  else
    display alert growlDescription message growlContent
  end if
end outputResultRoutine

on alfred_script(q)
  if true then
    set result to do shell script "bash -c \"source ~/.bash_profile && " & q & " 2>&1 &\""
    outputResultRoutine(q, result)
  else
    tell application "Terminal"
      activate
      do script q
    end tell
  end
end alfred_script

Copy/paste this into your Alfred setup, and you’re good to go!

Alfred setup