November 02, 2013

Combining iCal and Taskpaper items into a daily summary

I keep appointments and birthdays and certain recurring tasks in iCal and todo items in Taskpaper. Actually, I rarely open the Taskpaper app on my mac, I manage the todo file in vim using David O’Callaghan’s taskpaper.vim but I use the Taskpaper syntax and the Taskpaper iOS app. I’ve always wanted a daily overview that would show todos and appointments, birthdays, etc. in one place but I’ve never found a solution that suits. I think iCal, and BusyCal which I tried for a while, make a poor job of managing todos, and Taskpaper isn’t really suited to recurring tasks. I did use the mighty Taskwarrior for a period solely for its recurring tasks function and I love it: for me, unfortunately, loving Taskwarrior means spending oodles of time pruning, tweaking, admiring, filtering and visualising my todo list and not so much time doing the things on it. If you’re looking for a command line task manager that has more features than you could conceive of you should check it out.

I sat down today to see what I could come up with to give me a daily summary of my iCal and Taskpaper items and the result is my first ever shell script. I’m sure it’s ugly as hell and quite possibly dangerous but it’s working so far and I’m quite pleased with myself. I already used Ali Rantakari’s terrific icalBuddy for getting my calendar details from the command line, and I frequently search my todo file for items tagged @today or @overdue, so it wasn’t a huge stretch to combine the two into a one-pager that I could print out daily. One interesting piece of the puzzle is Andre Simon’s Ansifilter which I needed because icalBuddy includes ansi control characters in its output by default. Ansifilter does a champion job of removing them leaving me with just nice clean text and it compiled without issue on OSX. Here’s the result of my labours, no sniggering please.

#!/bin/sh
# Important disclaimer - I have no idea what I'm doing

# Set up temp files for the outputs
CALENDAR=$(mktemp /tmp/today.XXXXXXXXXX)
TODO=$(mktemp /tmp/today.XXXXXXXXXX)
COMBINED=$(mktemp /tmp/today.XXXXXXXXXX)
TODAY=$(mktemp /tmp/today.XXXXXXXXXX)

# Call icalBuddy with arguments, pass it to ansifilter to strip out control
# characters and write the resulting file to the calendar temp file
icalBuddy -sd -nc -npn -eed -eep url,notes -df "%a %e %b" eventsToday+5 | ansifilter > "$CALENDAR"

# Search the todo file for any items due today, tomorrow, or overdue, pass it
# to sed to strip the indentation at the start of the relevant lines and write
# the output to the todo temp file
egrep "(@today|@tomorrow|@overdue)" /Users/larry/todo.taskpaper | sed 's/[[:cntrl:]]//g' > "$TODO"

# Combine the todo and calendar files. For pretty formatting this would be
# better handled by awk but I haven't figured out how to do that yet :(
cat "$TODO" "$CALENDAR" > "$COMBINED"

# Pass the combined file to pandoc preserving linebreaks and using my tex
# template and output the resulting temp today.pdf file
pandoc "$COMBINED" -f markdown+hard_line_breaks --template=template.tex --latex-engine=xelatex -o "$TODAY".pdf

# Print the pdf
lp -o media=A4 "$TODAY".pdf

# Delete the temp files
rm -f /tmp/today*

The only thing that I’m not happy about is the combining of the files, but I’ll work on it. I want to get the todo items before a specific line in the calendar output but I haven’t yet figured out how to get awk to handle that and I don’t think sed is up to the task. I’m happy, for now, with what I have and I’ve set up a launchd task to run each morning at 8am so I’ll have a daily summary waiting in the printer. (If you do find anything too dangerous looking in there, please do give me a shout!)