Bug or feature?


Sorry for submitting what must look like a distracting bug report now that the Reminders integration is rolling out.

I am attaching a screenshot demonstrating the issue. Project 1 and Project 2 are identical, except that in Project 2 the blank line between Subproject 1 and Subproject 2 actually contains a tab character.

As a result of this tab character, the long red vertical line in Project 2 is unbroken and therefore correctly (in my opinion) indicates both Subproject 1 and Subproject 2 as members of the Project 2 scope.

On the contrary, the scope marker in Project 1 is broken into two parts. Subproject 2 is in this case effectively understood as the child not of Project 1 but of an untitled project. (Note the little red circle on the far left of the blank line between the two sub-projects).

Proof of this is that Select Branch (Cmd-B) selects only the upper half of the project (see screenshot), and leaves Subproject 2 out.

So far so good (almost; in its sensitivity to indentation, TaskPaper is a bit “Python-like”). The real problem, in my view, is that the difference between the two projects is not expressed in the sidebar. Expanding/collapsing Project 1 in the sidebar clearly indicates Subproject 2 as a child of Project 1.


TaskPaper is a tab-indentation outliner, so an intervening line at zero tab-indent is a parent of anything following it with 1 tab indent.

It’s a very simple and very consistent scheme, which makes it quite rugged and reliably predictable, in my experience.

Subproject 2 in your upper diagram is a child of the zero-indented line with no text. That textless parent line is a clickable and collapsible peer of your PROJECT 1.

If you were to make textless lines into special edge-case exceptions to the general tabbed outline model, it might seem helpful in one case, but confusing and unexpected in others.

A lot to be said for simplicity and consistency, I think …


I actually agree with you, @complexpoint. Semantic indentation, indeed as in Python, is a very elegant and, as you say, rugged approach. I do think think it has disadvantages, and it takes some getting used to in this non-programmatic context, but overall the pros outweigh the cons.

That said, don’t you think that the sidebar is behaving inconsistently in this case? If Subproject 2 of the upper diagram is a child of the zero-indented line with no text, then why does it fold in the sidebar under Project 1?


You are correct the behavior is odd/buggy in the case that you describe. It’s a problem that I know about, but don’t see a great solution to. The issues are:

  1. I only want to show projects in the sidebar
  2. Projects can be anywhere in the outline, children of tasks or notes for example

The result is that you can create cases like above where the project is shown, but not all of it’s parents are… and as a result it’s visual parent in the sidebar is incorrect. The two solutions that I’ve considered are:

  1. Always show ancestors (even if not projects) of all projects in the outline in the sidebar.
  2. Or kinda the opposite, only show projects in the sidebar if all of there ancestors are also projects.

Let me know what you think.


Thinking about this more … I think I’ll try to address this wtih solution #2 above … only show projects in sidebar if all of there ancestors are also projects. That solves the visual inconsistency, and gives the option to have projects that don’t show in sidebar. Does break the “projects show in sidebar” rule a bit, but I think visual consistency is better to have.


I see… Yes, I understand the problematics. Not easy to answer.

Would any of the following two alternatives be worth considering?

  1. Consider a whitespace-only line to be, conceptually, a project. But display it in the sidebar (as an untitled fold/unfold toggle) only if it has one or more project-type descendants.

  2. Add the missing whitespace: On saving the document, starting from the bottom and moving upwards, and for every entity that is the child of a blank line, automatically add as many tabs to the blank parent as needed so that it is no longer the parent. (In the top example of the screenshot, this would amount to adding the missing tab character between Subproject 1 and Subproject 2).

(I’m not sure 100% sure that #4 is a correct algorithm but it does look so spontaneously (?))