Showing ToDo's with Conky by Context (HOWTO)

In my ongoing series of "Gosh, I love tweaking my desktop", I've come across a solution to my todo.txt problem.

I love the todo.txt script originally created by Gina Trapani. Keeping my todo list in a flat text file lets me keep it portable. It also makes it easy for conky (or if I was still using Windows, Samurize or Rainmeter) to display my todos on my desktop. While this HOWTO is written with conky in mind, if you can run a bash script on your system you can probably modify this to your purposes.

The problem I faced was that my todo list - even when sliced down by context or project - got to be too large for my desktop. Either the font was too small, or items were not displayed, or I was simply overwhelmed by the sheer amount of stuff to get done.

I had four requirements in order to solve my problem:
  • Be able to show any combination of categories
  • Be able to dynamically choose which categories to show
  • Have the items update
  • Low system resource usage
This is what I came up with, using a combination of grep, cat, conky, and zenity. You may not have heard of zenity before; it allows you to have an extremely customizable GUI option selector. I did a standard install of the todo.txt, and created two files. Both reside in ~/scripts; there's
. I'll comment the bits of code, then give you the full script here in a second.
cat /home/USER/scripts/todorc_base.txt > /home/USER/.todoconky
First, we copy the base of our configuration over to the home directory, overwriting any that might already be there. Then this bit: ans=$(zenity --list --text "What categories shall we show?" --checklist --column "Pick" --column "options" TRUE @pc TRUE @web FALSE @data FALSE @fiction FALSE --separator=" -e "); cat -b /home/USER/Documents/todo/todo.txt | grep -e $ans > /home/USER/scripts/sortedtodo.txt; echo 'grep -e '$ans > /home/USER/scripts/categories.txt; echo '${execi 30 cat -b /home/USER/Documents/todo/todo.txt | grep -e '$ans' > /home/USER/scripts/sortedtodo.txt}' | cat - >> /home/USER/.todoconky ; echo '${color White}${execi 30 cat /home/USER/scripts/sortedtodo.txt | grep -e' $ans'}'| cat - >> /home/USER/.todoconky Yes, that's all one line.
ans=$(zenity  --list  --text "What categories shall we show?" --checklist  --column "Pick" --column "options" TRUE @pc TRUE @web FALSE @data FALSE @fiction FALSE --separator=" -e ") 
This uses zenity to present us with a messagebox with checkboxes for each option. It's actually simpler if you know you'll only show one category at a time; that example's in the code. My categories (or contexts) that I'm searching for are @pc, @web, @data, @fiction. I actually have more, but this gets the point across. It returns $ans with my responses.
cat -b /home/USER/Documents/todo/todo.txt | grep -e $ans > /home/USER/scripts/sortedtodo.txt 
This takes my todo.txt and parses it into a new text file that conky will actually read. Let's say I chose @pc and @web. The actual command passed to grep will be
grep -e @pc -e @web
, because the separator is -e. Sweet, huh? So only items that have @pc or @web in them will be in this text file.
echo '${execi 30 cat -b /home/USER/Documents/todo/todo.txt | grep -e '$ans' > /home/USER/scripts/sortedtodo.txt}' | cat - >> /home/USER/.todoconky 
This adds a line to my conky config file so that it will recreate this same sorted text file every thirty seconds. That way, when I use the todo script to mark something as done, it's automagically reflected in my conky display.
echo '${color White}${execi 30 cat /home/USER/scripts/sortedtodo.txt}' | cat - >> /home/USER/.todoconky 
This adds a line to my conky config file so that it displays the right text. I could have put it in my base copied file, but this makes more procedural sense to me. Same with this line:
echo '${color DarkSlateGray}${hr 2}' | cat - >> /home/USER/.todoconky
. And then the script kills all conky instances and restarts the appropriate ones. There's two things I'd love to be able to do - have the contexts highlighted in conky's display (the same way you would if you had --color=always with grep, and a way to only restart the particular conky instance in question. If you know how, please let me know in the comments! Anyway, here's the script and config! #!/bin/bash # Magic that makes it happen: # One category: #ans=$(zenity --height 300 --list --text "Which context would you like?" --radiolist --column "Pick" --column "Context" TRUE data FALSE pc FALSE web FALSE fiction FALSE nonfiction FALSE secondlife FALSE writing FALSE email FALSE phone); cat -b /home/USER/Documents/todo/todo.txt | grep --color=always @$ans > /home/USER/scripts/sortedtodo.txt # Move base there, overwrite old. cat /home/USER/scripts/todorc_base.txt > /home/USER/.todoconky # use zenity to choose categories. use text files to hold categories ans=$(zenity --list --text "What categories shall we show?" --checklist --column "Pick" --column "options" TRUE @pc TRUE @web FALSE @email FALSE @phone --separator=" -e "); cat -b /home/USER/Documents/todo/todo.txt | grep -e $ans > /home/USER/scripts/sortedtodo.txt; echo '${execi 30 cat -b /home/USER/Documents/todo/todo.txt | grep -e '$ans' > /home/USER/scripts/sortedtodo.txt}' | cat - >> /home/USER/.todoconky ; echo '${color White}${execi 30 cat /home/USER/scripts/sortedtodo.txt}' | cat - >> /home/USER/.todoconky echo '${color DarkSlateGray}${hr 2}' | cat - >> /home/USER/.todoconky killall conky # restart my top-of-screen bar conky -c /home/USER/.conkybar & # start or restart my todo list conky -c /home/USER/.todoconky & todorc_base.txt # Text alignment, other possible values are commented alignment top_left #alignment top_right #alignment bottom_left #alignment bottom_right # Gap between borders of screen and text # same thing as passing -x at command line #gap_x 970 gap_y 40 #maximum_width 300 use_xft yes xftfont verdana:size=9 xftalpha 0.8 own_window yes own_window_type override own_window_transparent yes own_window_colour 262626 own_window_hints undecorated,below,sticky,skip_taskbar,skip_pager double_buffer yes draw_shades no draw_outline yes draw_borders no stippled_borders 10 border_width 1 default_shade_color grey default_outline_color black default_color BADCDD use_spacer none no_buffers yes text_buffer_size 2048 uppercase no color1 F8DF58 update_interval 5 update_interval_on_battery 10 TEXT ${color DarkSlateGray}${hr 2}