A little Eggtimer script using Growl

The quasi-standard notification system for Mac OS X is Growl, and one of the extras included in the download is the growlnotify app that lets you push notifications from shell scripts. Then, there is the at command which allows to execute a job at a given time. It's essentially another way to modify the crontab, that doesn't use the crontab directly.

So with a notification system and a scheduler at our disposal, I thought it would be good to write a little eggtimer script so that I can specify "Remove Pizza from oven in 10 minutes". I'm sure there are tons of graphical tools available, but I prefer a simple shell script.

The growl side is easy, this command needs to be executed:

growlnotify -t "Reminder at 03:54" -m "Remove Pizza from oven" -s -a iCal

The -t parameter specifies the title (even though the manpage incorrectly states "this does nothing"), -m is the message, -s means it's sticky (so it doesn't disappear unless explicitly closed) and -a specifies the icon to use, in this case the iCal icon.

The at command is used to create jobs that run at a specified time. However, it requires another "service" to run, called atrun. By default, this is disabled. Check the atrun manpage for the command to enable it, on my OS X 10.6.6 it's

sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist

I found the syntax of at a bit weird as it kept complaining about garbled or incomplete time. It actually needs to read a whole input from stdin rather than just accepting a single command. So the invocation looks like this:

at now + 10 minutes << eol
growlnotify -t "Reminder at 03:54" -m "Remove Pizza from oven" -s -a iCal
eol

That works, but of course it's WAY too much to type for us lazy people 🙂 So let's wrap this in another shellscript that accepts two parameters: A number for "Remind in X minutes" and a message:

#! /bin/zsh
function verifyminutes () {
  echo -n $1 | grep -Eq "^[0-9]+$"
  echo $?
}
function gettargettime() {
  date -v +$1M "+%H:%M" 
}
function getmessage() {
  # function to collapse arguments $2..$n together (skipping $1)
  # I'm pretty sure there is a better way of doing this
  local FIRST_PARAMETER=0
  for i;
  do {
    if [ "$FIRST_PARAMETER" -eq 0 ]; then
      FIRST_PARAMETER=1
      continue
    fi 
    echo -n $i" "; 
  }
  done
  echo "\b"
}

local ISNUMBER=`verifyminutes $1`
[[ -z $1 || -z $2 || "$ISNUMBER" -gt 0 ]] && {
  echo "usage: $0 minutes message"
  exit 1 
}

local TARGET_TIME=`gettargettime $1`
MESSAGE=`getmessage $@`
echo "Reminder set at $TARGET_TIME: $MESSAGE"

at now + $1 minutes >/dev/null 2>&1 << eol
growlnotify -t "Reminder at $TARGET_TIME" -m "$MESSAGE" -s -a iCal
eol

exit 0

Usage of this script is simple, just call eggtimer 10 Remove Pizza from oven and 10 minutes later you will get a Growl notification.

PS: If you are wondering about the getmessage function: Normally if you have spaces in an argument, you need to enclose the entire message in quotes. I wanted to get rid of the quotes, hence I'm collapsing all parameters after the first one together.

Comments (1)

[...] them charging now, it's their right. And $2 really isn't much, I bought it immediately since I use growlnotify a [...]