This Engineering Notebook post discusses how to handle large numbers of updated nodes within @clean trees. This post proposes several new commands. It may be of general interest to many Leonistas.
Executive summary
Yesterday, I started work at what I thought would be an automatic way of cleaning up changed @clean nodes. I soon realized that this goal was misguided. To state my conclusions first:
- Automatic cleanups have no chance of working, regardless of new settings or directives.
- Instead, we need several new or improved commands that will make it easier to put code exactly where we want it, when we want it!
Background
I have been wondering how to handle large numbers of updated nodes within @clean trees.
The update algorithm guarantees that Leo will write all updated files without changes, regardless of whether new methods get their own nodes. Accuracy is not the question! Rather, the question is, do we care whether updated nodes aren't what we might have produced by hand?
In many cases, we won't care. Even then, "imperfections" in allocating lines to nodes might not bother us.
Otoh, sometimes the nodes that we create by hand wouldn't match what Leo's importers might produce! Oops. Automatically re-importing nodes might be harmful!
I considered creating a new directive, say @norescan, but that would prevent later changes that we want. Such a directive is a non-starter.
The conclusion is inescapable. Automatic splitting of changed @clean nodes is a bad idea. Neither settings nor new directives will magically update some changed nodes but not others. Manual intervention is the only solution.
New commands
The following new commands will split a single node into one or more sibling nodes:
- split-node-at-importer-blocks & split-selection-at-importer-blocks
- split-node-at-cursor
- split-selection-at-importer-blocks
The split-x-at-importer-blocks will be simplified versions of Leo's parse-body command. Experiments indicate that these commands should be reliable and useful.
In contrast, these commands allow us to handle groups of nodes:
- mark-all-changed-nodes & mark-all-changed-nodes-in-tree
- split-marked-nodes-at-importer-blocks
Summary
We have been using @clean nodes since 2015 (Leo 5.1). In that time, nobody has ever complained about the update algorithm. This fact shows that no heroic measures are necessary.
There is no way to update many @clean nodes automagically. Neither new settings nor new directives will allow Leonistas to get exactly the nodes they want.
Instead of automatic updates, a set of new and improved commands is the way forward. These commands will allow us to:
- Split a single node as we wish.
- Split groups of nodes as we wish.
These commands will use simplified versions of code in Leo's importers. All splitting commands will create new nodes as siblings of the original node.
The number and design of these new commands are up for discussion. Your comments are welcome!
Edward
P.S. Leo's parse-body command is similar to recent efforts. We have tolerated this feeble command only because we seldom use it! An improved version of the parse-body command will resemble the split-node-at-importer-blocks command.
P.P.S. The split-node-at-importer-blocks & split-selection-at-importer-blocks commands will not apply to xml or html. These commands will probably only apply to Python, Rust, and perhaps one or two other languages.
EKR
I agree with not always splitting nodes for changes. Someone may have worked hard to get a node tree organized the way they like, and may well want to have a new function or method in the same node as a pre-existing one. Reading a slightly changed @clean file should not change the existing organization. But a command to help splitting up nodes that the user wants to split, that would be valuable.
This Engineering Notebook post discusses how to handle large numbers of updated nodes within @clean trees.
The following new commands will split a single node into one or more sibling nodes:
- split-node-at-importer-blocks & split-selection-at-importer-blocks
- split-node-at-cursor
- split-selection-at-importer-blocks
- mark-all-changed-nodes & mark-all-changed-nodes-in-tree
- split-marked-nodes-at-importer-blocks
I started with a vague direction and a limited purpose: to get parse-body working for Python. At day's end, I had a general framework in which supporting a new language required two statements: an import statement and a new dictionary entry.
These two [lines] could be specified in an @data node in the settings. Then new importers could be added without revising any of Leo's files.
On Fri, Aug 8, 2025 at 7:45 AM Thomas Passin wrote:These two [lines] could be specified in an @data node in the settings. Then new importers could be added without revising any of Leo's files.I doubt it. Anyway, there are better ways to generalize the code.
Hehe. Once again it's easier to do something than to try not to think about it.