This is #1539 <https://github.com/leo-editor/leo-editor/issues/1539>. I
assigned this issue to 6.3 because because of this method's long history of
failure.
Yesterday I saw a new approach. If this new approach is sound, and I think
it is, I am willing to consider putting the new code in 6.2.
*Thought experiment*
I considered the possibility the following approach might be the only way:
1. Generate a list of positions meeting some criterion.
2. Delete one of the positions.
3. Regenerate the list of positions meeting the same criterion.
This surely must work. However, c.deletePositionsInList is not privy to the
criterion, so a practical way forward is required.
*Aha: p.position_after_deleting(p2)*
The essence of our woes is that deleting *any *position P in the outline
may affect all the other positions in the list passed to
c.deletePositionsInList. Rather than guessing, we must *compute *the effect
of deleting P on all positions in this list.
p.position_after_deleting(p2) will return None if p will not exist after
deleting p2. Otherwise, it will return the *adjusted* value of p.
Calculating this adjusted value is non-trivial, but surely it is possible.
Something like this:
- If p2 is p or an ancestor of p, p will no longer exist. Return None.
- Otherwise, len(p.stack) will remain unchanged, as will parent.v for
parents in p.stack.
- If p2 is a previous sibling of p_i, (p or one of p's parents), then
p_i.childIndex will decrease by 1.
*A sound algorithm*
The following is untested. Imo, it's ideas are most likely sound.
def deletePositionsInList(self, aList):
"""Delete all positions in the given list."""
c = self
while aList:
# del_p is the next position to be deleted.
del_p = aList.pop()
# Calculate new_positions.
new_positions = []
for p in aList:
new_p = p.position_after_deleting(del_p)
if new_p:
new_positions.append(new_p)
# Delete del_p.
p.doDelete()
# Check the new positions.
for p in new_positions:
assert c.positionExists(p)
# Update aList.
aList = new_positions
# Make sure c.hiddenRootNode always has at least one child.
if not c.hiddenRootNode.children:
v = leoNodes.VNode(context=c)
v._addCopiedLink(childIndex=0, parent_v=c.hiddenRootNode)
# Redraw.
c.selectPosition(c.rootPosition())
Notes:
- aList.pop() ensures that the loop terminates.
- p.position_after_deleting makes it possible to call p.doDelete rather
than vnode-based code.
*Summary*
Since day 1, c.deletePositionsInList has been based on guesswork and
wishful thinking. I am completely responsible for this.
p.position_after_deleting promises to put c.deletePositionsInList on a
solid foundation. I am willing to consider putting the new code in Leo 6.2,
provided a substantial set of unit tests for p.position_after_deleting
exists.
I'll attempt p.position_after_deleting later today. It's time for bed.
All comments welcome.
Edward
--
You received this message because you are subscribed to the Google Groups
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/leo-editor/c835d23d-8e54-49fd-94e2-d770d3b89379%40googlegroups.com.