On Thu, Jul 8, 2010 at 3:51 AM, Ville M. Vainio <[email protected]> wrote:
> On Thu, Jul 8, 2010 at 3:40 AM, Brian Theado <[email protected]> wrote:
>
> These methods could also be added to 'poslist' class that you get from
> find_h / find_b. LeoTreeql is basically the same thing with the
> difference that it doesn't inherit from list.
>
Just to play around with it, I added select_h and select_b to
LeoTreeql. The equivalent LeoTreeql code is more explicit than
poslist but rather more verbose. With poslist:
c.find_h('@thin.*py').select_h('class.*').select_b('import (.*)')
should be similar to this in LeoTreeql:
LeoTreeql(p).\
all_positions().select_h('@thin.*py').\
children().select_h('class.*'). \
children().select_b('import (.*)')
I have only minimal experience with Python (just from playing around
with Leo a few times over the years) and don't know all the tradeoffs
between lists and iterables. I just know the itertools module and
Leo's built-in iterators made this easy to implement.
I discovered in the Python docs I could make the LeoTreeql class
itself an iterable just be renaming the 'it' method to '_iter_', so
this:
LeoTreeql(p).clones().parent().it()
becomes:
LeoTreeql(p).clones().parent()
Here is my latest code:
class LeoTreeql:
def __init__(self,p):
# The initial iterable is just the given p as a list.
# With each step in the chain, this iterable will be
# refined as a composition of the new iterable upon the
# results of the old iterable. After each step self.i
# will be a flat iterable containing position elements
self.i = [p]
self.p = p
def __iter__(self):
# With this method, LeoTreeql objects themselves are iterable
return self.i
def mapchain (self,f):
# This method is intended for a function f which takes a position
# as input and outputs an iterable of positions. That function
# is mapped over the self.i iterable of positions. Then
# chain.from_iterable is used to flatten the "iterable of
# iterables of position" to just "iterable of positions"
self.i = itertools.chain.from_iterable (itertools.imap (f, self.i))
return self
def map (self, f):
# For functions that map a single 'p' to another 'p'
self.i = itertools.imap(f, self.i)
return self
def slice (self, *args):
self.i = itertools.islice(self.i, *args)
return self
def filter (self, f):
self.i = itertools.ifilter (f, self.i)
return self
def subtree (self):
# Pass in the "subtree" method of the position class as the
# refining iterable
return self.mapchain(type(self.p).subtree)
descendants = subtree
def self_and_subtree (self):
return self.mapchain(type(self.p).self_and_subtree)
def children (self):
return self.mapchain(type(self.p).children)
def parents (self):
return self.mapchain(type(self.p).parents)
ancestors = parents
def parent (self):
# Mapchain not needed here since p.parent() returns
# just a single position and not an iterable of
# positions
return self.map (type(self.p).parent)
def following_siblings (self):
return self.mapchain(type(self.p).following_siblings)
def self_and_siblings (self):
return self.mapchain(type(self.p).self_and_siblings)
def root (self):
# This is a strange one. Leo's root is not the parent of all toplevel
# nodes, it is simply the first toplevel node. So walking the whole
# tree is not q.root().descendants() and instead is
# q.root().following_siblings().descendants()
# Strange only because that is a different definition of root than
# I've seen before
return self.map(type(self.p).findRootPosition)
def toplevels (self):
return self.root().self_and_siblings()
def all_positions(self):
return self.toplevels().self_and_subtree()
def clones(self):
# My own all_positions that doesn't depend on 'c', since this
# class only knows about 'p'
def all_positions (p0):
p = p0.findRootPosition()
while p:
yield p
p.moveToThreadNext()
raise StopIteration
def clones_iter(p0):
def isCloneOf(p1,p2=p0):
return p1.v == p2.v
# Finding clones of a node involves searching the whole tree
return itertools.ifilter (isCloneOf, all_positions(p0))
return self.mapchain(clones_iter)
def select_h (self, regex, flags = re.IGNORECASE):
# Leo's select_h also stores the match object on each
# position--not done here
pat = re.compile(regex, flags)
return self.filter (lambda x: re.match(pat, x.h))
# Not working yet and I'm not sure why
def select_b (self, regex, flags = re.IGNORECASE):
# Leo's select_b also stores the match object iterator on
# each position--not done here
pat = re.compile(regex, flags)
return self.filter (lambda x: re.match(pat, x.b))
# Looks to be working for at least a few cases
g.es('=======')
g.es('\nChildren, nieces, and nephews')
map (g.es, LeoTreeql(p).self_and_siblings().children())
g.es('\nAncestors of descendants of brothers and sisters')
map (g.es, LeoTreeql(p).self_and_siblings().descendants().ancestors())
g.es('\nChildren of parents (should be the same as self and siblings)')
map (g.es, LeoTreeql(p).parent().children())
g.es('\nChildren of root (i.e. toplevel nodes except the first one)')
map (g.es, LeoTreeql(p).root().following_siblings())
g.es ('\nParents of all the clones of the current position')
map (g.es, LeoTreeql(p).clones().parent())
g.es ('\nCousins of current position and siblings and self')
map (g.es, LeoTreeql(p).parent().self_and_siblings().children())
g.es ('\nCousins of current position and siblings and self with
headline=newHeadline')
map (g.es, LeoTreeql(p).parent().self_and_siblings().children().filter(lambda
x: x.h == 'newHeadline'))
g.es ('\nmultiple levels of empty iterators should be handled fine
(just an empty result):')
map (g.es, LeoTreeql(p).children().children().children())
g.es ('\nAnother parent test')
map (g.es, LeoTreeql(p).self_and_siblings().parent())
g.es ('\nselect_h')
map (g.es, LeoTreeql(p).toplevels().descendants().select_h ('new.*').parent())
g.es ('\nselect_b')
map (g.es, LeoTreeql(p).all_positions().select_b('.*filter.*'))
--
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.