I use TP as a daily tracker. Can you help me automate the start of my day?


#1

Hi, Taskpaper geniuses!

I have tried time and again to find a task manager that fit my habits, and all of them were too feature-rich…but Taskpaper is just about perfect. I use it as a daily activity tracker at work—the scopes of the projects I work on (as a copywriter) aren’t clearly defined, so it’s difficult to track my responsibilities on a per-project basis, and I’ve found that the best way for me to get everything done is to have a list that follows me day-by-day, growing as new things are assigned and shrinking as I complete tasks from the list. I like to move the list as a whole to a new header every day, then leave behind the items I’ve finished so that I generate a work history list as I go forward.

I’d like to write a script that I can trigger with Alfred that creates a new header for the day and moves all open tasks into it, maintaining the tree structure that exists in it. Can anyone help me work this out? Alternatively, if you have a GTD system in place with TP that works kind of like a daily calendar, I’m all ears!

Thanks! (Also, Jesse, I’ve been a fan of WriteRoom for many years…thanks for your awesome apps!)


#2

Do you have a specific keyword for the parent project in order to know what you will be moving to the next day? Can you describe the set of steps that this script is supposed to follow?

I have never spent the necessary time to become proficient in JAvaScript, but I think that there might be a couple of examples in the script page that may be easily modified to accomplish what you want.

I am also not sure if you have also seen the TaskPaper month generator. I think it would be helpful to your particular system.


#3

Hello bonbonelan,
could you please give an example of your system?

TIA


#4

Thanks for responding, folks.

Here’s what my TP file basically looks like:

Inbox:
-I drop text into this space using an Alfred workflow
March 2018:
-3/1/18:
-tasks finished on 3/1/18
-3/2/18:
-tasks finished 3/2/18
…etc
3/29/18:
-task 1
-task 2
-Project task (with susbtasks indented beneath)

For the example, I’d want the script to create a 3/30/18 header and move all unfinished tasks beneath it.

Using Alfred, I think I could do something like this: newday (or newday {query}, where {query} is the date I enter), then have Alfred execute a script or workflow that does this:

  1. Find the most recent date’s header (which won’t always be the day before, i.e. friday-monday)
  2. Move all @done items to the top of the list
  3. Create a new header with today’s date (or whatever’s in {query})
  4. Do one of the following: a) move the header between the last @done item and the first unfinished item, or b) move all unfinished items, maintaining their indentation structures, under the new header.

Thanks for your help!


#5

For what it’s worth, I think that TeuxDeux is gorgeous and has the kind of daily tracking function I’d love to be using in TP.


#6

Sorry for the delay. Did you check the link to the TaskPaper month generator above?

I think that the beauty of TaskPaper is that it is a very powerful engine that allows you to do things your way. I actually use TaskPaper as a database of sorts where I end up putting all kinds of information in different files. I have gotten pretty good at complex queries for that reason. The best part is that those “databases” are readable and can be shared with others without “a program”.

You can implement a GTD system very easily. The key is to learn to use the “Move to Project” and you are good to go. Just put your initial tasks in the “Inbox:” and the move the tasks to the project as you review your things. Seriously, if you haven’t try the “Move to project…” you are missing something. I honestly cannot understand the reasons behind your system, but if you are comfortable with that, more power to you. That is the good thing about TaskPaper. But maybe you can try something like “NotePlan”. It seems to be more accord with your particular system. Just be aware that although Noteplan does some things very well, it does nothing else but that.

Hope this helps.


#7

Hi! Thanks for checking back in! A kind stranger at work helped me write out the automation in JavaScript. It’s not a perfect solution (it misbehaves with some headers and some tasks with colons in them) but it works spectacularly well with my setup. Here’s the code:

function() {
	'use strict'
	
	function TP3Function(editor, options) {
		
		var outline = editor.outline;
		var todayNode = setupTodayNode();
		
		var tasksToAdd = [];
		var level1Nodes = outline.root.children;
		for (var i = 0; i < level1Nodes.length; i++){
			var l1Node = level1Nodes[i];
			if (l1Node.hasChildren) {
				var level2Nodes = l1Node.children;
				for (var j = 0; j < level2Nodes.length; j++) {
					var l2Node = level2Nodes[j];
					if (l2Node.hasChildren) {
						processNode(l2Node, "", tasksToAdd); //Looking two levels down based on Elan's TaskPaper structure
					}
				}
			}
		}
		
		for (var i = 0; i < tasksToAdd.length; i++) {
			var aTask = tasksToAdd[i];
			addTaskToToday(aTask, todayNode);
		}
		
		var allItems = outline.items;
		for (var i = 0; i < allItems.length; i++) {
			var anItem = allItems[i];
			var itemText = anItem.bodyString;
			if (itemText.indexOf("@remove") > -1) {
				anItem.removeFromParent();
			}
		}
		
		var allItems = outline.items;
		for (var i = 0; i < allItems.length; i++) {
			var anItem = allItems[i];
			var itemText = anItem.bodyString;
			if ((itemText != "") && (!anItem.hasChildren) && (itemText != "Inbox:") && (itemText.indexOf("-")!=0)) {
				anItem.removeFromParent();
			}

		}
		
		
		function addTaskToToday(aTask, todayNode) {
			var taskPath = aTask.taskPath;
			var pathNodes = taskPath.split("||");
			pathNodes.shift(); //First node is old date
			pathNodes.pop(); //Last node is blank
			var nodeForTask = getPathForTask(todayNode, pathNodes);
			nodeForTask.appendChildren(outline.createItem(aTask.taskText));
		}
		
		function getPathForTask (todayNode, pathNodes) {
			var currentNode = todayNode;
			for (var i = 0; i < pathNodes.length; i++) {
				var nodeName = pathNodes[i];
				if (currentNode.hasChildren) {
					var foundNode = false;
					var nodeChildren = currentNode.children;
					for (var j = 0; j < nodeChildren.length; j++) {
						var childNode = nodeChildren[j];
						if (childNode.bodyString == nodeName) {
							currentNode = childNode;
							foundNode = true;
						}
					}
					if (!foundNode) {
						currentNode.appendChildren(outline.createItem(nodeName));
						currentNode = currentNode.lastChild;
					}
				} else {
					currentNode.appendChildren(outline.createItem(nodeName));
					currentNode = currentNode.lastChild;
				}
			}
			return currentNode;
		}
		
		function processNode(aNode, aPath, tasksToAdd) {
			var childNodes = aNode.children;
			var nodeText = aNode.bodyString;
			if (!nodeText) {
				return;
			}
			
			aPath = aPath + nodeText + "||";
			
			for (var i = 0; i < childNodes.length; i++) {
				var childNode = childNodes[i];
				if (childNode.hasChildren) {
					processNode(childNode, aPath, tasksToAdd);
				} else if (childNode.bodyString.indexOf("@done") == -1) {
					var taskToMove = {taskPath: aPath, taskText: childNode.bodyString};
					tasksToAdd.push(taskToMove);
					childNode.bodyString = childNode.bodyString + " @remove";
				}
			}
		}
		
		function setupTodayNode() {
			var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
			var d = new Date();
			var monthName = monthNames[d.getMonth()];
			var thisYearLong = d.getFullYear();
			var thisYearShort = d.getYear().toString().substr(-2);
			var thisMonth = d.getMonth()+1;
			var thisDay = d.getDate();
			
			var todayString = thisMonth + "/" + thisDay + "/" + thisYearShort + ":";
			var thisMonthString = monthName + " " + thisYearLong + ":";
			
			var todayNode = outline.createItem(todayString);
			var topLevelNodes = outline.root.children;
						
			for (var i = 0; i < topLevelNodes.length; i++){
				var aNode = topLevelNodes[i];
				if (aNode.bodyString == thisMonthString) {
					aNode.appendChildren(todayNode);
					return aNode.lastChild;
				}
			}
			outline.root.appendChildren(outline.createItem(thisMonthString));
			outline.root.lastChild.appendChildren(todayNode);
			return outline.root.lastChild.lastChild;
		}
	}
	
	Application("TaskPaper").documents[0].evaluate(
		{script: TP3Function.toString()
	})
})();

#8

That is awesome.