Disallowing direct "grandchild" relations


I think (but of course will welcome any counterarguments) that it is conceptually flawed to allow direct “grandchildren” in a TaskPaper outline. By this I mean two items that are at least two levels of indentation apart without a mediating entity at the level in-between, for example Action X in the screenshot attached. (A screenshot is the only way to indicate this as Markdown wisely disallows such inconsistent outlines.)

Addressing this issue would not only encourage conceptual sanity among users but also—most importantly and perhaps less controversially—it would make the “Move Up” and “Move Down” actions much more intuitive.


This is a great idea…but how to address it?

I can see that it would be feasible for TP to prevent creation of new grandchildren (by e.g. not allowing use of tab), but how should it handle grandchildren in existing files or situations where a grandchild is created by deleting a section above it?

Instead maybe offer a theming option or other display option to detect grandchildren and allow the user to manually fix them if necessary?

Or run this python script and theme the grandchild tag:



with open("test.taskpaper") as f:
	for line in f:
		tabs = line.count('\t')
		if tabs > lasttabs + 1: print line.strip('\n'), '@grandchild'
		else: print line,
		lasttabs = tabs


Excellent point, and one that i hadn’t thought about.

I can imagine a “consistency check” triggered automatically every time a file is opened or saved. This routine would warn of such inconsistencies and offer two options: either fix the outline (by removing problematic indents) or close the file.

This is not a feature that I would expect to see in a free-form editor like FoldingText but it makes strong sense in an outliner such as TaskPaper. The issue is not merely aesthetic or stylistic. “Action X” in the screenshot is ill-defined. Its level in the tree structure is ambiguous.

(I do wonder how it is represented at the Birch level but have not enough Applescripting chops to check quickly).

UPDATE: Thank you @derekvan for a very handy script.


conceptually flawed to allow direct “grandchildren” in a TaskPaper outline

Funnily enough, I don’t think you can actually get “direct grandchildren” in a TaskPaper outline – even if a line is over-indented by the user, it remains a sibling at the same level of the outline, with the same direct parent, as before the excessive visual indent.

To check this, try a filter like


(Which shows only items at levels one and two)

Even if you have visually overindented one of the level two lines, you will find that it still has not become a “grandchild” in the outline, it will still be a level two line – revealed by /*/* and hidden by /*/*/*

Of course, it might be possible to argue for a block on over-indentation, so that the tab key simply wouldn’t allow you to indent a line beyond its other logical siblings, or more than one tab-stop beyond its parent, but that could, I think sooner or later prove irritating, and might not really be in the spirit of plain text.


Thanks, @complexpoint, indeed a search expression is the best way to demonstrate the problem.

As your example shows, direct grandchildren are impossible at the logical level but perfectly possible at the visual level. So there is the potential for highly misleading conflicts between logical and visual representation, and I am inclined to say that in those cases the outline is ill-formed.

Lines 2, 3, and 4 in the following example are all level-1 at a logical level. Meanwhile, the last line is counterintuitively lower-level (level 2) than both line 2 and line 3.

Needless to say, the visual representation is deceptive. I’d go as far as saying that the outline itself is plainly ill-formed. But in the current implementation such spurious indentations can be common artifacts of copying and pasting content (or murky thinking).

I do appreciate your point about the spirit of plain text—it is the reason we are all here—but in this case it is possible that the cost of inconsistency might outweigh the benefits of expressivity.

Again, I am not sure myself. I am only pointing out a problem which, I think, begs for a strong answer, especially if FoldingText and TaskPaper are to remain distinct and equal citizens in the long-term product lineup.

Perhaps it boils down to an architectural question: is TaskPaper fundamentally a general-purpose plaintext editor with outlining facilities, or is it a dedicated outliner in plaintext, with built-in constraints to safeguard the integrity of the outline?


I’d say the former. I’ve been using tp since 2008 or so and I can only think of a handful of uses where validation would be helpful (here’s one – converting taskpaper files to Keynote presentations – https://github.com/derickfay/key2txt/blob/master/tp2k.applescript – but that’s probably pretty far off the beaten track for most users). Another might be preparing files for import into OmniFocus. But I suspect for most everyday uses strict validation isn’t necessary.

I have a vague memory of a validation script, though – maybe in the TP 2 applescript collection?


One use case I’m thinking of is working with long research outlines and performing surgery on the outline (copy-pasting). In that case I would just want to place the cursor on the destination point, press Cmd-V, and have the copied content pasted in a valid way.

Of course such a constraint would necessitate adjustments when deleting content (or cutting text out into the clipboard), as well. So indeed it would not be a minor change to the logic of the app.


If you want to tidy up an outline (before or after pasting), you can run the script below, which pulls back any over-indentations to the default single-tab-beyond-parent pattern.

If, for example you have pasted in an outline which happens to use 2 tabs for every indent, or you have an authored an outline which you think might acquired some accidental overindentations in the heat of late-night editing and outlining, this should tidy things up, and bring the appearance into line with the underlying outline structure.


(function () {
    'use strict';


    function TaskPaperContext(editor, options) {
        var outline = editor.outline;

        outline.groupUndoAndChanges(function () {
            // adjust indents from bottom up
                .forEach(function (x) {
                    if (x.indent !== 1) x.indent = 1;


    var tp3 = Application('com.hogbaysoftware.TaskPaper3'),
        ds = tp3.documents;

    return ds.length ? ds[0].evaluate({
        script: TaskPaperContext.toString(),
        withOptions: {}
    }) : undefined;



It appears to me to have rather good built-in constraints to safeguard the integrity of the outline - flexible in what it parses, and solidly rigorous in how it parses.

  • You can use multiple indents if you want to, for flexibility in formatting, for example,
  • but the outline already refuses to create any ‘direct grandchild’ relationships in its model.

The internal model even records any overindentations in the layout, and allows scripts to see, change, or create those overindentations.

(See the script above, and the .indent property of items)


There’s always a balance to be struck between flexibility and ‘magic’ - I personally appreciate this default combination of flexibility in formatting, with rigour in interpreting outline structure.

Mileage may vary, but if your workflow can benefit from a bit more magic (and a bit less flexibility) here, then scripts may well be able to provide those added constraints and automations.


I think this has been worked out in this thread… but this is actually by design and something that I don’t expect to change.

The reasons are:

  1. The underlying logical outline is always consistent. In the original example the over indented “Action X” is a logical sibling of “Action 2.1”. So there’s no logical inconsistencies… just visual.

  2. And the visual inconsistencies are required unless I constrain moment in the outline… I’ve tried that. It’s logical, but it gives the editor a “constrained outlinery” type feel. So instead I allow fee movement with no constraints, but must allow this visual break to allow for that.


Thanks for these replies. I do maintain that a strict coordination (@jessegrosjean’s “constrained outlinery”) between visual hierarchy and logical representation would be preferable. I am not being dogmatic—I have just never had a good use for this degree of freedom, and on the contrary have repeatedly found it distracting and time-wasting.

But I also realize this might manifest too dull or “academic” (in the worst sense of the word) an approach to outlining. :smile:

@complexpoint, thank you very much for your script, which does help a lot.


I guess you could experiment with automating that constraint, if it seems useful to your workflow, by using a TaskPaper-only macro which follows the tab key with some indent-normalizing code.

In Keyboard Maestro, for example, you would put the macro in a Taskpaper-only folder,

and its contents might be some variant of this:
Experiment with preventing over-indentation.kmmacros.zip (9.6 KB)


A great experiment—I’ll certainly try it. I had no idea that KM was so versatile. Thanks, @complexpoint.