I’ve been playing around with the geeky, efficient, command-line scheduling program remind. It’s very cool once you get used to it.
I wanted to automatically export any duedates from taskwarrior, so this is what I came up with.
Export Taskwarrior Dates
I found a script that did this (written in java), but I didn’t like it. It scheduled things that weren’t due and there seemed to be a lot of overhead for a task that amounts to generating a simple text file.
Using taskwarrior’s own export function and a bit of python, I put together the following code. It generates a file for Remind to read from only tasks that have a due date set and are not blocked by another task (such as one it depends on; rare for tasks with due-dates).
remindWarrior
#!/usr/bin/python
import json, subprocess
from pprint import pprint
outfile = '/home/USERNAME/.config/reminders/taskwarrior.rem'
reminders = '# Taskwarrior Tasks with Due Dates\n'
for t in json.loads(subprocess.check_output(['task', '+DUE', '+UNBLOCKED', 'export'])):
reminders += ("REM %s-%s-%s MSG %%\"%s%%\" (taskwarrior)\n" % (t['due'][:4],t['due'][4:6],t['due'][6:8],t['description']))
#print(reminders)
with open(outfile, 'r') as f:
#compare file with reminders string
if reminders != f.read():
#write new file only if it differs from existing file
with open(outfile, 'w') as o:
o.write(reminders)
Run crontab -e
and add a line in there to run this sucker every 5 minutes or so:
*/5 * * * * remindWarrior
As you can see, I’ve set up my reminders in a hidden directory. My ~/.reminders file includes a single line.
INCLUDE /home/USER/.config/reminders
Note also, that the script checks to see if the new file would be any different from the old file and only writes to the file if it has changed. This becomes significant later.
Automatic re-starting of Remind
I run remind as a daemon so that it will pop up reminders (using gmessage) for me. But when you change the files that remind uses, this daemon doesn’t re-read them. For that reason, and others, I created a script that would kill start the process if it isn’t running, or kill it and restart it again if it is running.
I call it reminderdaemon and it’s how I start the reminder daemon when I log in.
reminderdaemon
#!/bin/bash
XAUTHORITY=/home/USERNAME/.Xauthority
export XAUTHORITY
pid=$(ps -C rem -o pid=)
if [ -n "$pid" ]
then
#Remind is running so restart it
kill $pid
rem -az -k'gmessage %s -default okay -timeout 30 -center -title Remind -display :0.0' &
else
#Remind is NOT running so start it
rem -az -k'gmessage %s -default okay -timeout 30 -center -title Remind -display :0.0' &
fi
exit
Incron, or how to automate the restart script when files change
Here’s something really cool that I didn’t know about for a very long time:
You probably know about cron; the service that runs things for you based on time. But there’s also a service called incron that monitors files or folders and triggers actions when those files change. Very cool.
I ran incrontab -e
to edit my incron config file and put the following line in there:
/home/USER/.config/reminders IN_MODIFY /home/USER/bin/reminderdaemon
Now whenever one of the files in my .config/reminders directory is updated (including the taskwarrior.rem file), the reminder daemon restarts with the new configuration.
And remember that my remindWarrior script only writes to taskwarrior.rem if it would change the contents. This prevents unnecessarily restarting the daemon every five minutes.