p.deletePositionsInList is at the trunk at rev 3198.  I believe this
very tricky code works, even for clones.  A substantial unit tests
also works, and it does test clones.

Please test this in your code/plugins, and report any problems
immediately.

Passing an iterator to the method just adds needless complication.
Instead, 'self' (the receiver, in SmallTalk parlance) now specifies
the starting node of the traversal, and afterLastNode specifies the
node *after* the last node to be traversed.

Here is p.deletePositionsInList. As you can see, the docstring is
longer than the code.  Read the docstring carefully or suffer the
consequences!

def deletePositionsInList (self,afterLastNode,aList,callback):

    '''Traverse the nodes from self up to but *not* including
afterLastNode. The
    traversal continues to the end of the outline if afterLastNode is
None. The
    **range** of the traversal is the set of nodes from self to the
node
    *before* afterLastNode.

    This method calls the callback for any position in aList found in
the range,
    excluding any node whose ancestor has already been passed to the
callback.

    The callback takes one explicit argument, p. As usual, the
callback can bind
    values using keyword arguments. The callback may delete p or move
p out of
    the range. The callback **must not** move p within range.
    '''

    p = self.copy()
    after = afterLastNode and afterLastNode.copy()
    while p and p != after:
        if p in aList:
            next = p.nodeAfterTree()
            callback(p.copy())
            p = next
        else:
            p.moveToThreadNext()

Edward

P.S.  Here is how Leo uses deletePositionsInList to handle resurrected
nodes::

def deleteUnvisitedNodes (self,root):

    '''Delete unvisited nodes in root's subtree, not including root.

    Actually, instead of deleting the nodes, we move them to be
children of the
    'Resurrected Nodes' r.
    '''

    at = self

    if not root.hasChildren():
        return

    # Carefully set up the arguments.
    aList = [z.copy() for z in root.subtree() if not z.isVisited()]
    r = at.createResurrectedNodesNode()
    afterLastNode=root.nodeAfterTree() # Do this *after* creating r!
    callback=at.defineResurrectedNodeCallback(r,root)

    # Now move the nodes.
 
root.firstChild().deletePositionsInList(afterLastNode,aList,callback)

def createResurrectedNodesNode(self):

    '''Create a 'Resurrected Nodes' node as the last top-level
node.'''

    at = self ; c = at.c ; tag = 'Resurrected Nodes'

    # Find the last top-level node.
    last = c.rootPosition()
    while last.hasNext():
        last.moveToNext()

    if last.h == tag:
        # The 'Resurrected Nodes' node already exists.
        p = last
    else:
        # Create the 'Resurrected Nodes' node after 'last'.
        p = last.insertAfter()
        p.setHeadString(tag)

    p.expand()
    return p

def defineResurrectedNodeCallback (self,r,root):

    '''Define a callback that moves node p as r's last child.'''

    def callback(p,r=r.copy(),root=root):

        '''The resurrected nodes callback.'''

        child = r.insertAsLastChild()
        child.h = 'From %s' % root.h
        p.moveToLastChildOf(child)

        if g.unitTesting:
            # g.trace(p.h,r.h)
            pass
        else:
            g.es('resurrected node:',p.h,color='red')
            g.es('in file:',root.h,color='blue')

    return callback

EKR

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/leo-editor?hl=en.

Reply via email to