Skip to content

Comments

Support dynamic node edits#77

Open
Idorobots wants to merge 13 commits intokarlicoss:masterfrom
Idorobots:dynamic-edits
Open

Support dynamic node edits#77
Idorobots wants to merge 13 commits intokarlicoss:masterfrom
Idorobots:dynamic-edits

Conversation

@Idorobots
Copy link

@Idorobots Idorobots commented Feb 22, 2026

This is in reference to #11 and #76

I wanted to be able to modify parsed nodes and dump them to a file for a project I'm building. This code was written with AI (Codex 5.2 thinking primarily) but I was in the loop for every change made.

Here's how this works:

  • A new abstraction for LineItem is added that represents a parsed line of an org nodes text. There are subclasses for each supported Org function (dates, properties, headline etc).
  • Initially all lines are TextLines to preserve the 1-to-1 representation when using __str__.
  • When a property is set, the corresponding line is replaced with a semantic instance of LineItem. If one wasn't present for a specific property (node.scheduled = date when there was no previous scheduled date parsed from file) one is inserted.
  • If a change is made via the setters, the node's lines are marked as dirty, and the representation is regenerated from the _line_items instead. That's how the edits are made possible.
  • The _lines with the original file contents are still available, as a performance optimization, for the usual use-case of just parsing the nodes without making any modifications to them.

I also considered creating _line_items lazily, on first write, as another optimization, but didn't do that in the end - seems to be performant enough, my 37k task archive loads in 2.32s on current master and in 3.71s on this branch. Let me know if this is acceptable.

I mostly added unit tests for the new functionality as the current functionality is mostly left unchanged.

The body editing is pretty awkward as it requires a line index since bodies can be not contiguous and can contain timestamps etc.
Similarly, edge cases such as duplicated logbook drawers are equally awkward.
This PR also permits children modification, so essentially adding subtrees and moving them around the file (but only within the same OrgEnv.)

I reorganized the code a little bit and reexported the relevant functions back from the node module, to keep the API stable.

Technically, these new LineItems could replace the old attributes like _heading etc, entirely, but I opted to keep the old attributes in, at least until I get some comments on the general approach here - with richer representation it'll be easier to add support for links, etc, as part of the heading for instance.

I went ahead and made the "new" representation the only available one (without changing the public API).. That uncovered a few issues, but these were fixed and now my archive loads and looks correct. It also sped things up a bit - archive now loads in 2.68s.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant