from leo.core.leoNodes import Position
# or if inside Leo script and you have p instance
# Position = type(p)
def iter_all_positions(v, stack=None):
"""Generates all positions p in this outline where p.v is v""" if stack is None:stack = []
def allinds(par, ch): for i, x in enumerate(par.children): if x is ch: yield i
def stack2pos(stack): v, i = stack[-1] return Position(v, i, stack[:-1])
for par in set(v.parents): for i in allinds(par, v): stack.insert(0, (v, i)) if par is c.hiddenRootNode: yield stack2pos(stack) else: yield from iter_all_positions(par, stack) stack.pop(0)The positions generated are not necessarily in the outline order.
HTH Vitalije
Here is a very fast way to iterate all positions for a given vnode:
What say you, Vitalije?
What say you, Vitalije?I am glad you liked it. Please add it to wherever you think is best.
Here is a very fast way to iterate all positions for a given vnode:
def setAllAncestorAtFileNodesDirty(self, setDescendentsDirty=False):
"""Rewritten in Leo 6.1"""
p = self
c = p.v.context
dirtyVnodeList = []
for p2 in c.all_positions_for_v(p.v):
for parent in p2.self_and_parents():
if parent.isAnyAtFileNode() and not parent.v.isDirty():
dirtyVnodeList.append(parent.v)
for v in dirtyVnodeList:
v.setDirty()
return dirtyVnodeListdef collect_dirty_parents(v):
def it(ch):
yield ch
for par in ch.parents:
yield from it(par)
dirty_nodes = [x for x in it(v) if x.isAnyAtFileNode() and not x.isDirty()]
for x in dirty_nodes:
x.setDirty()
return dirty_nodesWithout any measurement I think that this can be further simplified and speed up. The all_positions_for_v builds and yields positions, which means it builds entire stacks of (v, index) pairs for each visited v node. And for marking dirty parents it doesn't need to build positions at all. The following is not tested but I believe it should work.
Without any measurement I think that this can be further simplified and speed up.