<?xml version="1.0" encoding="utf-8"?>
<!-- Created by Leo: http://leoeditor.com/leo_toc.html -->
<leo_file xmlns:leo="http://leoeditor.com/namespaces/leo-python-editor/1.1" >
<leo_header file_format="2" tnodes="0" max_tnode_index="0" clone_windows="0"/>
<globals body_outline_ratio="0.5" body_secondary_ratio="0.5">
	<global_window_position top="50" left="50" height="500" width="700"/>
	<global_log_window_position top="0" left="0" height="0" width="0"/>
</globals>
<preferences/>
<find_panel_settings/>
<vnodes>
<v t="ekr.20070615131954"><vh>Startup</vh>
<v t="ekr.20150302053516.3"><vh>@settings</vh></v>
<v t="ekr.20070427110751"><vh>@chapters</vh></v>
<v t="ekr.20141116105945.2"><vh>@persistence</vh>
<v t="ekr.20141116105945.3"><vh>@data:@auto create-leobat.bat</vh>
<v t="ekr.20141116105945.4"><vh>@gnxs</vh></v>
</v>
<v t="ekr.20161206070406.1"><vh>@data:@auto-md ../doc/c2py.md</vh>
<v t="ekr.20161206090903.1"><vh>@gnxs</vh></v>
</v>
</v>
</v>
<v t="ekr.20061008055616"><vh>Scripts</vh>
<v t="ekr.20110914030246.2405"><vh>@file gen_blender_docs.py</vh></v>
<v t="ekr.20051110111150" descendentVnodeUnknownAttributes="7d71005806000000302e372e323371017d710258120000007273745f687474705f61747472696275746571035d71042858460000003c6120636c6173733d22746172676574222069643d22687474702d6e6f64652d6d61726b65722d333922206e616d653d22687474702d6e6f64652d6d61726b65722d3339223e710558040000003c2f613e71065d71072858340000003c64697620636c6173733d2273656374696f6e222069643d2272756e6e696e672d6c656f2d696e2d62617463682d6d6f6465223e710858060000003c2f6469763e71095d710a28583f0000003c64697620636c6173733d22646f63756d656e74222069643d22636861707465722d372d736372697074696e672d6c656f2d776974682d707974686f6e223e710b58060000003c2f6469763e710c5d710d2858060000003c626f64793e710e58070000003c2f626f64793e710f5d71102858430000003c68746d6c20786d6c6e733d22687474703a2f2f7777772e77332e6f72672f313939392f7868746d6c2220786d6c3a6c616e673d22656e22206c616e673d22656e223e711158070000003c2f68746d6c3e71124e6565656558070000003c2f6469763e0a7113583e0000003c64697620636c6173733d2273656374696f6e222069643d2266756e6374696f6e732d646566696e65642d696e2d6c656f676c6f62616c732d7079223e0a7114587e0000003c68313e3c6120636c6173733d22746f632d6261636b7265662220687265663d22236964323022206e616d653d2266756e6374696f6e732d646566696e65642d696e2d6c656f676c6f62616c732d7079223e46756e6374696f6e7320646566696e656420696e206c656f476c6f62616c732e70793c2f613e3c2f68313e0a71156573732e"
expanded="ekr.20150416062553.1,maphew.20130612230051.2793,maphew.20130611235500.2658,maphew.20130509185752.1607,"><vh>@file leoScripts.txt</vh></v>
</v>
<v t="ekr.20170303064120.1"><vh>What's new in this file</vh>
<v t="ekr.20170303064128.1"><vh>Leo 5.5</vh>
<v t="ekr.20160923133728.1"><vh>Remove tabs from leo/modes/*.py</vh></v>
<v t="ekr.20161017063308.1"><vh>Find problems in pylint-leo-rc.txt</vh></v>
<v t="ekr.20141105055521.16"><vh>Replace body.x with body.wrapper.x</vh></v>
<v t="ekr.20170120110948.4"><vh>Print Qt color names</vh></v>
<v t="ekr.20170301022829.1"><vh>@ignore buttons new in Leo 5.5</vh>
<v t="ekr.20170301014329.1"><vh>@button cycling syntax coloring</vh></v>
<v t="ekr.20170211083757.1"><vh>@button Demo @key=Ctrl-9</vh>
<v t="ekr.20170211083757.2"><vh>&lt;&lt; imports &gt;&gt;</vh></v>
<v t="ekr.20170211083757.3"><vh>&lt;&lt; class myDemo &gt;&gt;</vh>
<v t="ekr.20170211083757.4"><vh>setup</vh></v>
<v t="ekr.20170211083757.5"><vh>setup_script</vh></v>
<v t="ekr.20170211083757.6"><vh>teardown</vh></v>
<v t="ekr.20170211083757.7"><vh>teardown_script</vh></v>
</v>
<v t="ekr.20170211083757.8"><vh>demo-script</vh>
<v t="ekr.20170211083757.9"><vh>First</vh></v>
<v t="ekr.20170211083757.10"><vh>Full featured outliner</vh></v>
<v t="ekr.20170211083757.11"><vh>Leo's panes</vh></v>
<v t="ekr.20170211083757.12"><vh>Leo creates scripts from outlines</vh></v>
<v t="ekr.20170211083757.13"><vh>Clones and cff</vh></v>
<v t="ekr.20170211083757.14"><vh>Last</vh></v>
</v>
</v>
<v t="ekr.20161006092435.1"><vh>@button import-tab-files</vh>
<v t="ekr.20161006092435.2"><vh>class TabImporter</vh>
<v t="ekr.20161006092435.3"><vh>check</vh></v>
<v t="ekr.20161006092435.4"><vh>dump_stack</vh></v>
<v t="ekr.20161006092435.5"><vh>lws</vh></v>
<v t="ekr.20161006092435.6"><vh>scan</vh></v>
<v t="ekr.20161006092435.7"><vh>scan_helper</vh></v>
<v t="ekr.20161006092435.8"><vh>undent</vh></v>
</v>
</v>
<v t="ekr.20170301023612.1"><vh>@button insert headlines as comments</vh></v>
<v t="ekr.20170212105552.1"><vh>@button IntroSlides @key=Ctrl-9</vh>
<v t="ekr.20170212105552.2"><vh>&lt;&lt; imports &gt;&gt;</vh></v>
<v t="ekr.20170212105552.3"><vh>&lt;&lt; class IntroSlides &gt;&gt;</vh>
<v t="ekr.20170212105552.4"><vh>setup</vh></v>
<v t="ekr.20170212105552.5"><vh>setup_script</vh></v>
<v t="ekr.20170212105552.6"><vh>teardown</vh></v>
<v t="ekr.20170212105552.7"><vh>teardown_script</vh></v>
</v>
<v t="ekr.20170212105552.8"><vh>&lt;&lt; main &gt;&gt;</vh></v>
<v t="ekr.20170212105552.9"><vh>Leo's Main Window</vh></v>
<v t="ekr.20170212105552.10"><vh>intro-slides-script</vh>
<v t="ekr.20170212105552.11"><vh>Slide 1: Leo's main window</vh></v>
</v>
</v>
<v t="ekr.20160923132656.1"><vh>@button introspect</vh></v>
<v t="ekr.20161031130627.1"><vh>@button pep8 @key=Ctrl-5</vh>
<v t="ekr.20161031130627.2"><vh>class Pep8</vh>
<v t="ekr.20161031130627.3"><vh>change_all &amp; helpers</vh>
<v t="ekr.20161031130627.4"><vh>change_body</vh></v>
<v t="ekr.20161031130627.5"><vh>change_headline</vh></v>
</v>
<v t="ekr.20161031130627.6"><vh>get_name</vh></v>
<v t="ekr.20161031130627.7"><vh>run</vh></v>
<v t="ekr.20161031130627.8"><vh>to_pep8</vh></v>
</v>
<v t="ekr.20161031130627.9"><vh>clear</vh></v>
</v>
<v t="ekr.20170225023738.1"><vh>@button test-http</vh></v>
<v t="ekr.20170120110015.1"><vh>@ignore importer scripts</vh>
<v t="ekr.20161120175101.1"><vh>@button make-md-heads</vh>
<v t="ekr.20161120175101.2"><vh>markup</vh></v>
</v>
<v t="ekr.20161123085419.1"><vh>@button make-table</vh></v>
<v t="ekr.20161124034654.1"><vh>@button make-importer</vh>
<v t="ekr.20161124034654.2"><vh>&lt;&lt; define run &amp; helpers &gt;&gt;</vh>
<v t="ekr.20161124034654.3"><vh>copy_tree</vh></v>
<v t="ekr.20161124034654.4"><vh>make_substitutions</vh></v>
<v t="ekr.20161124034654.5"><vh>run</vh></v>
<v t="ekr.20161124034654.6"><vh>substitue</vh></v>
</v>
<v t="ekr.20161124034654.7"><vh>@@file importers/{{name}}.py</vh>
<v t="ekr.20161124034654.8"><vh>class {{cap_name}}_Importer</vh>
<v t="ekr.20161124034654.9"><vh>{{name}}.Overrides</vh>
<v t="ekr.20161124034654.10"><vh>{{name}}.clean_headline</vh></v>
<v t="ekr.20161124034654.11"><vh>{{name}}.clean_nodes</vh></v>
</v>
</v>
<v t="ekr.20161124034654.12"><vh>class class {{cap_name}}_ScanState</vh>
<v t="ekr.20161124034654.13"><vh>{{name}}_state.level</vh></v>
<v t="ekr.20161124034654.14"><vh>{{name}}_state.update</vh></v>
</v>
</v>
</v>
<v t="ekr.20161124133327.1"><vh>@button make-test</vh>
<v t="ekr.20161124133327.2"><vh>&lt;&lt; define preamble &gt;&gt;</vh></v>
</v>
<v t="ekr.20161204063803.1"><vh>@button make-md-toc</vh>
<v t="ekr.20161204063803.2"><vh>run</vh></v>
<v t="ekr.20161204063803.3"><vh>mak_link</vh></v>
<v t="ekr.20161204063803.4"><vh>make_toc</vh></v>
</v>
</v>
</v>
</v>
<v t="ekr.20170804153254.1"><vh>Leo 5.6</vh>
<v t="ekr.20170411105625.1"><vh>Script: get git branch name using pygit2</vh></v>
<v t="ekr.20170804153229.1"><vh>script: find non-tracing g.unitTesting</vh></v>
</v>
<v t="ekr.20180529105231.1"><vh>Leo 5.7.4</vh>
<v t="ekr.20180529105204.1"><vh>script: get-child-headlines</vh></v>
</v>
</v>
</vnodes>
<tnodes>
<t tx="ekr.20061008055616"></t>
<t tx="ekr.20070427110751"></t>
<t tx="ekr.20070615131954"></t>
<t tx="ekr.20141105055521.16">@language python

'''
A script to replace body.x with body.wrapper.x for all x in the WrapperAPI.

It is *not undoable* to save massive amounts of memory.
Please run on an already-saved .leo file, and take all other
reasonable precautions.

If replace is False, it will just report the changes to be made.
'''
import leo.core.leoFrame as leoFrame
replace = False
aList = sorted([z for z in dir(leoFrame.WrapperAPI) if not z.startswith('__')])
nodes = 0
for p in c.all_unique_positions():
    s = p.b
    nodes += 1
    found = False
    for target in aList:
        i = 0
        pattern = 'body.' + target
        while True:
            i = s.find(pattern,i)
            if i == -1:
                break
            if g.match_word(s,i,pattern):
                if not found:
                    print('In node: %s' % p.h)
                    found = True
                i1,i2 = g.getLine(s,i)
                if replace:
                    j = i + len('body.')
                    s = s[:j] + 'wrapper.' + s[j:]
                    print(s[i1:i2+len('wrapper.')].rstrip())
                    i += len('wrapper.') + len(pattern)
                else:
                    print(s[i1:i2].rstrip())
                    i += len(pattern)
            else:
                i += len(pattern)
    if found and replace:
        p.b = s
</t>
<t tx="ekr.20141116105945.2"></t>
<t tx="ekr.20141116105945.3">gnx: maphew.20130809155103.2862
</t>
<t tx="ekr.20141116105945.4"></t>
<t tx="ekr.20150302053516.3"></t>
<t tx="ekr.20160923132656.1">@language python
"""Introspect"""

# By Terry Brown.  Requires Python 2.x.

# https://groups.google.com/forum/#!msg/leo-editor/Qu2HccpC_wc/_ee11jIvAQAJ

import types

sub_mode = 'instance'
# 'instance' or 'class' - controls which, instance or class names,
# are put it a subnode.  'instance class' sub-nodes both.
# '' appends classes after names, not useful.

def classname(thing):
    if hasattr(thing, '__class__'):
        return thing.__class__.__name__
    else:
        return thing.__name__

if not hasattr(c.p.v, '_introspection_target'):
    txt = g.app.gui.runAskOkCancelStringDialog(
        c, "Introspect what", "Introspect what")
    if txt is not None:
        o = eval(txt)
        c.p.v._introspection_target = o
        c.p.h = "%s %s" % (txt, classname(o))

# c.p.deletePositionsInList([i.copy() for i in p.children()])

obj = c.p.v._introspection_target
g.es(classname(obj))

def show_obj(c, obj):

    inames = sorted(dir(obj))
    
    things = {}
    instances = []
    for iname in inames:
        
        if iname.startswith('__'):
            continue
        
        o = getattr(obj, iname)
        cname = classname(o)
        instances.append((iname, o))
        things.setdefault(cname, []).append(instances[-1])

    if 'instance' in sub_mode:
        tnd = c.p.v.insertAsNthChild(0)
        tnd.h = "&lt;by name&gt;"
    else:
        tnd = c.p.v

    instances.sort()
    for iname, o in instances:
        
        if classname(o) == 'position':
            # apparently this collapses the space-time continuum?
            continue
        
        nd = tnd.insertAsLastChild()
        
        if not seen_already(tnd, nd, iname, o):
            nd.h = "%s %s" % (iname, format_type(nd, o))
            nd._introspection_target = o

    if 'class' in sub_mode:
        ttnd = c.p.v.insertAsNthChild(0)
        ttnd.h = "&lt;by class&gt;"
    else:
        ttnd = c.p.v

    for cname in sorted(things):
    
        if len(things[cname]) == 1:
            tnd = ttnd
        else:
            tnd = ttnd.insertAsLastChild()
            tnd.h = "&lt;%s&gt;"%cname
    
        for iname, o in sorted(things[cname]):
            
            if cname == 'position':
                # apparently this collapses the space-time continuum?
                continue
            
            nd = tnd.insertAsLastChild()
            if not seen_already(tnd, nd, iname, o):
                show_child(nd, iname, o)
                nd._introspection_target = o
         
def seen_already(tnd, nd, iname, o):
        
    up = tnd.parents
    while up:
        if (hasattr(up[0], '_introspection_target') and
            up[0]._introspection_target is o):
            break
        up = up[0].parents
    else:
        return False
        
    nd.h = "[%s %s]" % (classname(o), iname)
    pos = c.vnode2position(up[0])
    nd.b = pos.get_UNL(with_file=True, with_proto=True)
    
    return True
            
def show_child(nd, iname, o):
                
    nd._introspection_target = o
    nd.h = "%s %s" % (format_type(nd, o), iname)
    
docable = (
    types.ClassType, types.MethodType, types.UnboundMethodType, 
    types.BuiltinFunctionType, types.BuiltinMethodType,
)
    
def format_type(nd, o):
    
    if isinstance(o, docable):
        if hasattr(o, '__doc__'):
            nd.b = o.__doc__
    
    if isinstance(o, (str, unicode)):
        nd.b = o
        return "%s '%s'" % (classname(o), o[:20])
    elif isinstance(o, bool):
        return "%s %s" % (classname(o), 'T' if o else 'F')
    elif isinstance(o, (int, float)):
        return "%s %s" % (classname(o), o)
    elif isinstance(o, (tuple, list, dict)):
        return "%s %s" % (classname(o), len(o))
    else:
        return classname(o)
    
def show_list(c, list_):
    
    if len(list_) &gt; 100:
        nd = c.p.v.insertAsLastChild()
        nd.h = "&lt;%s of %d items truncated&gt;" % len(list_.__class__.__name__, list_)
        
    if len(list_) == 0:
        nd = c.p.v.insertAsLastChild()
        nd.h = "&lt;%s of 0 items&gt;" % list_.__class__.__name__
        
    for n, i in enumerate(list_[:100]):
        nd = c.p.v.insertAsLastChild()
        show_child(nd, '', i)
        nd.h = "%d: %s" % (n, nd.h)
        nd._introspection_target = i

def show_dict(c, dict_):
    
    if len(dict_) &gt; 100:
        nd = c.p.v.insertAsLastChild()
        nd.h = "&lt;dict of %d items truncated&gt;" % len(dict_)
        
    if len(dict_) == 0:
        nd = c.p.v.insertAsLastChild()
        nd.h = "&lt;dict of 0 items&gt;"
        
    keys = dict_.keys()
    keys.sort()
        
    for k in keys[:100]:
        nd = c.p.v.insertAsLastChild()
        i = dict_[k]
        show_child(nd, '', i)
        nd.h = "%s: %s" % (k, nd.h)
        nd._introspection_target = i

dispatch = {
    list: show_list,
    tuple: show_list,
    dict: show_dict,
}

func = dispatch.get(type(obj), show_obj)

func(c, obj)
   
c.p.expand()
c.redraw()
</t>
<t tx="ekr.20160923133728.1">@language python

import glob
path = g.os_path_join(g.app.loadDir, '..', 'modes', '*.py')
# print(g.os_path_exists(path))
aList = glob.glob(path)
# print('\n'.join(sorted(aList)))
for fn in aList:
    f = open(fn, 'r')
    s1 = f.read()
    f.close()
    s2 = s1.replace('\t', '    ')
    if s1 != s2:
        print('changed: %s' % fn)
        f = open(fn, 'w')
        f.write(s2)
        f.close()
</t>
<t tx="ekr.20161006092435.1">'''Import tab-indented files.'''
g.cls()
if c.isChanged():
    c.save()
separate = True # True: put all lines in separate nodes.
path = r'c:/test/tab_file_test.txt'
if 1:
    # Use the TabImporter class in leoImport.py.
    import leo.core.leoImport as leoImport
    importer = leoImport.TabImporter(c, separate=separate)
    importer.import_files([path])
else:
    # Use a custom class.
    @others
    s = open(path).read()
    last = c.lastTopLevel()
    root = last.insertAfter()
    root.h = path
    TabImporter(c, root=root, separate=separate).scan(s)
    g.es_print('Imported %s' % path)
    c.selectPosition(root)
    root.expand()
    c.redraw()
</t>
<t tx="ekr.20161006092435.2">class TabImporter:
    
    def __init__(self, c, root, separate):
        '''Ctor for the TabImporter class.'''
        self.c = c
        self.stack = []
        self.root = root
        self.separate = separate

    @others
</t>
<t tx="ekr.20161006092435.3">def check(self, lines):
    '''Return False and warn if lines contains mixed leading tabs/blanks.'''
    blanks, tabs = 0, 0
    for s in lines:
        lws = self.lws(s)
        if '\t' in lws: tabs += 1
        if ' ' in lws: blanks += 1
    if tabs and blanks:
        g.es_print('intermixed leading blanks and tabs.')
        return False
    else:
        return True
</t>
<t tx="ekr.20161006092435.4">def dump_stack(self):
    '''Dump the stack, containing (level, p) tuples.'''
    g.trace('==========')
    for i, data in enumerate(self.stack):
        level, p = data
        print('%2s %s %r' % (i, level, p.h))
</t>
<t tx="ekr.20161006092435.5">def lws(self, s):
    '''Return the length of the leading whitespace of s.'''
    for i, ch in enumerate(s):
        if ch not in ' \t':
            return s[:i]
    return s
    
    
</t>
<t tx="ekr.20161006092435.6">def scan(self, s1):
    trace = False and not g.unitTesting
    c, root, separate = self.c, self.root, self.separate
    if not s1.strip() or not root:
        return
    if trace: g.trace('importing to %s' % root.h)
    lines = g.splitLines(s1)
    if self.check(lines):
        self.stack = []
        for s in lines:
            if s.strip() or not separate:
                self.scan_helper(s)
</t>
<t tx="ekr.20161006092435.7">def scan_helper(self, s):
    '''Update the stack as necessary and return (level, parent, stack).'''
    trace = False and not g.unitTesting
    root, separate, stack = self.root, self.separate, self.stack
    if stack:
        level, parent = stack[-1]
    else:
        level, parent = 0, None
    lws = len(self.lws(s))
    if trace:
        g.trace('----- level: %s lws: %s %s' % (level, lws, s.rstrip()))
    h = s.strip()
    if lws == level:
        if separate or not parent:
            # Replace the top of the stack with a new entry.
            if stack:
                stack.pop()
            grand_parent = stack[-1][1] if stack else root
            parent = grand_parent.insertAsLastChild() # lws == level
            parent.h = h
            stack.append((level, parent),)
        elif not parent.h:
            parent.h = h
    elif lws &gt; level:
        # Create a new parent.
        level = lws
        parent = parent.insertAsLastChild()
        parent.h = h
        stack.append((level, parent),)
    else:
        # Find the previous parent.
        if trace: self.dump_stack()
        while stack:
            level2, parent2 = stack.pop()
            if level2 == lws:
                grand_parent = stack[-1][1] if stack else root
                parent = grand_parent.insertAsLastChild() # lws &lt; level
                parent.h = h
                level = lws
                stack.append((level, parent),)
                break
        else:
            level = 0
            parent = root.insertAsLastChild()
            parent.h = h
            stack = [(0, parent),]
    if trace:
        g.trace('DONE: lws: %s level: %s parent: %s' % (lws, level, parent.h))
        self.dump_stack()
    assert parent and parent == stack[-1][1]
        # An important invariant.
    assert level == stack[-1][0], (level, stack[-1][0])
    if not separate:
        parent.b = parent.b + self.undent(level, s)
    return level
</t>
<t tx="ekr.20161006092435.8">def undent(self, level, s):
    '''Unindent all lines of p.b by level.'''
    # g.trace(level, s.rstrip())
    if level &lt;= 0:
        return s
    if s.strip():
        lines = g.splitLines(s)
        ch = lines[0][0]
        assert ch in ' \t', repr(ch)
        # Check that all lines start with the proper lws.
        lws = ch * level
        for s in lines:
            if not s.startswith(lws):
                g.trace('bad indentation: %r' % s)
                return s
        return ''.join([z[len(lws):] for z in lines])
    else:
        return ''
</t>
<t tx="ekr.20161017063308.1">g.cls()
print_all_lines = True
table = [
    r'c:\leo.repo\leo-editor\leo\test\pylint-leo-rc.txt',
    r'c:\leo.repo\leo-editor\leo\test\pylint-leo-rc-ref.txt',
]
for path in table:
    f = open(path)
    s = f.read()
    f.close()
    # print(len(s))
    errors = []
    n = 0
    for i, line in enumerate(g.splitLines(s)):
        try:
            if print_all_lines:
                print('  %3s %4s %s' % (i+1, n, line.rstrip()))
            else:
                g.toUnicode(line)
        except UnicodeEncodeError:
            print('**%3s %4s %s' % (i+1, n, len(line.rstrip())))
            errors.append(i+1)
        n += len(line)
    print('%s error lines: %s' % (g.shortFileName(path), errors))
</t>
<t tx="ekr.20161031130627.1">'''
Undoably converts the word at the cursor to pep8 style throughout a given tree.
Also sets the find text to the new word.
'''
# aTestExample notFoundExample.
import re
# clear()
table = (
    'BLS.new_scan &amp; helpers',
    'BLS.Code generation',
)
@others
Pep8(table, change=True).run()
</t>
<t tx="ekr.20161031130627.2">class Pep8:
    '''
    Convert the word under the cursor to pep8 style in all subtrees in
    table.
    '''
    
    def __init__ (self, table, change=False):
        '''Ctor for Pep8 class.'''
        self.change = change
        self.table = table
        
    @others
</t>
<t tx="ekr.20161031130627.3">def change_all(self, name, new_name, root):
    '''Undoably change name to new_name throughout root's tree.'''
    u = c.undoer
    bunch = u.beforeChangeTree(root)
    found = False
    self.pattern = re.compile(r'\b%s\b' % name)
    for p in root.self_and_subtree():
        found = self.change_headline(name, new_name, p) or found
        found = self.change_body(name, new_name, p) or found
    if found:
        u.afterChangeTree(root, 'pep8', bunch)
    return found
</t>
<t tx="ekr.20161031130627.4">def change_body(self, name, new_name, p):
    indices = []
    for m in self.pattern.finditer(p.b):
        indices.append(str(m.start()))
    if indices:
        n = len(indices)
        g.es_print('%s change%s: %s' % (n, g.plural(n), p.h))
        s = p.b
        for i in reversed(indices):
            i = int(i)
            s = s[:i] + new_name + s[i+len(name):]
        if self.change:
            p.b = s
            p.setDirty()
        else:
            g.es_print(s)
    return bool(indices)
</t>
<t tx="ekr.20161031130627.5">def change_headline(self, name, new_name, p):
    m = self.pattern.search(p.h)
    if m:
        i = m.start()
        s = p.h
        s = s[:i] + new_name + s[i+len(name):]
        if self.change:
            p.h = s
            p.setDirty()
            g.es_print('changed headline', s)
        else:
            g.es_print('headline', s)
    return bool(m)
</t>
<t tx="ekr.20161031130627.6">def get_name(self):
    i, j = c.editCommands.extendToWord(event=None, select=False)
    w = c.frame.body.wrapper
    s = w.getAllText()
    name = s[i:j]
    return name
</t>
<t tx="ekr.20161031130627.7">def run(self):
    # self.clear()
    name = self.get_name()
    new_name = self.to_pep8(name)
    if len(name) &lt; 2:
        g.es_print('name too short:', name)
    elif new_name == name:
        g.es_print('already pep8:', name)
    else:
        g.es_print('%s -&gt; %s' % (name, new_name))
        c.findCommands.ftm.setFindText(new_name)
            # Preload the replacement text.
        found = False
        for target in table:
            root = g.findNodeAnywhere(c, target)
            assert root, target
            found = self.change_all(name, new_name, root) or found
        if found:
            c.redraw()
        else:
            g.es_print('not found:', name)
</t>
<t tx="ekr.20161031130627.8">def to_pep8(self, s):
    
    if len(s) &gt; 1 and s[0].islower() and s.lower() != s:
        result = []
        for ch in s:
            result.append(ch)
            if ch.isupper():
                result.pop()
                result.append('_%s' % (ch.lower()))
        return ''.join(result)
    else:
        return name
</t>
<t tx="ekr.20161031130627.9">def clear():
    g.cls()
    c.k.simulateCommand('clear-log')
</t>
<t tx="ekr.20161120175101.1">'''
Create markdown headers throughout the nearest .md outline.

That is, prepend p.b[0] with markdown section markup, if appriate.
'''
g.cls()
import re
@others

def predicate(p):
    return p.isAnyAtFileNode() and p.h.strip().endswith('.md')

for root in c.all_unique_roots(predicate):
    print(root.h)
    for p in root.self_and_subtree():
        markup(p, root)
c.redraw()

@language python
@tabwidth -4
</t>
<t tx="ekr.20161120175101.2">pattern = re.compile(r'^(#+\s+)(.*)$')

def markup(p, root):
    '''prepend p.b[0] with markdown section markup, if appriate.'''
    root_level = root.level()
    lines = g.splitLines(p.b)
    if len(lines) &lt; 2: return
    line0, line1 = lines[0], lines[1]
    if (
        not p.h.startswith('@md-ignore') and
        not line0.isspace() and # A real first line.
        not line0.startswith('@') and # Not a directive
        line1.isspace() # the next line is blank
    ):
        # Remove existing markup.
        m = pattern.match(line0)
        if m:  line0 = m.group(2) + '\n'
        # Add the correct markup.
        hashes = '#'*(p.level()-root_level+1)
        lines[0] = '%s %s' % (hashes, line0)
    # Ensure a blank line, so as not to interfere with later headers.
    s = ''.join(lines).rstrip()+'\n\n'
    if p.b != s:
        g.es_print('changed: %s' % (p.h))
        p.setDirty()
        c.setChanged(True)
        p.b = s
</t>
<t tx="ekr.20161123085419.1">'''
Create a table of expected headlines in a unit test.

To use this script, select the root of the tree containing the expected
results. After running this, copy the table from the console.
'''
g.cls()
# Proper escapes are tricky.
table = [
    '"%s",' % p.h.replace('\\', '\\\\').replace('"', '\\"')
        for p in c.p.subtree()
]
print("table = (\n    %s\n)" % '\n    '.join(table))
</t>
<t tx="ekr.20161124034654.1">g.cls()
# define constants that describe the new language.
name = 'otl'
    # The name of the file, and the prefix for classes.
language = 'plain'
    # The name of the language, case doesn't matter.
extensions = ['.org',]
    # A list of file extensions supported by this importer.
strict = False
    # True if leading whitespace is particularly significant.
state_ivar = 'self.not_used'
    # 'self.indent' for python, coffeescript.
    # 'self.curlies' for many other languages
    # '(self, curlies, self.parens)' for more complex comparisons
&lt;&lt; define run &amp; helpers &gt;&gt;
run(extensions, language, name, state_ivar)
</t>
<t tx="ekr.20161124034654.10">### Define an override if desired...

if 0: # The base class
    def clean_headline(self, s):
        '''Return a cleaned up headline s.'''
        return s.strip()
        
if 0: # A more complex example, for the C language.
    def clean_headline(self, s):
        '''Return a cleaned up headline s.'''
        import re
        type1 = r'(static|extern)*'
        type2 = r'(void|int|float|double|char)*'
        class_pattern = r'\s*(%s)\s*class\s+(\w+)' % (type1)
        pattern = r'\s*(%s)\s*(%s)\s*(\w+)' % (type1, type2)
        m = re.match(class_pattern, s)
        if m:
            prefix1 = '%s ' % (m.group(1)) if m.group(1) else ''
            return '%sclass %s' % (prefix1, m.group(2))
        m = re.match(pattern, s)
        if m:
            prefix1 = '%s ' % (m.group(1)) if m.group(1) else ''
            prefix2 = '%s ' % (m.group(2)) if m.group(2) else ''
            h = m.group(3) or '&lt;no c function name&gt;'
            return '%s%s%s' % (prefix1, prefix2, h)
        else:
            return s
</t>
<t tx="ekr.20161124034654.11">def clean_nodes(self, parent):
    '''
    Clean all nodes in parent's tree.
    Subclasses override this as desired.
    See perl_i.clean_nodes for an examplle.
    '''
    pass
</t>
<t tx="ekr.20161124034654.12">class {{cap_name}}_ScanState:
    '''A class representing the state of the {{name}} line-oriented scan.'''
    
    def __init__(self, d=None):
        '''{{cap_name}}_ScanState.__init__'''
        if d:
            prev = d.get('prev')
            self.context = prev.context
            ### Adjust these by hand.
            self.curlies = prev.curlies
        else:
            self.context = ''
            ### Adjust these by hand.
            self.curlies = 0

    def __repr__(self):
        '''{{cap_name}}_ScanState.__repr__'''
        ### Adjust these by hand.
        return "{{cap_name}}_ScanState context: %r curlies: %s" % (
            self.context, self.curlies)

    __str__ = __repr__

    @others
</t>
<t tx="ekr.20161124034654.13">def level(self):
    '''{{cap_name}}_ScanState.level.'''
    return {{state_ivar}}

</t>
<t tx="ekr.20161124034654.14">def update(self, data):
    '''
    {{cap_name}}_ScanState.update

    Update the state using the 6-tuple returned by v2_scan_line.
    Return i = data[1]
    '''
    context, i, delta_c, delta_p, delta_s, bs_nl = data
    # All ScanState classes must have a context ivar.
    self.context = context
    self.curlies += delta_c  
    ### Update {{cap_name}}_ScanState ivars
    # self.bs_nl = bs_nl
    # self.parens += delta_p
    # self.squares += delta_s
    return i
</t>
<t tx="ekr.20161124034654.2">@others
</t>
<t tx="ekr.20161124034654.3">def copy_tree(source, root, h):
    '''Copy the source tree to the node after p, with headline h.'''
    p2 = root.insertAfter()
    source.copyTreeFromSelfTo(p2)
    p2.h = h
    return p2
 
</t>
<t tx="ekr.20161124034654.4">def make_substitutions(destination, patterns):
    '''Make all substitutions in the destination tree.'''
    for p in destination.self_and_subtree():
        h = substitute(p.h, patterns)
        if p.h != h:
            # g.trace('CHANGED:', p.h, '==&gt;', h)
            p.h = h
        b = substitute(p.b, patterns)
        if p.b != b:
            # g.trace('CHANGED:', p.b, '==&gt;', b)
            p.b = b
</t>
<t tx="ekr.20161124034654.5">def run(extensions, language, name, state_ivar):
    '''The driver for this script.'''
    patterns = {
        'cap_name': name.capitalize(),
        'extensions': '[%s]' % ', '.join(["'%s'" % (z) for z in extensions]),
        'language': language.lower(),
        'name': name.lower(),
        'strict': 'True' if strict else 'False',
        'state_ivar': state_ivar,
    }
    h = '@button make-importer'
    root = g.findNodeAnywhere(c, h)
    assert root, h
    h = '@@file importers/{{name}}.py'
    source = g.findNodeInTree(c, root, h)
    assert source, h
    destination = copy_tree(source, root, h)
    make_substitutions(destination, patterns)
    c.contractAllHeadlines()
    c.redraw()
</t>
<t tx="ekr.20161124034654.6">def substitute(s, patterns):
    '''Make all substitutions in s.'''
    for pattern in patterns:
        find = '{{%s}}' % pattern
        replace = patterns.get(pattern)
        i = 0
        while i &lt; len(s):
            progress = i
            j = s.find(find, i)
            if j == -1: break
            s = s[:j] + replace + s[j+len(find):]
            i = j+len(replace)
            assert progress &lt; i
    return s
</t>
<t tx="ekr.20161124034654.7">'''The @auto importer for the {{name}} language.'''
import leo.plugins.importers.linescanner as linescanner
Importer = linescanner.Importer
@others
importer_dict = {
    'class': {{cap_name}}_Importer,
    'extensions': {{extensions}},
}
@language python
@tabwidth -4


</t>
<t tx="ekr.20161124034654.8">class {{cap_name}}_Importer(Importer):
    '''The importer for the {{name}} lanuage.'''

    def __init__(self, importCommands, atAuto):
        '''{{cap_name}}_Importer.__init__'''
        # Init the base class.
        Importer.__init__(self,
            importCommands,
            atAuto = atAuto,
            language = '{{language}}',
            state_class = {{cap_name}}_ScanState,
            strict = {{strict}},
        )
        
    @others
</t>
<t tx="ekr.20161124034654.9"># These can be overridden in subclasses.
</t>
<t tx="ekr.20161124133327.1">'''Make an @test node for the importer whose name is given.'''
name = 'javascript'
d = g.app.permanentScriptDict
tag = 'make_test_%s_n' % name
n = d.get(tag, 0) + 1
d [tag] = n
d = {'n': n, 'name': name}
&lt;&lt; define preamble &gt;&gt;
p = c.lastTopLevel().insertAfter()
p.b = preamble
p.h = '@test %(name)s importer-%(n)s' % d
c.redraw()
c.selectPosition(p)
c.bodyWantsFocusNow()
c.frame.body.wrapper.setInsertPoint(len(p.b))
</t>
<t tx="ekr.20161124133327.2">preamble = '''\
if 1:
    # The preamble...
    g.cls()
    if c.isChanged(): c.save()
    import imp
    import leo.plugins.importers.linescanner as linescanner
    import leo.plugins.importers.%(name)s as %(name)s
    imp.reload(linescanner)
    imp.reload(%(name)s)
# insert test for %(name)s here.
''' % d
</t>
<t tx="ekr.20161204063803.1">'''Make a markdown table of contents from an @auto-md node.'''
g.cls()
if c.isChanged(): c.save()

class Controller:
    '''Controller class for @button md-toc.'''
    @others
    
if 0:
    h = '@auto-md importers.md'
    p = g.findTopLevelNode(c, h)
    assert p, h
else:
    p = c.p
Controller().run(p)
@language python
@tabwidth -4
</t>
<t tx="ekr.20161204063803.2">def run(self, p):
    '''The driver for @button md-toc.'''
    if p.h.startswith('@auto-md '): #  or p.h.endswith('.md'):
        last = c.lastTopLevel()
        self.root = last.insertAfter()
        self.root.h = 'Table of contents'
        self.make_toc(p)
    else:
        print('must be an @auto-md node or an x.md node: %s' % p.h)
</t>
<t tx="ekr.20161204063803.3">def make_link(self, s):
    '''Return the markdown link for s.'''
    result = []
    for ch in s.lower():
        if ch in ' -':
            result.append('-')
        elif ch.isalnum():
            result.append(ch)
        else:
            pass
    return ''.join(result)
</t>
<t tx="ekr.20161204063803.4">def make_toc(self, p):
    '''Create the toc in self.root.b.'''
    result, stack = [], []
    prefix = p.h.lstrip('@auto-md').strip()
    for p in p.subtree():
        level = p.level() - self.root.level()
        assert level &gt; 0
        if len(stack) &lt; level:
            stack.append(1)
        else:
            stack = stack[:level]
        n = stack[-1]
        stack[-1] = n+1
        indent = ' '*4*(level-1)
        line = '%s%s. [%s](%s#%s)\n' % (
            indent, n, p.h, prefix, self.make_link(p.h))
        result.append(line)
    if 0:
        g.trace(p.h)
        g.printList(result)
    else:
        self.root.b = ''.join(result)
    c.redraw()
</t>
<t tx="ekr.20161206070406.1">gnx: ekr.20161206070323.1
</t>
<t tx="ekr.20161206090903.1">gnx: ekr.20161206070323.2
unl: &lt;&lt; what c2py does &gt;&gt;
gnx: ekr.20161206070323.3
unl: &lt;&lt; theory of operation &gt;&gt;
gnx: ekr.20161206070323.4
unl: &lt;&lt; specify user types &gt;&gt;
gnx: ekr.20161206070323.5
unl: &lt;&lt; define testData &gt;&gt;
gnx: ekr.20161206070323.6
unl: speedTest
gnx: ekr.20161206070323.7
unl: leo1to2
gnx: ekr.20161206070323.8
unl: leo1to2--&gt;leo1to2
gnx: ekr.20161206070323.9
unl: leo1to2--&gt;convertLeo1to2
gnx: ekr.20161206070323.10
unl: leo1to2--&gt;convertStringLeo1to2
gnx: ekr.20161206070323.11
unl: leo1to2--&gt;convertCodeList1to2
gnx: ekr.20161206070323.12
unl: c2py entry points
gnx: ekr.20161206070323.13
unl: c2py entry points--&gt;convertCurrentTree
gnx: ekr.20161206070323.14
unl: c2py entry points--&gt;convertLeoTree
gnx: ekr.20161206070323.15
unl: c2py entry points--&gt;convertCFileToPython
gnx: ekr.20161206070323.16
unl: convertCStringToPython &amp; helpers (top level)
gnx: ekr.20161206070323.17
unl: convertCStringToPython &amp; helpers (top level)--&gt;convertCodeList (main pattern function)
gnx: ekr.20161206070323.18
unl: convertCStringToPython &amp; helpers (top level)--&gt;convertDocList
gnx: ekr.20161206070323.19
unl: convertCStringToPython &amp; helpers (top level)--&gt;skipDocPart
gnx: ekr.20161206070323.20
unl: convertCStringToPython &amp; helpers (top level)--&gt;skipCodePart
gnx: ekr.20161206070323.21
unl: Scanning &amp; Replacing...
gnx: ekr.20161206070323.22
unl: Scanning &amp; Replacing...--&gt;convertLeadingBlanks
gnx: ekr.20161206070323.23
unl: Scanning &amp; Replacing...--&gt;mungeAllFunctions
gnx: ekr.20161206070323.24
unl: Scanning &amp; Replacing...--&gt;mungeAllFunctions--&gt;handlePossibleFunctionHeader
gnx: ekr.20161206070323.25
unl: Scanning &amp; Replacing...--&gt;mungeAllFunctions--&gt;massageFunctionArgs
gnx: ekr.20161206070323.26
unl: Scanning &amp; Replacing...--&gt;mungeAllFunctions--&gt;massageFunctionHead (sets gClassName)
gnx: ekr.20161206070323.27
unl: Scanning &amp; Replacing...--&gt;mungeAllFunctions--&gt;massageFunctionBody
gnx: ekr.20161206070323.28
unl: Scanning &amp; Replacing...--&gt;mungeAllFunctions--&gt;massageFunctionBody--&gt;massageIvars
gnx: ekr.20161206070323.29
unl: Scanning &amp; Replacing...--&gt;mungeAllFunctions--&gt;massageFunctionBody--&gt;removeCasts
gnx: ekr.20161206070323.30
unl: Scanning &amp; Replacing...--&gt;mungeAllFunctions--&gt;massageFunctionBody--&gt;removeTypeNames
gnx: ekr.20161206070323.31
unl: Scanning &amp; Replacing...--&gt;handleAllKeywords
gnx: ekr.20161206070323.32
unl: Scanning &amp; Replacing...--&gt;handleAllKeywords--&gt;handleKeyword
gnx: ekr.20161206070323.33
unl: Scanning &amp; Replacing...--&gt;isX...
gnx: ekr.20161206070323.34
unl: Scanning &amp; Replacing...--&gt;isX...--&gt;isWs and isWOrNl
gnx: ekr.20161206070323.35
unl: Scanning &amp; Replacing...--&gt;isX...--&gt;isSectionDef
gnx: ekr.20161206070323.36
unl: Scanning &amp; Replacing...--&gt;isX...--&gt;isStringOrComment
gnx: ekr.20161206070323.37
unl: Scanning &amp; Replacing...--&gt;find... &amp; match...
gnx: ekr.20161206070323.38
unl: Scanning &amp; Replacing...--&gt;find... &amp; match...--&gt;findInCode
gnx: ekr.20161206070323.39
unl: Scanning &amp; Replacing...--&gt;find... &amp; match...--&gt;findInList
gnx: ekr.20161206070323.40
unl: Scanning &amp; Replacing...--&gt;find... &amp; match...--&gt;match
gnx: ekr.20161206070323.41
unl: Scanning &amp; Replacing...--&gt;find... &amp; match...--&gt;matchWord
gnx: ekr.20161206070323.42
unl: Scanning &amp; Replacing...--&gt;remove...
gnx: ekr.20161206070323.43
unl: Scanning &amp; Replacing...--&gt;remove...--&gt;removeAllCComments
gnx: ekr.20161206070323.44
unl: Scanning &amp; Replacing...--&gt;remove...--&gt;removeAllCSentinels
gnx: ekr.20161206070323.45
unl: Scanning &amp; Replacing...--&gt;remove...--&gt;removeAllPythonComments
gnx: ekr.20161206070323.46
unl: Scanning &amp; Replacing...--&gt;remove...--&gt;removeAllPythonSentinels
gnx: ekr.20161206070323.47
unl: Scanning &amp; Replacing...--&gt;remove...--&gt;removeAtRoot
gnx: ekr.20161206070323.48
unl: Scanning &amp; Replacing...--&gt;remove...--&gt;removeBlankLines
gnx: ekr.20161206070323.49
unl: Scanning &amp; Replacing...--&gt;remove...--&gt;removeExcessWs
gnx: ekr.20161206070323.50
unl: Scanning &amp; Replacing...--&gt;remove...--&gt;removeExcessWs--&gt;removeExessWsFromLine
gnx: ekr.20161206070323.51
unl: Scanning &amp; Replacing...--&gt;remove...--&gt;removeLeadingAtCode
gnx: ekr.20161206070323.52
unl: Scanning &amp; Replacing...--&gt;remove...--&gt;removeMatchingBrackets
gnx: ekr.20161206070323.53
unl: Scanning &amp; Replacing...--&gt;remove...--&gt;removeSemicolonsAtEndOfLines
gnx: ekr.20161206070323.54
unl: Scanning &amp; Replacing...--&gt;remove...--&gt;removeTrailingWs
gnx: ekr.20161206070323.55
unl: Scanning &amp; Replacing...--&gt;replace... &amp; safeReplace
gnx: ekr.20161206070323.56
unl: Scanning &amp; Replacing...--&gt;replace... &amp; safeReplace--&gt;replace
gnx: ekr.20161206070323.57
unl: Scanning &amp; Replacing...--&gt;replace... &amp; safeReplace--&gt;replaceComments
gnx: ekr.20161206070323.58
unl: Scanning &amp; Replacing...--&gt;replace... &amp; safeReplace--&gt;replaceSectionDefs
gnx: ekr.20161206070323.59
unl: Scanning &amp; Replacing...--&gt;replace... &amp; safeReplace--&gt;safeReplace
gnx: ekr.20161206070323.60
unl: Scanning &amp; Replacing...--&gt;skip... &amp; prev...
gnx: ekr.20161206070323.61
unl: Scanning &amp; Replacing...--&gt;skip... &amp; prev...--&gt;prevNonWsChar and prevNonWsOrNlChar
gnx: ekr.20161206070323.62
unl: Scanning &amp; Replacing...--&gt;skip... &amp; prev...--&gt;skipCBlockComment
gnx: ekr.20161206070323.63
unl: Scanning &amp; Replacing...--&gt;skip... &amp; prev...--&gt;skipPastLine
gnx: ekr.20161206070323.64
unl: Scanning &amp; Replacing...--&gt;skip... &amp; prev...--&gt;skipPastWord
gnx: ekr.20161206070323.65
unl: Scanning &amp; Replacing...--&gt;skip... &amp; prev...--&gt;skipString
gnx: ekr.20161206070323.66
unl: Scanning &amp; Replacing...--&gt;skip... &amp; prev...--&gt;skipStringOrComment
gnx: ekr.20161206070323.67
unl: Scanning &amp; Replacing...--&gt;skip... &amp; prev...--&gt;skipToMatchingBracket
gnx: ekr.20161206070323.68
unl: Scanning &amp; Replacing...--&gt;skip... &amp; prev...--&gt;skipWs and skipWsAndNl
gnx: ekr.20161206070323.69
unl: Scanning &amp; Replacing...--&gt;stringToList &amp; listToString
gnx: ekr.20161206070323.70
unl: Scanning &amp; Replacing...--&gt;stringToList &amp; listToString--&gt;stringToList
gnx: ekr.20161206070323.71
unl: Scanning &amp; Replacing...--&gt;stringToList &amp; listToString--&gt;listToString
</t>
<t tx="ekr.20170120110015.1"></t>
<t tx="ekr.20170120110948.4"># This script prints the list of known Qt names. Qt seems to ignore case.
from leo.core.leoQt import QtGui
aList = sorted([g.u(z) for z in QtGui.QColor().colorNames()])
print('\n'.join(aList))
</t>
<t tx="ekr.20170211083757.1">if c.isChanged(): c.save()
&lt;&lt; imports &gt;&gt;
&lt;&lt; class MyDemo &gt;&gt;
# Don't use @others here.
# The *same* command/key binding calls both demo-start and demo.next.
try:
    if getattr(g.app, 'demo', None):
        g.app.demo.next()
    else:
        g.cls()
        c.frame.log.clearTab('Log')
        g.es_print('Starting MyDemo')
        c.k.demoNextKey = c.k.strokeFromSetting('Ctrl-9')
            # Tell k.masterKeyHandler to process Ctrl-9 immediately.
            # Binding demo-next in a setting does *not* work.
        demo = MyDemo(c)
        p = g.findNodeAnywhere(c, '@button Demo @key=Ctrl-9')
        script_tree = g.findNodeInTree(c, p, 'demo-script')
        demo.start(script_tree, auto_run=True)
except Exception:
    g.app.demo = None
    raise
</t>
<t tx="ekr.20170211083757.10"># Create, move, promote, demote, hoist.
demo.retain(Title('Leo is a full featured outliner.'))
demo.wait(1.0)
###
demo.insert_node('a new node', keys=True, speed=10.0)
###
c.moveOutlineRight()
###
# demo.end() # Test of early exit.
###
demo.insert_node('another headline')
###
demo.insert_node('yet another node')
###
p = g.findNodeInTree(c, demo.root, 'a new node')
assert p, 'a new node'
c.selectPosition(p)
demo.wait(0.25)
###
c.demote()
demo.wait(1.0)
###
demo.delete_retained_widgets()
</t>
<t tx="ekr.20170211083757.11"># The body pane shows the text of the selected outline node.
</t>
<t tx="ekr.20170211083757.12"># Section refs, @others, @file
</t>
<t tx="ekr.20170211083757.13"></t>
<t tx="ekr.20170211083757.14"># Callout('Thanks for watching')
###
# demo.next()
</t>
<t tx="ekr.20170211083757.2">from leo.core.leoQt import QtGui
import leo.plugins.demo as demo_module
import imp
imp.reload(demo_module)
</t>
<t tx="ekr.20170211083757.3">class MyDemo (demo_module.Demo):
    
    @others
</t>
<t tx="ekr.20170211083757.4">def setup(self, p=None):
    c = self.c
    self.end_on_exception = True # Good for debugging.
    self.delta = 10
    demo.set_text_delta(10)
    self.geometry1 = self.get_top_geometry()
    p = g.findNodeAnywhere(c, 'Demo Area')
    self.root = p.copy() if p else None
    if p:
        p.expand()
        c.selectPosition(p)
    # c.frame.equalSizedPanes()
    c.redraw()
    self.set_youtube_position()
</t>
<t tx="ekr.20170211083757.5">def setup_script(self):
    self.delete_widgets()
</t>
<t tx="ekr.20170211083757.6">def teardown(self):
    c = self.c
    self.delete_all_widgets()
    # self.set_top_geometry(self.geometry1)
    if hasattr(self, 'delta') and self.delta &gt; 0:
        self.set_text_delta(-self.delta)
    if self.root and c.positionExists(self.root, trace=False):
        self.root.deleteAllChildren()
    p = c.lastTopLevel()
    p.expand()
    c.selectPosition(p)
    c.redraw()
</t>
<t tx="ekr.20170211083757.7">def teardown_script(self):
    if self.auto_run:
        # Default wait.
        self.wait(0.5)
</t>
<t tx="ekr.20170211083757.8">@language python
</t>
<t tx="ekr.20170211083757.9">Callout('Hello. This tutorial introduces Leo')
# Callout("First, I'll increase the text size for easier viewing")
# demo.next(wait=1.0)
</t>
<t tx="ekr.20170212105552.1">@language python
'''Create intro slides for screen shots.'''
# The *same* command/key binding calls both demo-start and demo.next.
if c.isChanged():
    c.save()
&lt;&lt; imports &gt;&gt;
#
# Do NOT use @others here.
#
&lt;&lt; class IntroSlides &gt;&gt;
&lt;&lt; main &gt;&gt;
if getattr(g.app, 'demo', None):
    g.app.demo.next()
else:
    demo = IntroSlides(c)
    main(c, demo,
        auto_run=False,
        hoist_node = "Leo's Main Window",
        script_name='intro-slides-script')
</t>
<t tx="ekr.20170212105552.10">@language python
</t>
<t tx="ekr.20170212105552.11">Callout("This is Leo's main window")

###
demo.next()
</t>
<t tx="ekr.20170212105552.2">from leo.core.leoQt import QtGui
import leo.plugins.demo as demo_module
# import imp
# imp.reload(demo_module)
</t>
<t tx="ekr.20170212105552.3">class IntroSlides (demo_module.Demo):
    
    @others
</t>
<t tx="ekr.20170212105552.4">def setup(self, p=None):
    c = self.c
    self.end_on_exception = True # Good for debugging.
    self.delta = 0
    demo.set_text_delta(self.delta)
    # self.set_youtube_position()
    if hasattr(self, 'hoist_node'):
        c.selectPosition(self.hoist_node)
        c.hoist()
    c.redraw()
</t>
<t tx="ekr.20170212105552.5">def setup_script(self):
    self.delete_widgets()
</t>
<t tx="ekr.20170212105552.6">def teardown(self):
    c = self.c
    self.delete_all_widgets()
    if self.delta &gt; 0:
        self.set_text_delta(-self.delta)
    if self.hoist_node:
        c.selectPosition(self.hoist_node)
        c.dehoist()
    c.redraw()
</t>
<t tx="ekr.20170212105552.7">def teardown_script(self):
    if self.auto_run:
        # Default wait.
        self.wait(0.5)
</t>
<t tx="ekr.20170212105552.8">def main(c, demo, script_name, auto_run=False, hoist_node=None):
    g.cls()
    k = c.k
    class_name = demo.__class__.__name__
    c.frame.log.clearTab('Log')
    g.es_print('Starting', class_name)
    k.demoNextKey = k.strokeFromSetting('Ctrl-9')
        # Tell k.masterKeyHandler to process Ctrl-9 immediately.
        # Binding demo-next in a setting does *not* work.
    h = '@button %s @key=Ctrl-9' % class_name
    p = g.findNodeAnywhere(c, h)
    assert p, h
    script_tree = g.findNodeInTree(c, p, script_name)
    assert script_tree, repr(script_name)
    demo.hoist_node = hoist_node and g.findNodeInTree(c, p, hoist_node)
    demo.start(script_tree, auto_run=auto_run)
</t>
<t tx="ekr.20170212105552.9"></t>
<t tx="ekr.20170225023738.1">'''
Web development involves endless reloading of pages.  It gets old really fast.

This @button allows me to fiddle with the .css and javascript for mod_http
itself without having to reload Leo. Oh so useful. I can just change the
settings in myLeoSettings and hit Ctrl-p to re-execute the button. 

This trick doesn't work when changing mod_http.py itself, but most of
the work involved the css and javascript.

This pattern could be useful to other web developers.
'''

# g.cls()
if c.isChanged():
    c.save()
# *Always* use the most current settings.
g.app.pluginsController.loadOnePlugin(
    'leo.plugins.mod_http',
    tag='open0',
    verbose=False)
g.app.loadManager.readGlobalSettingsFiles()
g.handleUrl('http://127.0.0.1:8130/leoPlugins.leo')
</t>
<t tx="ekr.20170301014329.1">'''Cycle syntax coloring when there are multiple @langauge directives in a node.'''
# Original by Terry Brown, Revised by EKR.
while not p.isRoot():
    if p.b.strip().startswith("@language "):
        lines = g.splitLines(p.b)
        words = lines[0].split()
        # Careful: don't treat comments as languages.
        if len(words) &gt; 2 and words[2][0].isalpha():
            # Cycle the languages on line 1.
            line0 = '%s %s %s\n' % (words[0], ' '.join(words[2:]), words[1])
            p.b = line0 + ''.join(lines[1:])
            c.selectVisBack()
            c.selectVisNext()
            break
    p.moveToParent()
else:
    g.es("No ambiguous @language directive found")
</t>
<t tx="ekr.20170301022829.1"># Please don't ignore these :-)
</t>
<t tx="ekr.20170301023612.1">'''
    insert / update headlines as comments in @nosent R code
    https://gist.github.com/tbnorth/eb913fcab82f6a4b37734b5156543308
'''
# By Terry Brown
headlines = []
for nd in p.self_and_subtree():
    if nd.h and nd.h[0] == '@' or nd.b and nd.b[0] == '@':
        continue
    headlines.append(nd.h)
    lines = nd.b.split('\n')
    if lines and lines[0].startswith('### '):
        del lines[0]
    if lines and lines[0].strip():
        lines[0: 0] = [""]
    lines[0: 0] = [
        "### %s %s" % (nd.h, "#" * (80 - len(nd.h) - 5)),
    ]
    if '.coffee' in p.h:
        lines[0: 0] = [""]
    if lines[-1].strip():
        lines.append("")
    if lines[-2].strip():
        lines.append("")
    b = '\n'.join(lines)
    if nd.b != b:
        nd.b = b
g.es('\n'.join(headlines))
c.redraw()
</t>
<t tx="ekr.20170303064120.1"></t>
<t tx="ekr.20170303064128.1"></t>
<t tx="ekr.20170411105625.1"># http://stackoverflow.com/questions/26134026/
# how-to-get-the-current-checked-out-git-branch-name-through-pygit2

import pygit2
path = g.os_path_finalize_join(g.app.loadDir, '..', '..')
repo = pygit2.Repository(path)
head = repo.head
# print(head)
print(head.name)
print(head.shorthand)
</t>
<t tx="ekr.20170804153229.1">def predicate(p):
    return any([
        s.find('g.unitTesting') &gt; -1 and s.find('trace') == -1
            for s in g.splitLines(p.b)
        ])
        
p = c.cloneFindByPredicate(
    generator = c.all_unique_positions,
    predicate = predicate,
    flatten = True,
)
p.h = 'clone-find-predicate: real use of g.unitTesting'
p.b = '%s nodes' % p.numberOfChildren()
</t>
<t tx="ekr.20170804153254.1"></t>
<t tx="ekr.20180529105204.1">s = p.b
for child in p.children():
    s = s + '\n- ' + child.h
p.b = s</t>
<t tx="ekr.20180529105231.1"></t>
</tnodes>
</leo_file>
