Here’s a screenshot of how I used to use TeuxDeux:

Oh. No, actually I stupidly forgot to take one before I deleted my account. I’ll have to make do with drawing one instead:

MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY
# 20% # MENTORING # PROJECT 2 # PROJECT 2 # 20%
         
Unplanned 1   Task 3 Task 5 Unplanned 2
         
# PROJECT 1 # MENTORING # PROJECT 2 # PROJECT 1  
         
Task 1   Task 4 Task 6  
Task 2        
         
# HOME # HOME # HOME # HOME # HOME
         
  Ironing   Ironing  

I split my working week into nine slots, i.e. mornings and afternoons; Friday is one slot as it’s a half day. I then allocated eighty percent of my time to planned activities. The remaining twenty percent isn’t “free” time, just me being realistic about all the unplanned stuff I get asked to do; whether my manager believes it or not. Perhaps I shouldn’t have time allocated to unplanned work on a Monday morning, but I’m also being realistic about it being Monday morning. Since “Project 1” is/was supposedly winding down I didn’t mind splitting that between the start and end of the week. As everything in TeuxDeux is a task I had my headings (# HOME, etc) as recurring tasks. I know full well that just because I’ve planned my week to be allocated this way that it might not happen; However, I do want the headings there as a gentle reminder so I know what I’m supposed to be working on.

I still really like TeuxDeux. It is really simple, speedy and as flexible as you want it to be. It really is like pen and paper, but perhaps actually a little bit better. I had tried many other applications that in theory should have been better than TeuxDeux because they were the kind of thing that if I were designing a todo application would be exactly what I’d do, but in reality I found too fiddly to use. With TeuxDeux it just click, type, done. But ever since the Neux TeuxDeux launched the old API now longer worked which meant my simple command line app also no longer worked; It’s been a year and I don’t think they are in a rush to release the new API. And after getting my new laptop I need command line access more than ever.

I can’t particularly recall how and why I decided on Taskwarrior. It is overkill for my needs. It’s C++. It’s quite probably thousands of lines of C++. For a todo application! It uses plain text files, good, but not in anyway you can really interact with them outside of Taskwarrior. But it is command line based and is malleable enough that I could create a TeuxDeux like experience.

Firstly, I wanted some kind of obvious heading or separator. Taskwarrior has built in support for projects and tags which I thought of using for this purpose, but I decided to use some user defined attributes for reasons I’ll come to. So my Taskwarrior version of TeuxDeux looks like this:

ID  Slot       Due              Description
  - ---        Mon Apr 28, 2014 ---
  - 20%        Mon Apr 28, 2014 # 20% _am_
  -            Mon Apr 28, 2014 Do something
  - PROJECT 1  Mon Apr 28, 2014 # PROJECT 1 _pm_
  -            Mon Apr 28, 2014 This project will never die
  - HOME       Mon Apr 28, 2014 # HOME
  -            Mon Apr 28, 2014 Finishing transferring tasks from TeuxDeux
  - ---        Tue Apr 29, 2014 ---
  - MENTORING  Tue Apr 29, 2014 # MENTORING _am_
  -            Tue Apr 29, 2014 Go to see X 
  - MENTORING  Tue Apr 29, 2014 # MENTORING _pm_
  -            Tue Apr 29, 2014 Phone call with Y
  - HOME       Tue Apr 29, 2014 # HOME
  -            Tue Apr 29, 2014 Investigate smtps on postfix
  - ---        Wed Apr 30, 2014 ---

(The IDs are blank here as the tasks are completed, and I’ve only shown half of the week). It’s a vertical layout instead of horizontal, but it does the same thing. I have a user defined attribute called “ord” that I used to ensure my slots and tasks are in the correct order. I like having the Slot column with white-space between slots and clearly identifiable starts to the days (“—”); This is one reason why I decided not to just use the Project attribute instead of dedicated tasks as headings. This is the report definition I have in Taskwarrior:

#Custom report - Teuxdeux
report.teuxdeux.description=TeuxDeux style
report.teuxdeux.sort=due+,ord+,sep-
report.teuxdeux.filter=(status:completed or status:pending) and due.before:sow
report.teuxdeux.columns=id,sep,priority,due,description.truncated
report.teuxdeux.labels=ID,Slot,Pri.,Due,Description

I have something along the lines of the “Someday” lists in TeuxDeux as well:

#Custom report - Someday
report.someday.description=Someday
report.someday.sort=project+,tags+
report.someday.filter=(status:completed or status:pending) and due:
report.someday.columns=id,project,tags,description.truncated
report.someday.labels=ID,Project,Tag,Description

The second thing I wanted was to replicate the automatic rolling over of uncompleted tasks from Teuxdeux I have a couple of commands that run sequentially from crontab at midnight (my first stupid mistake was having as two separate cron tasks which executed simultaneously and corrupted my files):

task $(task sep: status:pending due.before:today ids) rc.confirmation:no rc.bulk:100 modify due:today ord:4 < ~/.
  taskcronin;task $(task sep.isnt: status:pending due.before:today ids) rc.confirmation:no rc.bulk:100 done < ~/.taskcronin

This is another reason why I have a user defined attribute for the separator: I can easily identify between them and real tasks. The first command takes anything that’s not a separator (so any real task) that isn’t complete and moves them over to the next day, setting the “ord” to 4 to move them to the bottom of the list. The second part just closes off the separators, so in that way better than TeuxDeux. The taskcronin bit is a bit of hack. It’s just a text file containing “a” to answer the “all” prompt should it come up since there is no corresponding rc setting to override this.

The last thing I needed to do was to have a week at a time view. The “Teuxdeux” report format I defined above shows everything up until the end of the week and also shows completed tasks, good, but there is no limit on how far back it’ll show completed tasks so they would just accumulate. TeuxDeux does a rolling 5 day look ahead with 1 day look behind. I decided to things slightly differently for now and have a week at a view time, but only roll over to the next week at the start of the week. In order to do this I had to make a small wrapper function in my shell as I couldn’t find a way to refer to past dates in Taskwarrior (there is “sow” for “start of next week”, for instance):

function td {
	if [[ -z "$@" ]]; then
		task due.after:$(date -d 'last sunday' +%F) teuxdeux
	else
		task "$@"
	fi
}

This means I just type “td” I’ll get my week-at-a-view report, but otherwise it just acts as an alias to “task”.

And that is pretty much it. To switch over from TeuxDeux I re-created my recurring tasks. For the someday tasks I did a bit of formatting of the backup/export from TeuxDeux in Vim and then used a simple loop in the shell to add each list to Taskwarrior, and for my Someday lists I do make use of Projects and Tags; Projects identify each Someday list with tags, so far, used to categorise each entry as “Need to do”, “Maybe”, and “Nice to have”. I didn’t bother importing my entire completed task history, just the items for the week in which I switched.


[EDIT: 2014-05-09] If you want something more along the lines of the Neux TeuxDeux rolling five day style then you can skip having to define any shell command and just define the following report:

#Custom report - Teuxdeux rolling
report.roll.description=Neux TeuxDeux style
report.roll.sort=due+,ord+,sep-
report.roll.filter=(status:completed or status:pending) and due.before:5days and due.after:-2days
report.roll.columns=id,sep,priority,due,description.truncated
report.roll.labels=ID,Slot,Pri.,Due,Description

I realise this is a seven day span and not five, but why not?


[EDIT: 2014-06-26] I’ve also started playing with task dependencies so I have amended my reports to filter out blocked tasks (using -BLOCKED).

Ideally what I like to be able to do is have dynamic/variable due dates for tasks, so that I could say the due date for Task 2 is the due date of Task 1 plus one day, for instance. Then, if Task 1 rolled over the next day (via my cron set-up), Task 2 would also be pushed a further day out.

I don’t think there is anyway of doing this within Taskwarrior, but as mentioned, I can use task dependencies to block and filter out tasks from my reports. So, say for example, I start out with Task 1 today and Task 2 tomorrow, but dependent on Task 1, if I don’t get around to Task 1 it will roll over to the next day and sit with Task 2. If I don’t get around to it for another day then both tasks will roll over, but forever remain on the same day. However, as long as I’m filtering them out with -BLOCKED it doesn’t matter as I won’t see Task 2 until I’ve finished Task 1.

This is probably the best I can manage (quickly) at the moment without getting into setting up a more complicated cron tasks that also pushes out dependent tasks by one day if their dependent task rolls over.


[EDIT: 2014-06-26] I also wish Taskwarrior had a report column to indicate the presence of annotations. I thought it did, but when I went to add it to my report I couldn’t find it. Assuming it really isn’t there, I might investigate adding this in.


[EDIT: 2015-01-09] Taskwarrior 2.4.0 broke my rolling Teuxdeux report so I’ve gone back to defining it in the shell. I now have this function defined:

function td {
	if [[ -z "$@" ]]; then
		task due.after:$(date -d 'last sunday' +%F) due.before:sow teuxdeux
	elif [[ "$@" == "roll" ]]; then
		task due.after:$(date -d 'today -2days' +%F) due.before:$(date -d 'today +6days' +%F) teuxdeux
	else
		task "$@"
	fi
}

Which gives me both the original fixed Teuxdeux style and the newer rolling style (note that I’ve corrected it so it does actually give me seven days and not six - I got it wrong in my edit of 2014-05-09). And then in my .taskrc I have the teuxdeux report defined as follows:

#Custom report - Teuxdeux
report.teuxdeux.description=TeuxDeux style
report.teuxdeux.sort=due+,ord+,sep-
report.teuxdeux.filter=(status:completed or status:pending) and -BLOCKED and -graveyard
report.teuxdeux.columns=id,sep,priority,due,description.truncated_count
report.teuxdeux.labels=ID,Slot,Pri.,Due,Description

*** Also see Taskwarrior, Teuxdeux style, an update] ***