Writing the cffm and cfam commands was snap using c.cloneFindByPredicate, a 
powerful new addition to Leo. Here is the entire code for the new commands:

    @cmd('clone-find-all-marked')
    @cmd('cfam')
    def cloneFindAllMarked(self, event=None):
        '''The clone-find-all-marked command.'''
        self.cloneFindMarkedHelper(flatten=False)
        
    @cmd('clone-find-all-flattened-marked')
    @cmd('cffm')
    def cloneFindAllFlattenedMarked(self, event=None):
        '''The clone-find-all-flattened-marked command.'''
        self.cloneFindMarkedHelper(flatten=True)

    def cloneFindMarkedHelper(self, flatten):
        '''Helper for clone-find-marked commands.'''
        
        def isMarked(p):
            return p.isMarked()
            
        self.cloneFindByPredicate(
            generator = self.all_unique_positions,
            predicate = isMarked,
            flatten = flatten,
            undoType = 'clone-find-marked',
        )

It's hard to imagine anything simpler. *Important*: the predicate could 
filter on an attribute or *combination *of attributes. For example, the 
predicate could return p has attributes A and B but *not* attribute C. 
Instantly we have full database query capabilities. If we then hoist the 
resulting node we see *all and only* those nodes satisfying the query.

Here is c.findNodeByPredicate. *Important*: Rev c8a3581c9b corrects a 
serious blunder in c.cloneFindByPredicate. Don't use previous versions!
    
    def cloneFindByPredicate(self,
        generator,     # The generator used to traverse the tree.   
        predicate,     # A function of one argument p, returning True
                       # if p should be included in the results.
        flatten=False, # True: Put all matches at the top level.
        undoType=None, # The undo name, shown in the Edit:Undo menu.
                       # The default is 'clone-find-predicate'
    ):
        '''
        Traverse the tree given using the generator, cloning all positions
        for which predicate(p) is True. Undoably move all clones to a new
        node, created as the last top-level node. Arguments:
    
        generator,      The generator used to traverse the tree.
        predicate,      A function of one argument p returning true if
                        p should be included.
        flatten=False,  True: Move all node to be parents of the root node.
        undo_type=None, The undo/redo name shown in the Edit:Undo menu.
                        The default is 'clone-find-predicate'
        '''
        c = self
        u, undoType = c.undoer, undoType or 'clone-find-predicate'
        clones, seen = [], set(), 
        for p in generator():
            if predicate(p) and p.v not in seen:
                if flatten:
                    seen.add(p.v)
                else:
                    for p2 in p.self_and_subtree():
                        seen.add(p2.v)
                clones.append(p.copy())
        if clones:
            undoData = u.beforeInsertNode(c.p)
            root = c.createCloneFindPredicateRoot(flatten, undoType)
            # This was botched in previous versions.
            # The result was low-level vnode failures.
            for p in clones: 
                clone = p.clone()
                clone.moveToLastChildOf(root)
            u.afterInsertNode(root, undoType, undoData, dirtyVnodeList=[])
            c.selectPosition(root)
            c.setChanged(True)
            c.redraw()
        else:
            g.es_print('not found:', undoType)

Imo, this is the dawn of a new era in Leo's database capabilities.

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 leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.

Reply via email to