Taskpaper editor: is this the right approach?

I am creating a TaskPaper editor using ProseMirror. The TaskPaper format is plain text that gives special meaning to certain sequences of text.

My goal is add functionality on top of a regular text editor. For example:

  • Syntax highlighting of projects and tags
  • Folding child projects/tasks
  • Focus on a single project/task
  • Filtering

The TaskPaper app already has most of these features, but it’s Mac-only and there are some additional features I would like to add like sorting by @priority(value) tag. For more background, todo-taskpaper.leftium.com is a related project using CodeMirror where you can explore the TaskPaper format and associated API.

First question: is this possible? Or am I trying to use ProseMirror for something it not suited for? At least one person tried to do something similar with markdown.

Then, what is the best approach? The first idea I had no longer seems to be the best route; I thought of other ways that might work better. I will describe them below:

At first, I thought I needed to write a ProseMirror schema for TaskPaper files. So I tried to come up with a BNF grammar here. With this Taskpaper schema, input rules could be used to convert a “note” node to a “project” node when : is typed. “Task” and “tag” nodes could be created when - or @ is typed. However, there doesn’t seem to be a simple way to convert these nodes back to plain “note” nodes when they no longer match the proper syntax (for example when the @ is deleted from a tag or inserted in the middle of a tag name).

However, perhaps a custom schema is not required. Schemas seem to enforce what type of content is allowed; Taskpaper files allow just about any sequence of text; it’s just that the interpretation of the text might change if you add/remove the right special characters (/[:-@()\t\s]/). Maybe just enforcing the rule that all lines start with (optional) tabbed indentation (and not spaces) would be enough. Then I could just decorate stuff like tags and projects a la the linter example.

Since a Taskpaper file is just a list, I also considered starting with just the ProseMirror list schema for a base. However, ProseMirror lists don’t maintain indentation when copy/pasting to a plain text file.

Based on my current understanding of ProseMirror this seems to be the best approach:

  • Use a simple text schema that only enforces indentation with tabs. (The schema doesn’t know about concepts like projects, tasks, tags, and notes. Is there any value to a custom Taskpaper schema that does know about these concepts?)
  • Augment the basic text editor with TaskPaper features like syntax highlighting similar to the ProseMirror linting example.
  • Each line of plain text will be a node in the document, but I’m torn on whether they should be organized as a flat list or tree based on indentation. The tree structure would help with the folding/focus features, but it seems to make the schema and copy/pasting parts more difficult.

Are there any other approaches I haven’t thought of, yet?

I’m not familiar with Taskpaper, but this sounds like it is a text-file oriented format, and you want to embrace that textual editing (using sigils like @ to indicate node type). For that, using a text editor (like CodeMirror) might be more suited. The way to do this in ProseMirror would be, I think, to hide the sigils, and use other UI patterns (menus, keyboard shortcuts) to change the type of the nodes. You can still use some typed patterns as shortcuts, but if you make them disappear and change the node type (as the input rules for headers and such in the ProseMirror demos do), they indeed don’t provide a good way to change node types after the fact.

Sometimes keeping the sigils is desired, like in the main text-editing view. But I planned additional synchronized views where other UI patterns could be used (like a view that organized items on a calendar). So a task could be created/edited via both the text view and the calendar view.

At first glance, ProseMirror seemed promising because it was designed with collab from the start. Maybe the schemas would even help. However, implementing with ProseMirror was more difficult than I expected.

I tried using CodeMirror a long time ago to develop this, but ran into some challenges like:

  • My synchronization between views was very primitive/buggy and did not have the benefit of transactions.
  • (And if I remember correctly) CodeMirror doesn’t like when its contents have varying heights/widths (for inline controls and syntax highlighting.)

Looking forward to CodeMirror v6!

That has been supported since version 3 in 2012.

But yeah, solid collaborative editing is still tricky with CodeMirror. That should indeed change with version 6.

I made some progress adapting PM for TaskPaper: https://taskmirror.glitch.me/

I gave up trying to encode TaskPaper features/structure in the schema and just store a flat list of items as divs. I added TaskPaper syntax highlighting following the linter example. I think I can add other TaskPaper features using a similar strategy.

I took the basic example and made these changes:

  • Enabled TAB input (instead of the browser default of focusing on the next element.) And preserved white space.
  • Modified clipboardTextSerializer so “tight lists” are copied to the clipboard. Copy-paste to/from TaskPaper text files seems to work, now.
  • Added syntax highlighting via decorations.

View the code here: