The following script ensures that every non-empty body text ends with exactly one newline. There are severl subtlties in the script:
- pass1: We must be careful to draw the outline only once. In particular, we must not call p.setDirty, but must instead call p.v.t.setDirty.
- pass2: We must compute the dirty @file/@thin nodes quickly, and we must examine the entire tree for dirty @file/@thin nodes.
This script may possibly form the basis for automatic regularization of whitespace. However, it remains to be seen whether this is really needed to keep cvs happy:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet ekr_stylesheet?>
<leo_file>
<leo_header file_format="1" tnodes="3" max_tnode_index="3"/>
<vnodes>
<v t="ekr.20060808103945" a="V"><vh>Set trailing ws script</vh>
<v t="ekr.20060808103945.1"><vh>pass1</vh></v>
<v t="ekr.20060808103945.2"><vh>pass2</vh></v>
</v>
</vnodes>
<tnodes>
<t tx="ekr.20060808103945">'''This script quickly ends all nodes in the selected tree with exactly one
newline and marks all @thin/@file nodes dirty if any of their descendents have
been changed.'''
@others
c.beginUpdate()
try:
p = c.currentPosition()
pass1(p) # Make the changes and do p.v.t.setDirty for all changed nodes p.
pass2() # Quickly set all @thin/@file nodes dirty if any of their descendents are dirty.
g.es_print('done')
finally:
c.endUpdate()</t>
<t tx="ekr.20060808103945.1">def pass1(root):
'''Remove trailing newlines from all nodes.'''
count = 0 ; seen = {}
for p in root.self_and_subtree_iter():
if seen.get(p.v.t): continue
s = p.bodyString()
if s:
s2 = s.rstrip() + '\n'
if s2 != s:
s2 = g.toUnicode(s2,g.app.tkEncoding,reportErrors=True)
p.v.t.bodyString = s2
seen [p.v.t] = True
p.v.t.setDirty() # Just set the bit: do **not** redraw!
count += 1
g.es_print("pass 1: %d nodes converted" % count)
</t>
<t tx="ekr.20060808103945.2">def pass2():
'''Quickly mark all changed @file nodes dirty.'''
count = 0
# Important: we must look at **all** nodes because of clones.
for p in c.allNodes_iter():
if p.isAnyAtFileNode():
root = p.copy()
for p2 in root.self_and_subtree_iter():
if p2.v.t.isDirty():
root.setDirty()
count += 1
break
g.es_print("pass 2: %d @file/@thin nodes set dirty" % count)
</t>
</tnodes>
</leo_file>