TaskPaper 3: Child-aware Archiving
TaskPaper 3 is a critical part of my workflow.1 I use it to track what's happening now and what's up next, but also what I've done recently. Having a log of recent tasks is great during times of retrospection or when timeline questions come up.
In TaskPaper, completed tasks are tagged with @done
. The built-in
"Archive" action moves all done tasks to an "Archive" Project.
Unfortunately, Archive will also disconnect child tasks from their
parents:
Fortunately, TaskPaper is scriptable with JavaScript, and we can create a custom action with archiving more to my liking.
Goals
Ideally, we would not move child tasks to the Archive until their parent task is complete. The default behavior disconnects children from their parents, losing important context. Here's a document before archiving:
Inbox:
- Build login page @due(2018-12-01)
- Add auth0 library to composer.json @done(2018-08-17)
- Write tests
- Create tables
- Book hotel for trip to sf @done(2018-06-10)
- Get corporate card @done(2018-06-10)
And, after archiving:
Inbox:
- Build login page @due(2018-12-01)
- Write tests
- Create tables
Archive:
- Add auth0 library to composer.json @done(2018-08-17)
- Book hotel for trip to sf @done(2018-06-10)
- Get corporate card @done(2018-06-10)
Our history no longer tells us why the auth0 task existed. My preference is to keep the hierarchy, and only archive the "top-level" tasks that sit directly below a Project.
The "Smart Archive" extension
Here's an extension that accomplishes our goal.
- Ensure an "Archive" project exists
- Find all
@done
tasks that are immediate children of projects (excluding the Archive project) - Move these items to the Archive, preserving their current order in the document
var TaskPaper = Application('TaskPaper');
function fn(editor, options) {
var outline = editor.outline;
var archive = outline.evaluateItemPath("//Archive:")[0];
var insertBeforeElement = archive ? archive.firstChild : undefined;
outline.groupUndoAndChanges(() => {
if (typeof archive === "undefined") {
archive = outline.createItem("Archive:");
outline.root.appendChildren(archive);
}
var topLevelItems = outline.evaluateItemPath("project/@done except Archive//*")
topLevelItems.map(item => {
item.removeFromParent();
if (insertBeforeElement) {
archive.insertChildrenBefore(item, insertBeforeElement)
} else {
archive.appendChildren(item);
}
});
});
}
TaskPaper.documents[0].evaluate({
script: fn.toString()
})
If we install this script to the TaskPaper Scripts folder, we can quickly run it
using cmd-shift-P
and typing the script name. I find it's also helpful to
rebind the default Archive shortcut in the Keyboard preference pane to
combat muscle memory.
For more information about TaskPaper scripting, see the Scripting API, Extensions Wiki, and script installation guide.
- For more about why I like and how I use TaskPaper, see IFTTT and Taskpaper TODO Workflow. ↩