<?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.20111017085134.16069"><vh>Disabled buttons</vh>
<v t="ekr.20111017085134.16072"><vh>@@button check-dirty</vh></v>
<v t="ekr.20150508132450.1"><vh>@@button create decorators</vh>
<v t="ekr.20150508132450.2"><vh>create_d</vh></v>
<v t="ekr.20150508132450.3"><vh>create_decorator</vh></v>
<v t="ekr.20150508132450.4"><vh>create_decorators</vh></v>
<v t="ekr.20150508132450.5"><vh>create_fixups</vh></v>
<v t="ekr.20150508132450.6"><vh>find_class</vh></v>
<v t="ekr.20150508132450.7"><vh>find_next_clone</vh></v>
<v t="ekr.20150508132450.8"><vh>munge_lines</vh></v>
<v t="ekr.20150508132450.9"><vh>run</vh></v>
</v>
<v t="ekr.20111017085134.16070"><vh>@@button jython</vh></v>
<v t="ekr.20111017085134.16074"><vh>@@button Lines Down</vh>
<v t="ekr.20111017085134.16075"><vh>moveLinesDown</vh></v>
</v>
<v t="ekr.20111017085134.16076"><vh>@@button Lines Up</vh>
<v t="ekr.20111017085134.16077"><vh>moveLinesUp</vh></v>
</v>
<v t="ekr.20111017085134.16078"><vh>@@button lispCall @key=alt+6</vh>
<v t="ekr.20111017085134.16079"><vh>ctor</vh></v>
<v t="ekr.20111017085134.16080"><vh>run &amp; helpers</vh>
<v t="ekr.20111017085134.16081"><vh>findCalls</vh></v>
<v t="ekr.20111017085134.16082"><vh>findDefs</vh></v>
<v t="ekr.20111017085134.16083"><vh>stripComments</vh></v>
<v t="ekr.20111017085134.16084"><vh>stripLispIds</vh></v>
<v t="ekr.20111017085134.16085"><vh>stripStrings</vh></v>
</v>
<v t="ekr.20111017085134.16086"><vh>class token</vh></v>
<v t="ekr.20111017085134.16087"><vh>choose</vh></v>
<v t="ekr.20111017085134.16088"><vh>dumpList</vh></v>
<v t="ekr.20111017085134.16089"><vh>Parsing...</vh>
<v t="ekr.20111017085134.16090"><vh>parse</vh></v>
<v t="ekr.20111017085134.16091"><vh>scan &amp; helpers</vh>
<v t="ekr.20111017085134.16092"><vh>skipComment</vh></v>
<v t="ekr.20111017085134.16093"><vh>skipId</vh></v>
<v t="ekr.20111017085134.16094"><vh>skipString</vh></v>
</v>
<v t="ekr.20111017085134.16095"><vh>scanForest</vh></v>
</v>
<v t="ekr.20111017085134.16096"><vh>Code generators...</vh>
<v t="ekr.20111017085134.16097"><vh>gen</vh></v>
<v t="ekr.20111017085134.16098"><vh>gen_token</vh></v>
<v t="ekr.20111017085134.16099"><vh>gen_block &amp; helper</vh>
<v t="ekr.20111017085134.16100"><vh>gen_block_id</vh></v>
</v>
<v t="ekr.20111017085134.16101"><vh>gen_call &amp; helper</vh>
<v t="ekr.20111017085134.16102"><vh>gen_arg</vh></v>
</v>
<v t="ekr.20111017085134.16103"><vh>gen_def</vh></v>
<v t="ekr.20111017085134.16104"><vh>gen_if &amp; helpers</vh>
<v t="ekr.20111017085134.16105"><vh>gen_then</vh></v>
</v>
<v t="ekr.20111017085134.16106"><vh>gen_expr</vh></v>
<v t="ekr.20111017085134.16107"><vh>gen_let &amp; helper</vh>
<v t="ekr.20111017085134.16108"><vh>gen_let_bindings</vh></v>
</v>
<v t="ekr.20111017085134.16109"><vh>put...</vh>
<v t="ekr.20111017085134.16110"><vh>put </vh></v>
<v t="ekr.20111017085134.16111"><vh>put_token</vh></v>
<v t="ekr.20111017085134.16112"><vh>put_code &amp; put_code_line</vh></v>
<v t="ekr.20111017085134.16113"><vh>put_code_token</vh></v>
</v>
</v>
</v>
<v t="ekr.20160123185308.1"><vh>@@button make_stub_files script</vh>
<v t="ekr.20160123185308.2"><vh>class MakeStubFile</vh>
<v t="ekr.20160123185308.3"><vh>msf.ctors &amp; helpers</vh>
<v t="ekr.20160123185308.4"><vh>msf.make_types_dict</vh></v>
<v t="ekr.20160123185308.5"><vh>msf.scan_types_data</vh></v>
</v>
<v t="ekr.20160123185308.6"><vh>msf.make_stub_file</vh></v>
<v t="ekr.20160123185308.7"><vh>msf.run</vh></v>
</v>
<v t="ekr.20160123185308.8"><vh>class AstFormatter</vh>
<v t="ekr.20160123185308.9"><vh> f.Entries</vh>
<v t="ekr.20160123185308.10"><vh>f.format</vh></v>
<v t="ekr.20160123185308.11"><vh>f.visit</vh></v>
</v>
<v t="ekr.20160123185308.12"><vh>f.Contexts</vh>
<v t="ekr.20160123185308.13"><vh>f.ClassDef</vh></v>
<v t="ekr.20160123185308.14"><vh>f.FunctionDef</vh></v>
<v t="ekr.20160123185308.15"><vh>f.Interactive</vh></v>
<v t="ekr.20160123185308.16"><vh>f.Module</vh></v>
<v t="ekr.20160123185308.17"><vh>f.Lambda</vh></v>
</v>
<v t="ekr.20160123185308.18"><vh>f.Expressions</vh>
<v t="ekr.20160123185308.19"><vh>f.Expr</vh></v>
<v t="ekr.20160123185308.20"><vh>f.Expression</vh></v>
<v t="ekr.20160123185308.21"><vh>f.GeneratorExp</vh></v>
<v t="ekr.20160123185308.22"><vh>f.ctx nodes</vh></v>
</v>
<v t="ekr.20160123185308.23"><vh>f.Operands</vh>
<v t="ekr.20160123185308.24"><vh>f.arguments</vh></v>
<v t="ekr.20160123185308.25"><vh>f.arg (Python3 only)</vh></v>
<v t="ekr.20160123185308.26"><vh>f.Attribute</vh></v>
<v t="ekr.20160123185308.27"><vh>f.Bytes</vh></v>
<v t="ekr.20160123185308.28"><vh>f.Call &amp; f.keyword</vh>
<v t="ekr.20160123185308.29"><vh>f.keyword</vh></v>
</v>
<v t="ekr.20160123185308.30"><vh>f.comprehension</vh></v>
<v t="ekr.20160123185308.31"><vh>f.Dict</vh></v>
<v t="ekr.20160123185308.32"><vh>f.Ellipsis</vh></v>
<v t="ekr.20160123185308.33"><vh>f.ExtSlice</vh></v>
<v t="ekr.20160123185308.34"><vh>f.Index</vh></v>
<v t="ekr.20160123185308.35"><vh>f.List</vh></v>
<v t="ekr.20160123185308.36"><vh>f.ListComp</vh></v>
<v t="ekr.20160123185308.37"><vh>f.Name</vh></v>
<v t="ekr.20160123185308.38"><vh>f.Num</vh></v>
<v t="ekr.20160123185308.39"><vh>f.Repr</vh></v>
<v t="ekr.20160123185308.40"><vh>f.Slice</vh></v>
<v t="ekr.20160123185308.41"><vh>f.Str</vh></v>
<v t="ekr.20160123185308.42"><vh>f.Subscript</vh></v>
<v t="ekr.20160123185308.43"><vh>f.Tuple</vh></v>
</v>
<v t="ekr.20160123185308.44"><vh>f.Operators</vh>
<v t="ekr.20160123185308.45"><vh>f.BinOp</vh></v>
<v t="ekr.20160123185308.46"><vh>f.BoolOp</vh></v>
<v t="ekr.20160123185308.47"><vh>f.Compare</vh></v>
<v t="ekr.20160123185308.48"><vh>f.UnaryOp</vh></v>
<v t="ekr.20160123185308.49"><vh>f.ifExp (ternary operator)</vh></v>
</v>
<v t="ekr.20160123185308.50"><vh>f.Statements</vh>
<v t="ekr.20160123185308.51"><vh>f.Assert</vh></v>
<v t="ekr.20160123185308.52"><vh>f.Assign</vh></v>
<v t="ekr.20160123185308.53"><vh>f.AugAssign</vh></v>
<v t="ekr.20160123185308.54"><vh>f.Break</vh></v>
<v t="ekr.20160123185308.55"><vh>f.Continue</vh></v>
<v t="ekr.20160123185308.56"><vh>f.Delete</vh></v>
<v t="ekr.20160123185308.57"><vh>f.ExceptHandler</vh></v>
<v t="ekr.20160123185308.58"><vh>f.Exec</vh></v>
<v t="ekr.20160123185308.59"><vh>f.For</vh></v>
<v t="ekr.20160123185308.60"><vh>f.Global</vh></v>
<v t="ekr.20160123185308.61"><vh>f.If</vh></v>
<v t="ekr.20160123185308.62"><vh>f.Import &amp; helper</vh>
<v t="ekr.20160123185308.63"><vh>f.get_import_names</vh></v>
</v>
<v t="ekr.20160123185308.64"><vh>f.ImportFrom</vh></v>
<v t="ekr.20160123185308.65"><vh>f.Pass</vh></v>
<v t="ekr.20160123185308.66"><vh>f.Print</vh></v>
<v t="ekr.20160123185308.67"><vh>f.Raise</vh></v>
<v t="ekr.20160123185308.68"><vh>f.Return</vh></v>
<v t="ekr.20160123185308.69"><vh>f.Suite</vh></v>
<v t="ekr.20160123185308.70"><vh>f.TryExcept</vh></v>
<v t="ekr.20160123185308.71"><vh>f.TryFinally</vh></v>
<v t="ekr.20160123185308.72"><vh>f.While</vh></v>
<v t="ekr.20160123185308.73"><vh>f.With</vh></v>
<v t="ekr.20160123185308.74"><vh>f.Yield</vh></v>
</v>
<v t="ekr.20160123185308.75"><vh>f.Utils</vh>
<v t="ekr.20160123185308.76"><vh>f.kind</vh></v>
<v t="ekr.20160123185308.77"><vh>f.indent</vh></v>
<v t="ekr.20160123185308.78"><vh>f.op_name</vh></v>
</v>
</v>
<v t="ekr.20160123185308.79"><vh>class StubFormatter (AstFormatter)</vh>
<v t="ekr.20160123185308.80"><vh>sf.Constants &amp; Name</vh></v>
</v>
<v t="ekr.20160123185308.81"><vh>class StubTraverser (ast.NodeVisitor)</vh>
<v t="ekr.20160123185308.82"><vh>st.indent &amp; out</vh></v>
<v t="ekr.20160123185308.83"><vh>st.run</vh></v>
<v t="ekr.20160123185308.84"><vh>st.visit (not used)</vh></v>
<v t="ekr.20160123185308.85"><vh>st.Visitors</vh>
<v t="ekr.20160123185308.86"><vh>st.ClassDef</vh></v>
<v t="ekr.20160123185308.87"><vh>st.FunctionDef &amp; helpers</vh>
<v t="ekr.20160123185308.88"><vh>format_arguments &amp; helper</vh>
<v t="ekr.20160123185308.89"><vh>munge_arg</vh></v>
</v>
<v t="ekr.20160123185308.90"><vh>format_returns</vh></v>
</v>
<v t="ekr.20160123185308.91"><vh>st.Return</vh></v>
</v>
</v>
</v>
<v t="ekr.20111017085134.16114"><vh>@@button outlineToClipboard</vh></v>
<v t="ekr.20111017085134.16071"><vh>@@button pydoc</vh></v>
<v t="ekr.20150525161132.1"><vh>@@button tokens2tree</vh>
<v t="ekr.20150525161132.2"><vh>&lt;&lt; imports &gt;&gt;</vh></v>
</v>
</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>
</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="7d71005806000000302e362e323271017d710258120000007273745f687474705f61747472696275746571035d71042858460000003c6120636c6173733d22746172676574222069643d22687474702d6e6f64652d6d61726b65722d333922206e616d653d22687474702d6e6f64652d6d61726b65722d3339223e710558040000003c2f613e71065d71072858340000003c64697620636c6173733d2273656374696f6e222069643d2272756e6e696e672d6c656f2d696e2d62617463682d6d6f6465223e710858060000003c2f6469763e71095d710a28583f0000003c64697620636c6173733d22646f63756d656e74222069643d22636861707465722d372d736372697074696e672d6c656f2d776974682d707974686f6e223e710b58060000003c2f6469763e710c5d710d2858060000003c626f64793e710e58070000003c2f626f64793e710f5d71102858430000003c68746d6c20786d6c6e733d22687474703a2f2f7777772e77332e6f72672f313939392f7868746d6c2220786d6c3a6c616e673d22656e22206c616e673d22656e223e711158070000003c2f68746d6c3e71124e6565656558070000003c2f6469763e0a7113583e0000003c64697620636c6173733d2273656374696f6e222069643d2266756e6374696f6e732d646566696e65642d696e2d6c656f676c6f62616c732d7079223e0a7114587e0000003c68313e3c6120636c6173733d22746f632d6261636b7265662220687265663d22236964323022206e616d653d2266756e6374696f6e732d646566696e65642d696e2d6c656f676c6f62616c732d7079223e46756e6374696f6e7320646566696e656420696e206c656f476c6f62616c732e70793c2f613e3c2f68313e0a71156573732e"
expanded="ekr.20060824111500.113,"><vh>@file leoScripts.txt</vh></v>
</v>
</vnodes>
<tnodes>
<t tx="ekr.20061008055616"></t>
<t tx="ekr.20070427110751"></t>
<t tx="ekr.20070615131954"></t>
<t tx="ekr.20111017085134.16069"></t>
<t tx="ekr.20111017085134.16070"># **** Change these as needed ***
import os, sys

tempFileName = g.os_path_abspath(
    g.os_path_join(g.app.testDir,'jythonScript.py'))

if sys.platform == 'win32':
    jython = r'C:\Jython-21\jython.bat'
    command = '%s "%s"' % (jython,tempFileName) 
else:
    jython = r'cd ~/jython-2.1 ; ./jython'
    command = '%s "%s" &amp;' % (jython,tempFileName)

script = g.getScript(c,p).strip()
if not script:
    s = "no script in %s" % p.h
    g.es(s) ; print s
else:
    f = file(tempFileName,'w')
    f.write(script + '\n')
    f.close()
    print command
    os.system(command)
</t>
<t tx="ekr.20111017085134.16071">import os, sys, threading

python = sys.executable
pythonDir,junk = g.os_path_split(python)
pydoc = g.os_path_join(pythonDir,'Lib','pydoc.py')
command = '%s %s -g' % (python,pydoc)

# Execute the command in a separate thread.
def go():
    os.system(command)
    
threading.Thread(target=go).start()</t>
<t tx="ekr.20111017085134.16072"># This works, but is too slow to be really useful.

count = 0
for p in c.all_unique_positions():
    if p.isDirty():
        c.checkPythonNode (p,suppressErrors=False)
        count += 1
        
g.es('%s nodes checked' % count)</t>
<t tx="ekr.20111017085134.16074"># Move selected text of the body down one line.

@others

moveLinesDown(c,p)</t>
<t tx="ekr.20111017085134.16075">def moveLinesDown(c,p):
    
    undoType = 'Move Lines Down'
    head,lines,tail,oldSel,oldYview = c.getBodyLines()
    if not tail or not lines: return
    tail = g.splitLines(tail)[1:]
    lines = '\n'.join(lines) + '\n'
    lines = g.splitLines(lines)
    # Move the lines down.
    lines.insert(0,tail[0])
    tail = tail[1:]
    if not tail: lines.insert(1,'\n')
    # Convert back to strings.
    tail = ''.join(tail)
    lines = ''.join(lines)
    # Adjust selection.
    sel1,sel2 = oldSel
    row,col = sel1.split('.') ; sel1 = '%d.%s' % (int(row)+1,col)
    row,col = sel2.split('.') ; sel2 = '%d.%s' % (int(row)+1,col)
    newSel = sel1,sel2
    c.updateBodyPane(head,lines,tail,undoType,newSel,oldYview)</t>
<t tx="ekr.20111017085134.16076"># Move selected text of the body up one line.

@others

moveLinesUp(c,p)</t>
<t tx="ekr.20111017085134.16077">def moveLinesUp(c,p):
    
    undoType = 'Move Lines Up'
    head,lines,tail,oldSel,oldYview = c.getBodyLines()
    if not head or not lines: return
    # A slight adjustment: lines doesn't end in '\n'.
    head = g.splitLines(head)
    lines = '\n'.join(lines) + '\n'
    lines = g.splitLines(lines)
    # Move the lines up.
    lines.append(head[-1])
    head = head[:-1]
    # Convert back to strings.
    head = ''.join(head)
    lines = ''.join(lines)[:-1] # Undo the adjustment above.
    # Adjust selection.
    sel1,sel2 = oldSel
    row,col = sel1.split('.') ; sel1 = '%d.%s' % (int(row)-1,col)
    row,col = sel2.split('.') ; sel2 = '%d.%s' % (int(row)-1,col)
    newSel = sel1,sel2
    c.updateBodyPane(head,lines,tail,undoType,newSel,oldYview)</t>
<t tx="ekr.20111017085134.16078">'''Analyze external calls in lisp files.'''

import glob
class lispAnalyzer:
    @others

base = '/media/disk/XEmacs/XEmacs-21.4.13/lisp/*.el'
paths = glob.glob(base)
# g.es(g.listToString(paths))
paths = [paths[0]]

x = lispAnalyzer(c,paths)
x.run()</t>
<t tx="ekr.20111017085134.16079">def __init__ (self,c,paths):

    self.c = c
    self.paths = paths

    # Debugging.
    self.debug = True
    self.trace = False

    # Semantic info.
    self.def_keywords = ('defun','defvar',)
    self.indent_keywords = ('if','prog','prog1','progn','set',)
    self.expr_keywords = ('and','not','or',)

    self.indent = 0 # Indentation of production output.

    # Dispatch dictionary.
    self.dispatchDict = {}</t>
<t tx="ekr.20111017085134.16080">def run(self):

    fn = self.paths[0]
    f = open(fn)
    s = f.read()
    g.es_print(fn)
    # g.trace(s)
    s = self.stripStrings(s)
    s = self.stripComments(s)
    defs = self.findDefs(s)
    calls = self.findCalls(s,defs)
    calls = self.stripLispIds(calls)
    defs.sort()
    calls.sort()
    g.trace('defs...\n',g.listToString(defs))
    g.trace('calls...\n',g.listToString(calls))
</t>
<t tx="ekr.20111017085134.16081">def findCalls (self,s,defs):

    calls = []
    i = 0
    while i &lt; len(s):
        progress = i
        ch = s[i]
        if ch.isalnum() or ch == u'_':
            j = self.skipId(s,i)
            theId = s[i:j].strip()
            if theId not in defs and theId not in calls:
                calls.append(theId)
            i = j
        else: i += 1
        assert progress &lt; i

    return calls       
</t>
<t tx="ekr.20111017085134.16082">def findDefs (self,s):

    defs = [] ; tag = '(defun'
    i = 0
    while True:
        progress = i
        j = s.find(tag,i)
        if j == -1:
            return defs
        i = j + len(tag)
        j = g.skip_ws(s,i)
        if j &gt; i:
            k = self.skipId(s,j)
            if k &gt; j:
                defs.append(s[j:k])
            i = k
        assert progress &lt; i 
</t>
<t tx="ekr.20111017085134.16083">def stripComments(self,s):

    result = []
    i = 0
    while i &lt; len(s):
        progress = i
        ch = s[i]
        if ch == ';':
            i = self.skipComment(s,i)
        else:
            result.append(ch)
            i += 1
        assert progress &lt; i

    return ''.join(result)
</t>
<t tx="ekr.20111017085134.16084">def stripLispIds (self,aList):

    lispIds = [
        't','f',
        'apply',
        'boundp',
        'car','cons','cdr','consp',
        'eq','equal','eval',
        'lamda','lambda',
        'macro',
        'nil','not','null','numberp',
        'or',
        'unless',
        'vector','vectorp',
        # special forms
        'and',
        'catch',
        'cond',
        'condition-case',
        'defconst',
        'defmacro',
        'defun',
        'defvar',
        'function',
        'if',
        'interactive',
        'let',
        'let*',
        'or',
        'prog1',
        'prog2',
        'progn',
        'quote',
        'save-current-buffer',
        'save-excursion',
        'save-restriction',
        'save-window-excursion',
        'setq',
        'setq-default',
        'track-mouse',
        'unwind-protect',
        'while',
        'with-output-to-temp-buffer',
    ]

    return [z for z in aList if z not in lispIds]</t>
<t tx="ekr.20111017085134.16085">def stripStrings(self,s):

    result = []
    i = 0
    while i &lt; len(s):
        progress = i
        ch = s[i]
        if ch == '"':
            i = self.skipString(s,i)
        elif ch == "'":
            i = self.skipId(s,i+1)
        else:
            result.append(ch)
            i += 1
        assert progress &lt; i

    return ''.join(result)
</t>
<t tx="ekr.20111017085134.16086">class token:

    '''Representing one elisp syntactic entity,
    with a list of preceding comments.'''

    def __init__ (self,comments,kind,val):
        self.comments = comments[:]
        self.kind = kind
        self.val = val
            # For blocks, a list of tokens.
            # For all other tokens, the spelling of the token.

    def __repr__ (self):
        return '&lt;token kind: %s, val: %s&gt;' % (self.kind,self.val)

    def __str__ (self):
        if self.kind == 'block:':
            return 'block: [snip]'
        elif self.kind == 'string:':
            return '%s%s' % (self.kind,self.val[:20])
        else:
            return '%s%s' % (self.kind,self.val)
</t>
<t tx="ekr.20111017085134.16087">def choose(self,cond,a,b): # warning: evaluates all arguments

    if cond: return a
    else: return b
</t>
<t tx="ekr.20111017085134.16088">def dumpList(self,aList):

    if type(aList) == type([]):
        result = self.dumpListHelper(aList,indent=0)
        return '\n'.join(result)
    else:
        return repr(aList)

def dumpListHelper(self,aList,indent):

    result = []
    leading = ' ' * (4 * indent)

    for z in aList:
        if z is None:
            result.append('%s%s' % (leading,'None'))
        elif z == []:
            result.append('%s%s' % (leading,'[]'))
        elif type(z) == type([]):
            result.append('%s%s' % (leading,'['))
            result.extend(self.dumpListHelper(z,indent+1))
            result.append('%s%s' % (leading,']'))
        elif isinstance(z,self.token):
            if z.kind=='block:':
                result.append('%s%s' % (leading,'block:'))
                result.extend(self.dumpListHelper(z.val,indent+1))
                # result.append('%s%s' % (leading,'block:]'))
            else:
                result.append('%s%s' % (leading,str(z)))
        else:
            result.append('%s%s' % (leading,str(z)))

    return result

listToString = dumpList</t>
<t tx="ekr.20111017085134.16089"></t>
<t tx="ekr.20111017085134.16090">def parse(self,s):

    # Generate the nodes, including directive and section references.
    return self.scanForest(s)
</t>
<t tx="ekr.20111017085134.16091">def scan(self,s,i):

    '''Scan an elisp expression.'''

    start = i ; end = len(s) ; result = []
    comments = [] ; token = self.token
    # A hack. ignore initial @language lisp
    tag = '@language lisp'
    if i == 0 and s[i:i+len(tag)]==tag:
        i += len(tag)
    while i &lt; end:
        progress = i
        ch = s[i]
        if ch == ';':
            j = self.skipComment(s,i)
            start = i = j
        elif ch == '"':
            j = self.skipString(s,i)
            start = i = j
        elif ch.isalnum() or ch == u'_':
            j = self.skipId(s,i)
            result.append(token(comments,'id:',s[i:j]))
            start = i = j
        elif ch =='(':
            i += 1
            j,aList = self.scan(s,i)
            result.append(token(comments,'block:',aList))
            start = i = j
        elif ch == ')':
            i += 1
            return i,result
        else:
            # if ch == "'": ch = 'quote'
            # if ch not in (' ','\t','\n','\r'):
                # result.append(token(comments,'op:',ch))
            i += 1
        assert progress &lt; i,'i: %d, ch: %s' % (i,repr(s[i]))

    if start &lt; end:
        tail = s[start:end].strip()
        if tail:
            result.append(token(comments,'tail:',tail))
            comment = []
    if comments:
        result.append(token(comments,'trailing-comment:',''))

    return i,result
</t>
<t tx="ekr.20111017085134.16092">def skipComment (self,s,i):

    '''Skip a comment.'''

    while i &lt; len(s):
        if s[i] == '\n':
            break
        i += 1
    return i
</t>
<t tx="ekr.20111017085134.16093">def skipId (self,s,i):

    while i &lt; len(s):
        ch = s[i]
        if ch.isalnum() or ch in ('_','-'):
            i += 1
        else:
            break
    return i
</t>
<t tx="ekr.20111017085134.16094">def skipString(self,s,i):

    """Skip a string literal."""

    assert(s[i] == '"')
    i += 1
    while i &lt; len(s):
        ch = s[i]
        if ch == '\\' : i += 2
        elif ch == '"':
            i += 1 ; break
        else: i += 1

    return i</t>
<t tx="ekr.20111017085134.16095">def scanForest (self,s):

    i = 0 ; result = []

    while i &lt; len(s):
        progress = i
        i,aList = self.scan(s,i)
        aList and result.extend(aList)
        assert i &gt; progress

    return result


</t>
<t tx="ekr.20111017085134.16096">@ From Richard Deibenkorn:

1. Attempt what is not certain. Certainty may or may not come later. It may then
be a valuable delusion.

2. The pretty, initial position which falls short of completeness is not to be
valued--except as stimulus for further moves.

3. Do search.  But in order to find other than what is looked for.

4. Use and respond to the initial fresh qualities but consider them absolutely
expendable.
</t>
<t tx="ekr.20111017085134.16097">def gen(self,tokens,indent,init=False):

    result = []

    if init: result.append('='*40)

    for token in tokens:
        aList = self.gen_token(token,indent)
        result.extend(aList)

    if init: result.append('-'*40)

    return result

</t>
<t tx="ekr.20111017085134.16098">def gen_token(self,token,indent):

    result = []

    if self.debug:
        if token.kind == 'block:':
            aList = self.gen_block(token,indent)
            result.extend(aList)
        else:
            self.put_token(token,indent,result)
    else:
        if token.kind == 'block:':
            self.gen_block(token,indent)
        else:
            self.put_code_token(token)

    return result
</t>
<t tx="ekr.20111017085134.16099">def gen_block (self,token,indent):

    if not (token and token.val):
        return []

    blockList = token.val
    token2 = blockList[0]
    result = []

    if token2.kind.startswith('id'):
        aList = self.gen_block_id(token2.val,blockList,indent)
    else:
        if self.debug:
            self.put('block...',[],indent,result)
        aList = self.gen(token.val,indent+1)

    result.extend(aList)
    return result
</t>
<t tx="ekr.20111017085134.16100">def gen_block_id (self,theId,tokens,indent):

    result = []

    # Eventually there will be a lookup of the dispatch dict here.
    if theId == 'let':
        aList = self.gen_let(tokens,indent)
    elif theId == 'if':
        aList = self.gen_if(tokens,indent)
    elif theId in self.def_keywords:
        aList = self.gen_def(theId,tokens,indent)
    elif theId in self.indent_keywords:
        self.put('%s...' % (theId),[],indent,result)
        aList = self.gen(tokens[1:],indent+1)
    elif theId in self.expr_keywords:
        aList = self.gen_expr(theId,tokens[1:],indent+1)
    else:
        aList = self.gen_call(theId,tokens[1:],indent)

    result.extend(aList)
    return result
</t>
<t tx="ekr.20111017085134.16101">def gen_call (self,funcId,tokens,indent):

    result = []

    if self.debug:
        self.put('call: %s' % (funcId),[],indent,result)
        for token in tokens:
            aList = self.gen_arg(token,indent+1)
            result.extend(aList)
    else:
        self.put_code_line('%s(' % (funcId))
        for token in tokens:
            self.gen_arg(token,indent+1)
        self.put_code(')')

    return result

</t>
<t tx="ekr.20111017085134.16102">def gen_arg(self,token,indent):

    result = []

    if self.debug:
        if token.kind == 'block:':
            self.put('arg block:...',[],indent,result)
            aList = self.gen_block(token,indent)
            result.extend(aList)
        else:
            self.put_token(token,indent,result)
    else:
        if token.kind == 'block:':
            aList = self.gen_block(token,indent)
            self.put_code(''.join(aList))
        else:
            self.put_code_token(token)

    return result
</t>
<t tx="ekr.20111017085134.16103">def gen_def(self,theId,tokens,indent):

    result = []

    if not tokens or len(tokens) &lt; 3:
        result.append('*** bad def tokens')
        return result

    defToken,idToken = tokens[0:2]
    if idToken.kind != 'id:':
        result.append('*** bad def id')
        return result

    if self.debug:
        self.put(theId,idToken.val,indent,result)
        aList = self.gen(tokens[2:],indent+1)
        result.extend(aList)
    else:
        self.put_code('def %s (' % idToken.val)
        self.gen_token(tokens[2],indent)
        self.put_code('): # end def\n')
        self.indent += 1
        self.gen(tokens[3:],indent+1)
        self.indent -= 1

    return result
</t>
<t tx="ekr.20111017085134.16104">@ if condition then-form else-forms.

If the evaluated condition is non-nil, then-form is evaluated and the result
returned. Otherwise, the else-forms are evaluated in textual order, and the
value of the last one is returned. If condition has the value nil, and no
else-forms are given, if returns nil.
@c

def gen_if (self,tokens,indent):

    # tokens[0]: id:if
    # tokens[1] cond

    for i in xrange(len(tokens)):
        g.trace('tokens[%d]: %s' % (i,self.dumpList(tokens[i])))

    # g.trace(self.dumpList(tokens))

    result = []

    if self.debug:
        self.put('if...',[],indent,result)
        aList = self.gen(tokens[1:],indent+1)
        result.extend(aList)
    else:
        self.put_code('if ')
        self.gen(tokens[1:],indent+1)
        self.put_code(': # end if\n')

    return result
</t>
<t tx="ekr.20111017085134.16105">def gen_then (self,token):

    pass
</t>
<t tx="ekr.20111017085134.16106">def gen_expr (self,theId,aList,indent):

    binops = ('and','or',)
    result = []

    self.put(theId,[],indent,result)
    aList = self.gen(aList,indent+1)

    result.extend(aList)
    return result
</t>
<t tx="ekr.20111017085134.16107">@
(let ((variable value)
      (variable value)
      ...)
  body...)
@c

def gen_let (self,tokens,indent):

    if not tokens: return []
    if len(tokens) != 3:
        g.trace('unusual let')
        result = self.gen(tokens,indent+1)
        return result

    if 0:
        for i in xrange(len(tokens)):
            g.trace('token',i,tokens[i])

    letToken,bindingToken,bodyToken = tokens
    result = []
    self.put('let...',[],indent,result)
    self.put('let-bindings...',[],indent+1,result)
    aList = self.gen_let_bindings(bindingToken,indent+2)
    result.extend(aList)
    self.put('let-block...',[],indent+1,result)
    aList = self.gen_block(bodyToken,indent+2)
    result.extend(aList)
    return result</t>
<t tx="ekr.20111017085134.16108">def gen_let_bindings (self,token,indent):

    result = []

    if token.kind != 'block:':
        g.trace('unexpected let')
        return result

    for z in token.val:
        if z.kind == 'block:': # one (id,val) pair
            if z.val and len(z.val) == 2:
                token1 = z.val[0]
                token2 = z.val[1]
                self.put('let-id',token1,indent,result)
                self.put('let-val...',[],indent,result)
                if token2.kind == 'block:':
                    aList = self.gen_block(token2,indent+1)
                    result.extend(aList)
                else:
                    #g.trace('no let list')
                    self.put_token(token2,indent+1,result)
            else:
                g.trace('unexpected let 2')

    return result
</t>
<t tx="ekr.20111017085134.16109"></t>
<t tx="ekr.20111017085134.16110">def put (self,kind,val,indent,result):

    '''Append one or more lines of output to result.'''

    leading = '%2d: %s' % (indent,' ' * indent)

    if kind == 'string:':
        val = self.choose(len(val)&gt;20,val[:20]+'..."',val)

    if val:
        s = '%s%s %s' % (leading,str(kind),str(val))
    else:
        s = '%s%s' % (leading,str(kind))

    result.append(s)
</t>
<t tx="ekr.20111017085134.16111">def put_token (self,token,indent,result):

    for z in token.comments:
        self.put('comment:',z,indent,result)

    self.put(token.kind,token.val,indent,result)
</t>
<t tx="ekr.20111017085134.16112">def put_code_line (self,s):

    s2 = '%s%s' % (' '*self.indent,s)
    print s2,

def put_code (self,s):

    print s,
</t>
<t tx="ekr.20111017085134.16113">def put_code_token (self,token):

    if token.kind == 'block:':
        self.put_code('&lt;block&gt;')
    else:
        self.put_code(token.val)

</t>
<t tx="ekr.20111017085134.16114">result = []
firstLevel = p.level()

for p in p.self_and_subtree_iter():
    head = p.moreHead(firstLevel)
    head = g.toEncodedString(head,'ascii',reportErrors=True)
    result.append(head)
    body = p.moreBody() # Inserts escapes for '+' and '-' characters.
    if body:
        body = g.toEncodedString(body,'ascii',reportErrors=True)
        result.append(body)

result = '\n'.join(result) + '\n'
# print result
w = c.frame.body.bodyCtrl
w.clipboard_clear()
w.clipboard_append(result)</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.20150508132450.1">g.cls()

class CreateDecorators:
    '''
    A class to create decorators from tables in getPublicCommands.
    This class uses a node called "Found: getPublicCommands".
    
    This @button node must be executed in LeoPy.leo.
    '''
    def __init__(self,c):
        self.c = c
        self.fixups = self.create_fixups()
        self.n = 0
        self.n_fail = 0
    @others

CreateDecorators(c).run()
</t>
<t tx="ekr.20150508132450.2">def create_d(self,lines,publicCommands):
    '''Create a dict. keys are method names; values are command names.'''
    trace = False
    if trace:
        print('')
        g.trace(publicCommands.h)
    d = {}
    for s in lines:
        aList = s.split()
        if len(aList) &gt; 2:
            aList = [aList[0],' '.join(aList[1:])]
        c_name,f_name = aList[0].strip(),aList[1].strip()
        if ' ' not in f_name:
            f_name = f_name.split('.')[-1]
        # if '(' in f_name:
            # f_name = f_name[:f_name.find('(')]
        if trace: g.trace('%45s %s' % (c_name,f_name))
        d [f_name] = c_name
    return d
</t>
<t tx="ekr.20150508132450.3">def create_decorator(self,c_name,f_name,root):
    '''
    Search root for a definition of f_name.
    If found, insert @cmd(f_name) before the definition.
    '''
    # g.trace('%45s %s' % (c_name,f_name))
    found = False
    for p in root.self_and_subtree():
        result = []
        for s in g.splitLines(p.b):
            if g.match_word(s,0,'def ' + f_name):
                if found:
                    g.trace('duplicate def',f_name)
                else:
                    found = True
                    decorator = '@cmd(%s)\n' % (c_name)
                    result.append(decorator)
                    # print('%s%s' % (decorator,s))
            result.append(s)
    return found
</t>
<t tx="ekr.20150508132450.4">def create_decorators(self,d,root):
    '''Create decorators for all items in d in root's tree.'''
    print('\n%s\n' % root.h)
    if root.h in self.fixups:
        roots = []
        aList = self.fixups.get(root.h)
        for root2_h in aList:
            root2 = g.findNodeAnywhere(self.c,root2_h)
            if root2:
                g.trace(root.h,'=====&gt;',root2.h)
                roots.append(root2)
            else:
                g.trace('===== not found',root2_h)
    else:
        roots = [root]
    for f_name in sorted(d.keys()):
        found = False
        for root in roots:
            c_name = d.get(f_name)
            found = self.create_decorator(c_name,f_name,root)
            if found: break
        if not found:
            g.trace('not found',f_name)
            self.n_fail += 1
</t>
<t tx="ekr.20150508132450.5">def create_fixups(self):
    '''
    Return a fixup dict.
    Keys are headlines for classes.
    Values are new headlines of nodes containing the actual class.
    '''
    return {
        'ChapterCommandsClass': ['class ChapterController'],
        'EditCommandsClass': [
            'EditCommandsClass',
            'class Commands',
            'class LeoQtFrame',
            'class LeoBody',
        ],
        'class SearchCommandsClass': ['class LeoFind (LeoFind.py)'],
        'KeyHandlerCommandsClass (add docstrings)': [
            'class KeyHandlerClass',
            'class AutoCompleterClass',
        ]
    }
</t>
<t tx="ekr.20150508132450.6">def find_class(self,p):
    '''Return the position of the class enclosing p.'''
    for p2 in p.parents():
        if p2.h.lower().find('class') &gt; -1 and p2.b.find('class') &gt; -1:
            return p2
    else:
        g.trace('*** no class for p.h')
        return None
</t>
<t tx="ekr.20150508132450.7">def find_next_clone(self,p):
    v = p.v
    p = p.copy()
    p.moveToThreadNext()
    wrapped = False
    while 1:
        # g.trace(p.v,p.h)
        if p and p.v == v:
            break
        elif p:
            p.moveToThreadNext()
        elif wrapped:
            break
        else:
            wrapped = True
            p = c.rootPosition()
    return p
</t>
<t tx="ekr.20150508132450.8">def munge_lines(self,root,publicCommands):
    '''Return munged lines of '''
    # print('')
    # g.trace(root.h)
    s = publicCommands.b
    i,j = s.find('{'),s.find('}')
    s = s[i+1:j]
    # print(s)
    lines = sorted([z.strip() for z in g.splitLines(s) if z.strip()])
    lines = [z for z in lines if not z.startswith('#')]
    lines = [z[:z.find('#')] if z.find('#') &gt; -1 else z for z in lines]
    lines = [z.rstrip().rstrip(',') for z in lines]
    lines = [z[1:] for z in lines]
    lines = [z.replace("':",' ') for z in lines]
    # print('\n'.join(lines))
    self.n += len(lines)
    return lines
</t>
<t tx="ekr.20150508132450.9">def run(self):
    '''Top-level code.'''
    self.n = 0
    found = g.findNodeAnywhere(c,'Found: getPublicCommands')
    assert found
    for child in found.children():
        publicCommands = self.find_next_clone(child)
        root = self.find_class(publicCommands)
        if root:
            lines = self.munge_lines(root,publicCommands)
            d = self.create_d(lines,publicCommands)
            self.create_decorators(d,root)
    print('\n%s commands %s failed' % (self.n,self.n_fail))
</t>
<t tx="ekr.20150525161132.1">r'''The script to test AddTokensToTree class.'''
g.cls()
if c.isChanged():
    c.save()
&lt;&lt; imports &gt;&gt;
project = False
if project:
    aList = leoBeautify.ProjectUtils().project_files('leo')
    aList = ['@file %s' % (g.shortFileName(z).rstrip()) for z in aList]
    aList = aList
    settings_d = {}
else:
    aList = [
        'unit test: leoBeautify.py',
        # '@file leoFileCommands.py',
        # '@file leoBeautify.py',
    ]
    settings_d = {
        'ast_tokens_d': False,
        'stats': True,
        'input_string': True,
        'input_lines': False,
        'input_tokens': False,
        'token_list': False,
        'code_list': False,
        'output_string': True,
    }
assert aList,'no input in %s' % (p.h)
t1 = time.clock()
for h in aList:
    p2 = g.findNodeAnywhere(c,h)
    if p2:
        try:
            leoBeautify.test_LeoTidy(c,h,p2,settings_d)
        except Exception:
            g.es_exception()
if project:
    print('done: %4.2f sec.' % (time.clock()-t1))
</t>
<t tx="ekr.20150525161132.2"># import leo.external.PythonTidy as PythonTidy
import leo.core.leoAst as leoAst
import leo.core.leoBeautify as leoBeautify
import imp
import time
imp.reload(leoAst)
imp.reload(leoBeautify)
# imp.reload(PythonTidy)</t>
<t tx="ekr.20160123185308.1">'''
Make a stub file in the ~/home directory for every @&lt;file&gt; node in the
selected tree.
'''
import ast
import os
import textwrap
import leo.core.leoGlobals as g
@others
MakeStubFile(c).run(c.p)
</t>
<t tx="ekr.20160123185308.10">def format(self, node):
    '''Format the node (or list of nodes) and its descendants.'''
    self.level = 0
    val = self.visit(node)
    return val and val.strip() or ''
</t>
<t tx="ekr.20160123185308.11">def visit(self, node):
    '''Return the formatted version of an Ast node, or list of Ast nodes.'''
    if isinstance(node, (list, tuple)):
        return ','.join([self.visit(z) for z in node])
    elif node is None:
        return 'None'
    else:
        assert isinstance(node, ast.AST), node.__class__.__name__
        method_name = 'do_' + node.__class__.__name__
        method = getattr(self, method_name)
        s = method(node)
        # pylint: disable=unidiomatic-typecheck
        assert type(s) == type('abc'), type(s)
        return s
</t>
<t tx="ekr.20160123185308.12"></t>
<t tx="ekr.20160123185308.13"># ClassDef(identifier name, expr* bases, stmt* body, expr* decorator_list)

def do_ClassDef(self, node):
    result = []
    name = node.name # Only a plain string is valid.
    bases = [self.visit(z) for z in node.bases] if node.bases else []
    if bases:
        result.append(self.indent('class %s(%s):\n' % (name, ','.join(bases))))
    else:
        result.append(self.indent('class %s:\n' % name))
    for z in node.body:
        self.level += 1
        result.append(self.visit(z))
        self.level -= 1
    return ''.join(result)
</t>
<t tx="ekr.20160123185308.14"># FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list)

def do_FunctionDef(self, node):
    '''Format a FunctionDef node.'''
    result = []
    if node.decorator_list:
        for z in node.decorator_list:
            result.append('@%s\n' % self.visit(z))
    name = node.name # Only a plain string is valid.
    args = self.visit(node.args) if node.args else ''
    result.append(self.indent('def %s(%s):\n' % (name, args)))
    for z in node.body:
        self.level += 1
        result.append(self.visit(z))
        self.level -= 1
    return ''.join(result)
</t>
<t tx="ekr.20160123185308.15">def do_Interactive(self, node):
    for z in node.body:
        self.visit(z)
</t>
<t tx="ekr.20160123185308.16">def do_Module(self, node):
    assert 'body' in node._fields
    result = ''.join([self.visit(z) for z in node.body])
    return result # 'module:\n%s' % (result)
</t>
<t tx="ekr.20160123185308.17">def do_Lambda(self, node):
    return self.indent('lambda %s: %s' % (
        self.visit(node.args),
        self.visit(node.body)))
</t>
<t tx="ekr.20160123185308.18"></t>
<t tx="ekr.20160123185308.19">def do_Expr(self, node):
    '''An outer expression: must be indented.'''
    return self.indent('%s\n' % self.visit(node.value))
</t>
<t tx="ekr.20160123185308.2">class MakeStubFile:
    '''A class to make Python stub (.pyi) files.'''
    @others
</t>
<t tx="ekr.20160123185308.20">def do_Expression(self, node):
    '''An inner expression: do not indent.'''
    return '%s\n' % self.visit(node.body)
</t>
<t tx="ekr.20160123185308.21">def do_GeneratorExp(self, node):
    elt = self.visit(node.elt) or ''
    gens = [self.visit(z) for z in node.generators]
    gens = [z if z else '&lt;**None**&gt;' for z in gens] ### Kludge: probable bug.
    return '&lt;gen %s for %s&gt;' % (elt, ','.join(gens))
</t>
<t tx="ekr.20160123185308.22">def do_AugLoad(self, node):
    return 'AugLoad'

def do_Del(self, node):
    return 'Del'

def do_Load(self, node):
    return 'Load'

def do_Param(self, node):
    return 'Param'

def do_Store(self, node):
    return 'Store'
</t>
<t tx="ekr.20160123185308.23"></t>
<t tx="ekr.20160123185308.24"># arguments = (expr* args, identifier? vararg, identifier? kwarg, expr* defaults)

def do_arguments(self, node):
    '''Format the arguments node.'''
    kind = self.kind(node)
    assert kind == 'arguments', kind
    args = [self.visit(z) for z in node.args]
    defaults = [self.visit(z) for z in node.defaults]
    # Assign default values to the last args.
    args2 = []
    n_plain = len(args) - len(defaults)
    for i in range(len(args)):
        if i &lt; n_plain:
            args2.append(args[i])
        else:
            args2.append('%s=%s' % (args[i], defaults[i - n_plain]))
    # Now add the vararg and kwarg args.
    name = getattr(node, 'vararg', None)
    if name: args2.append('*' + name)
    name = getattr(node, 'kwarg', None)
    if name: args2.append('**' + name)
    return ','.join(args2)
</t>
<t tx="ekr.20160123185308.25"># Python 3:
# arg = (identifier arg, expr? annotation)

def do_arg(self, node):
    if node.annotation:
        return self.visit(node.annotation)
    else:
        return ''
</t>
<t tx="ekr.20160123185308.26"># Attribute(expr value, identifier attr, expr_context ctx)

def do_Attribute(self, node):
    return '%s.%s' % (
        self.visit(node.value),
        node.attr) # Don't visit node.attr: it is always a string.
</t>
<t tx="ekr.20160123185308.27">def do_Bytes(self, node): # Python 3.x only.
    assert g.isPython3
    return str(node.s)
</t>
<t tx="ekr.20160123185308.28"># Call(expr func, expr* args, keyword* keywords, expr? starargs, expr? kwargs)

def do_Call(self, node):
    # g.trace(node,Utils().dump_ast(node))
    func = self.visit(node.func)
    args = [self.visit(z) for z in node.args]
    for z in node.keywords:
        # Calls f.do_keyword.
        args.append(self.visit(z))
    if getattr(node, 'starargs', None):
        args.append('*%s' % (self.visit(node.starargs)))
    if getattr(node, 'kwargs', None):
        args.append('**%s' % (self.visit(node.kwargs)))
    args = [z for z in args if z] # Kludge: Defensive coding.
    return '%s(%s)' % (func, ','.join(args))
</t>
<t tx="ekr.20160123185308.29"># keyword = (identifier arg, expr value)

def do_keyword(self, node):
    # node.arg is a string.
    value = self.visit(node.value)
    # This is a keyword *arg*, not a Python keyword!
    return '%s=%s' % (node.arg, value)
</t>
<t tx="ekr.20160123185308.3">def __init__(self, c):
    self.c = c
    self.d = self.scan_types_data(c) or self.make_types_dict(c)
        # Keys are strings, values are Type objects.
</t>
<t tx="ekr.20160123185308.30">def do_comprehension(self, node):
    result = []
    name = self.visit(node.target) # A name.
    it = self.visit(node.iter) # An attribute.
    result.append('%s in %s' % (name, it))
    ifs = [self.visit(z) for z in node.ifs]
    if ifs:
        result.append(' if %s' % (''.join(ifs)))
    return ''.join(result)
</t>
<t tx="ekr.20160123185308.31">def do_Dict(self, node):
    result = []
    keys = [self.visit(z) for z in node.keys]
    values = [self.visit(z) for z in node.values]
    if len(keys) == len(values):
        result.append('{\n' if keys else '{')
        items = []
        for i in range(len(keys)):
            items.append('  %s:%s' % (keys[i], values[i]))
        result.append(',\n'.join(items))
        result.append('\n}' if keys else '}')
    else:
        print('Error: f.Dict: len(keys) != len(values)\nkeys: %s\nvals: %s' % (
            repr(keys), repr(values)))
    return ''.join(result)
</t>
<t tx="ekr.20160123185308.32">def do_Ellipsis(self, node):
    return '...'
</t>
<t tx="ekr.20160123185308.33">def do_ExtSlice(self, node):
    return ':'.join([self.visit(z) for z in node.dims])
</t>
<t tx="ekr.20160123185308.34">def do_Index(self, node):
    return self.visit(node.value)
</t>
<t tx="ekr.20160123185308.35">def do_List(self, node):
    # Not used: list context.
    # self.visit(node.ctx)
    elts = [self.visit(z) for z in node.elts]
    elst = [z for z in elts if z] # Defensive.
    return '[%s]' % ','.join(elts)
</t>
<t tx="ekr.20160123185308.36">def do_ListComp(self, node):
    elt = self.visit(node.elt)
    gens = [self.visit(z) for z in node.generators]
    gens = [z if z else '&lt;**None**&gt;' for z in gens] ### Kludge: probable bug.
    return '%s for %s' % (elt, ''.join(gens))
</t>
<t tx="ekr.20160123185308.37">def do_Name(self, node):
    return node.id
</t>
<t tx="ekr.20160123185308.38">def do_Num(self, node):
    return repr(node.n)
</t>
<t tx="ekr.20160123185308.39"># Python 2.x only

def do_Repr(self, node):
    return 'repr(%s)' % self.visit(node.value)
</t>
<t tx="ekr.20160123185308.4">def make_types_dict(self, c):
    '''Return a dict whose keys are names and values are type specs.'''
    return {
        'aList': 'Sequence',
        'aList2': 'Sequence',
        'c': 'Commander',
        'i': 'int',
        'j': 'int',
        'k': 'int',
        'node': 'ast.Ast',
        'p': 'Position',
        's': 'str',
        's2': 'str',
        'v': 'VNode',
    }
</t>
<t tx="ekr.20160123185308.40">def do_Slice(self, node):
    lower, upper, step = '', '', ''
    if getattr(node, 'lower', None) is not None:
        lower = self.visit(node.lower)
    if getattr(node, 'upper', None) is not None:
        upper = self.visit(node.upper)
    if getattr(node, 'step', None) is not None:
        step = self.visit(node.step)
    if step:
        return '%s:%s:%s' % (lower, upper, step)
    else:
        return '%s:%s' % (lower, upper)
</t>
<t tx="ekr.20160123185308.41">def do_Str(self, node):
    '''This represents a string constant.'''
    return repr(node.s)
</t>
<t tx="ekr.20160123185308.42"># Subscript(expr value, slice slice, expr_context ctx)

def do_Subscript(self, node):
    value = self.visit(node.value)
    the_slice = self.visit(node.slice)
    return '%s[%s]' % (value, the_slice)
</t>
<t tx="ekr.20160123185308.43">def do_Tuple(self, node):
    elts = [self.visit(z) for z in node.elts]
    return '(%s)' % ','.join(elts)
</t>
<t tx="ekr.20160123185308.44"></t>
<t tx="ekr.20160123185308.45">def do_BinOp(self, node):
    return '%s%s%s' % (
        self.visit(node.left),
        self.op_name(node.op),
        self.visit(node.right))
</t>
<t tx="ekr.20160123185308.46">def do_BoolOp(self, node):
    op_name = self.op_name(node.op)
    values = [self.visit(z) for z in node.values]
    return op_name.join(values)
</t>
<t tx="ekr.20160123185308.47">def do_Compare(self, node):
    result = []
    lt = self.visit(node.left)
    # ops   = [self.visit(z) for z in node.ops]
    ops = [self.op_name(z) for z in node.ops]
    comps = [self.visit(z) for z in node.comparators]
    result.append(lt)
    if len(ops) == len(comps):
        for i in range(len(ops)):
            result.append('%s%s' % (ops[i], comps[i]))
    else:
        g.trace('ops', repr(ops), 'comparators', repr(comps))
    return ''.join(result)
</t>
<t tx="ekr.20160123185308.48">def do_UnaryOp(self, node):
    return '%s%s' % (
        self.op_name(node.op),
        self.visit(node.operand))
</t>
<t tx="ekr.20160123185308.49">def do_IfExp(self, node):
    return '%s if %s else %s ' % (
        self.visit(node.body),
        self.visit(node.test),
        self.visit(node.orelse))
</t>
<t tx="ekr.20160123185308.5">def scan_types_data(self, c):
    '''Create self.d from @data stub-types nodes.'''
    aList = c.config.getData(
        'stub-types',
        strip_comments=True,
        strip_data=True)
    d = {}
    for s in aList:
        name, value = s.split(None,1)
        d[name.strip()] = value.strip()
    if False:
        for key in sorted(d.keys()):
            g.trace(key, d.get(key))
    return d
</t>
<t tx="ekr.20160123185308.50"></t>
<t tx="ekr.20160123185308.51">def do_Assert(self, node):
    test = self.visit(node.test)
    if getattr(node, 'msg', None):
        message = self.visit(node.msg)
        return self.indent('assert %s, %s' % (test, message))
    else:
        return self.indent('assert %s' % test)
</t>
<t tx="ekr.20160123185308.52">def do_Assign(self, node):
    return self.indent('%s=%s\n' % (
        '='.join([self.visit(z) for z in node.targets]),
        self.visit(node.value)))
</t>
<t tx="ekr.20160123185308.53">def do_AugAssign(self, node):
    return self.indent('%s%s=%s\n' % (
        self.visit(node.target),
        self.op_name(node.op), # Bug fix: 2013/03/08.
        self.visit(node.value)))
</t>
<t tx="ekr.20160123185308.54">def do_Break(self, node):
    return self.indent('break\n')
</t>
<t tx="ekr.20160123185308.55">def do_Continue(self, node):
    return self.indent('continue\n')
</t>
<t tx="ekr.20160123185308.56">def do_Delete(self, node):
    targets = [self.visit(z) for z in node.targets]
    return self.indent('del %s\n' % ','.join(targets))
</t>
<t tx="ekr.20160123185308.57">def do_ExceptHandler(self, node):
    result = []
    result.append(self.indent('except'))
    if getattr(node, 'type', None):
        result.append(' %s' % self.visit(node.type))
    if getattr(node, 'name', None):
        if isinstance(node.name, ast.AST):
            result.append(' as %s' % self.visit(node.name))
        else:
            result.append(' as %s' % node.name) # Python 3.x.
    result.append(':\n')
    for z in node.body:
        self.level += 1
        result.append(self.visit(z))
        self.level -= 1
    return ''.join(result)
</t>
<t tx="ekr.20160123185308.58"># Python 2.x only

def do_Exec(self, node):
    body = self.visit(node.body)
    args = [] # Globals before locals.
    if getattr(node, 'globals', None):
        args.append(self.visit(node.globals))
    if getattr(node, 'locals', None):
        args.append(self.visit(node.locals))
    if args:
        return self.indent('exec %s in %s\n' % (
            body, ','.join(args)))
    else:
        return self.indent('exec %s\n' % (body))
</t>
<t tx="ekr.20160123185308.59">def do_For(self, node):
    result = []
    result.append(self.indent('for %s in %s:\n' % (
        self.visit(node.target),
        self.visit(node.iter))))
    for z in node.body:
        self.level += 1
        result.append(self.visit(z))
        self.level -= 1
    if node.orelse:
        result.append(self.indent('else:\n'))
        for z in node.orelse:
            self.level += 1
            result.append(self.visit(z))
            self.level -= 1
    return ''.join(result)
</t>
<t tx="ekr.20160123185308.6">def make_stub_file(self, p):
    '''Make a stub file in ~/stubs for the @&lt;file&gt; node at p.'''
    import ast
    import leo.core.leoAst as leoAst
    assert p.isAnyAtFileNode()
    c = self.c
    fn = p.anyAtFileNodeName()
    if not fn.endswith('.py'):
        g.es_print('not a python file', fn)
        return
    ### abs_fn = g.os_path_finalize_join(g.app.loadDir, fn)
    abs_fn = g.fullPath(c, p)
    if not g.os_path_exists(abs_fn):
        g.es_print('not found', abs_fn)
        return
    stubs = g.os_path_finalize(g.os_path_expanduser('~/stubs'))
    if g.os_path_exists(stubs):
        base_fn = g.os_path_basename(fn)
        out_fn = g.os_path_finalize_join(stubs,base_fn)
    else:
        g.es_print('not found', stubs)
        return
        # out_fn = g.os_path_finalize_join(g.app.loadDir, fn)
    out_fn = out_fn[:-3] + '.pyi'
    s = open(abs_fn).read()
    node = ast.parse(s,filename=fn,mode='exec')
    leoAst.StubTraverser(self.c, self.d, out_fn).run(node)
</t>
<t tx="ekr.20160123185308.60">def do_Global(self, node):
    return self.indent('global %s\n' % (
        ','.join(node.names)))
</t>
<t tx="ekr.20160123185308.61">def do_If(self, node):
    result = []
    result.append(self.indent('if %s:\n' % (
        self.visit(node.test))))
    for z in node.body:
        self.level += 1
        result.append(self.visit(z))
        self.level -= 1
    if node.orelse:
        result.append(self.indent('else:\n'))
        for z in node.orelse:
            self.level += 1
            result.append(self.visit(z))
            self.level -= 1
    return ''.join(result)
</t>
<t tx="ekr.20160123185308.62">def do_Import(self, node):
    names = []
    for fn, asname in self.get_import_names(node):
        if asname:
            names.append('%s as %s' % (fn, asname))
        else:
            names.append(fn)
    return self.indent('import %s\n' % (
        ','.join(names)))
</t>
<t tx="ekr.20160123185308.63">def get_import_names(self, node):
    '''Return a list of the the full file names in the import statement.'''
    result = []
    for ast2 in node.names:
        if self.kind(ast2) == 'alias':
            data = ast2.name, ast2.asname
            result.append(data)
        else:
            g.trace('unsupported kind in Import.names list', self.kind(ast2))
    return result
</t>
<t tx="ekr.20160123185308.64">def do_ImportFrom(self, node):
    names = []
    for fn, asname in self.get_import_names(node):
        if asname:
            names.append('%s as %s' % (fn, asname))
        else:
            names.append(fn)
    return self.indent('from %s import %s\n' % (
        node.module,
        ','.join(names)))
</t>
<t tx="ekr.20160123185308.65">def do_Pass(self, node):
    return self.indent('pass\n')
</t>
<t tx="ekr.20160123185308.66"># Python 2.x only

def do_Print(self, node):
    vals = []
    for z in node.values:
        vals.append(self.visit(z))
    if getattr(node, 'dest', None):
        vals.append('dest=%s' % self.visit(node.dest))
    if getattr(node, 'nl', None):
        # vals.append('nl=%s' % self.visit(node.nl))
        vals.append('nl=%s' % node.nl)
    return self.indent('print(%s)\n' % (
        ','.join(vals)))
</t>
<t tx="ekr.20160123185308.67">def do_Raise(self, node):
    args = []
    for attr in ('type', 'inst', 'tback'):
        if getattr(node, attr, None) is not None:
            args.append(self.visit(getattr(node, attr)))
    if args:
        return self.indent('raise %s\n' % (
            ','.join(args)))
    else:
        return self.indent('raise\n')
</t>
<t tx="ekr.20160123185308.68">def do_Return(self, node):
    if node.value:
        return self.indent('return %s\n' % (
            self.visit(node.value)))
    else:
        return self.indent('return\n')
</t>
<t tx="ekr.20160123185308.69"># def do_Suite(self,node):
    # for z in node.body:
        # s = self.visit(z)
</t>
<t tx="ekr.20160123185308.7">def run(self, p):
    '''Make stub files for all files in p's tree.'''
    if p.isAnyAtFileNode():
        self.make_stub_file(p)
        return
    # First, look down tree.
    after, p2 = p.nodeAfterTree(), p.firstChild()
    found = False
    while p2 and p != after:
        if p2.isAnyAtFileNode():
            self.make_stub_file(p2)
            p2.moveToNext()
            found = True
        else:
            p2.moveToThreadNext()
    if not found:
        # Look up the tree.
        for p2 in p.parents():
            if p2.isAnyAtFileNode():
                self.make_stub_file(p2)
                break
        else:
            g.es('no files found in tree:', p.h)
</t>
<t tx="ekr.20160123185308.70">def do_TryExcept(self, node):
    result = []
    result.append(self.indent('try:\n'))
    for z in node.body:
        self.level += 1
        result.append(self.visit(z))
        self.level -= 1
    if node.handlers:
        for z in node.handlers:
            result.append(self.visit(z))
    if node.orelse:
        result.append('else:\n')
        for z in node.orelse:
            self.level += 1
            result.append(self.visit(z))
            self.level -= 1
    return ''.join(result)
</t>
<t tx="ekr.20160123185308.71">def do_TryFinally(self, node):
    result = []
    result.append(self.indent('try:\n'))
    for z in node.body:
        self.level += 1
        result.append(self.visit(z))
        self.level -= 1
    result.append(self.indent('finally:\n'))
    for z in node.finalbody:
        self.level += 1
        result.append(self.visit(z))
        self.level -= 1
    return ''.join(result)
</t>
<t tx="ekr.20160123185308.72">def do_While(self, node):
    result = []
    result.append(self.indent('while %s:\n' % (
        self.visit(node.test))))
    for z in node.body:
        self.level += 1
        result.append(self.visit(z))
        self.level -= 1
    if node.orelse:
        result.append('else:\n')
        for z in node.orelse:
            self.level += 1
            result.append(self.visit(z))
            self.level -= 1
    return ''.join(result)
</t>
<t tx="ekr.20160123185308.73">def do_With(self, node):
    result = []
    result.append(self.indent('with '))
    if hasattr(node, 'context_expression'):
        result.append(self.visit(node.context_expresssion))
    vars_list = []
    if hasattr(node, 'optional_vars'):
        try:
            for z in node.optional_vars:
                vars_list.append(self.visit(z))
        except TypeError: # Not iterable.
            vars_list.append(self.visit(node.optional_vars))
    result.append(','.join(vars_list))
    result.append(':\n')
    for z in node.body:
        self.level += 1
        result.append(self.visit(z))
        self.level -= 1
    result.append('\n')
    return ''.join(result)
</t>
<t tx="ekr.20160123185308.74">def do_Yield(self, node):
    if getattr(node, 'value', None):
        return self.indent('yield %s\n' % (
            self.visit(node.value)))
    else:
        return self.indent('yield\n')
</t>
<t tx="ekr.20160123185308.75"></t>
<t tx="ekr.20160123185308.76">def kind(self, node):
    '''Return the name of node's class.'''
    return node.__class__.__name__
</t>
<t tx="ekr.20160123185308.77">def indent(self, s):
    return '%s%s' % (' ' * 4 * self.level, s)
</t>
<t tx="ekr.20160123185308.78">@nobeautify

def op_name (self,node,strict=True):
    '''Return the print name of an operator node.'''
    d = {
        # Binary operators. 
        'Add':       '+',
        'BitAnd':    '&amp;',
        'BitOr':     '|',
        'BitXor':    '^',
        'Div':       '/',
        'FloorDiv':  '//',
        'LShift':    '&lt;&lt;',
        'Mod':       '%',
        'Mult':      '*',
        'Pow':       '**',
        'RShift':    '&gt;&gt;',
        'Sub':       '-',
        # Boolean operators.
        'And':   ' and ',
        'Or':    ' or ',
        # Comparison operators
        'Eq':    '==',
        'Gt':    '&gt;',
        'GtE':   '&gt;=',
        'In':    ' in ',
        'Is':    ' is ',
        'IsNot': ' is not ',
        'Lt':    '&lt;',
        'LtE':   '&lt;=',
        'NotEq': '!=',
        'NotIn': ' not in ',
        # Context operators.
        'AugLoad':  '&lt;AugLoad&gt;',
        'AugStore': '&lt;AugStore&gt;',
        'Del':      '&lt;Del&gt;',
        'Load':     '&lt;Load&gt;',
        'Param':    '&lt;Param&gt;',
        'Store':    '&lt;Store&gt;',
        # Unary operators.
        'Invert':   '~',
        'Not':      ' not ',
        'UAdd':     '+',
        'USub':     '-',
    }
    name = d.get(self.kind(node),'&lt;%s&gt;' % node.__class__.__name__)
    if strict: assert name,self.kind(node)
    return name
</t>
<t tx="ekr.20160123185308.79">class StubFormatter (AstFormatter):
    @others
</t>
<t tx="ekr.20160123185308.8">class AstFormatter:
    '''
    A class to recreate source code from an AST.
    
    This does not have to be perfect, but it should be close.
    
    Also supports optional annotations such as line numbers, file names, etc.
    '''
    # No ctor.
    # pylint: disable=consider-using-enumerate
    @others
</t>
<t tx="ekr.20160123185308.80"># Return generic markers allow better pattern matches.

def do_BoolOp(self, node): # Python 2.x only.
    return 'bool'

def do_Bytes(self, node): # Python 3.x only.
    return 'bytes' # return str(node.s)

def do_Name(self, node):
    return 'bool' if node.id in ('True', 'False') else node.id

def do_Num(self, node):
    return 'number' # return repr(node.n)

def do_Str(self, node):
    '''This represents a string constant.'''
    return 'str' # return repr(node.s)
</t>
<t tx="ekr.20160123185308.81">class StubTraverser (ast.NodeVisitor):
    
    def __init__(self, c, d, output_fn):
        '''Ctor for StubTraverser class.'''
        self.c = c
        self.d = d
        self.format = StubFormatter().format
        self.in_function = False
        self.level = 0
        self.output_file = None
        self.output_fn = output_fn
        self.returns = set()

    @others
</t>
<t tx="ekr.20160123185308.82">def indent(self, s):
    '''Return s, properly indented.'''
    return '%s%s' % (' ' * 4 * self.level, s)

def out(self, s):
    '''Output the string to the console or the file.'''
    if self.output_file:
        self.output_file.write(self.indent(s)+'\n')
    else:
        print(self.indent(s))
</t>
<t tx="ekr.20160123185308.83">def run(self, node):
    '''StubTraverser.run: write the stubs in node's tree to self.output_fn.'''
    c = self.c
    dir_ = g.os_path_dirname(self.output_fn)
    if g.os_path_exists(dir_):
        self.output_file = open(self.output_fn, 'w')
        aList = c.config.getData('stub-prefix')
        if aList:
            for z in aList:
                self.out(z.strip())
        self.visit(node)
        self.output_file.close()
        self.output_file = None
        g.es_print('wrote', self.output_fn)
    else:
        g.es_print('not found:', dir_)

</t>
<t tx="ekr.20160123185308.84"># This is needed only when subclassing from the leoAst.AstFullTraverser class.

# def visit(self, node):
    # '''Visit a *single* ast node.  Visitors are responsible for visiting children!'''
    # assert isinstance(node, ast.AST), node.__class__.__name__
    # method = getattr(self, 'do_' + node.__class__.__name__)
    # method(node)
</t>
<t tx="ekr.20160123185308.85"></t>
<t tx="ekr.20160123185308.86"># ClassDef(identifier name, expr* bases, stmt* body, expr* decorator_list)

def visit_ClassDef(self, node):

    # Format...
    if not node.name.startswith('_'):
        if node.bases:
            s = '(%s)' % ','.join([self.format(z) for z in node.bases])
        else:
            s = ''
        self.out('class %s%s:' % (node.name, s))
    # Visit...
    self.level += 1
    old_in_function = self.in_function
    self.in_function = False
    for z in node.body:
        self.visit(z)
    self.level -= 1
    self.in_function = old_in_function
</t>
<t tx="ekr.20160123185308.87"># FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list)

def visit_FunctionDef(self, node):
    
    # Do nothing if we are already in a function.
    # We do not generate stubs for inner defs.
    if self.in_function or node.name.startswith('_'):
        return
    # First, visit the function body.
    self.returns = set()
    self.in_function = True
    self.level += 1
    for z in node.body:
        self.visit(z)
    self.level -= 1
    self.in_function = False
    # Format *after* traversing
    self.out('def %s(%s) -&gt; %s: ...' % (
        node.name,
        self.format_arguments(node.args),
        self.format_returns(node)))
</t>
<t tx="ekr.20160123185308.88"># arguments = (expr* args, identifier? vararg, identifier? kwarg, expr* defaults)

def format_arguments(self, node):
    '''
    Format the arguments node.
    Similar to AstFormat.do_arguments, but it is not a visitor!
    '''
    assert isinstance(node,ast.arguments), node
    args = [self.format(z) for z in node.args]
    defaults = [self.format(z) for z in node.defaults]
    # Assign default values to the last args.
    result = []
    n_plain = len(args) - len(defaults)
    # pylint: disable=consider-using-enumerate
    for i in range(len(args)):
        s = self.munge_arg(args[i])
        if i &lt; n_plain:
            result.append(s)
        else:
            result.append('%s=%s' % (s, defaults[i - n_plain]))
    # Now add the vararg and kwarg args.
    name = getattr(node, 'vararg', None)
    if name: result.append('*' + name)
    name = getattr(node, 'kwarg', None)
    if name: result.append('**' + name)
    return ', '.join(result)
</t>
<t tx="ekr.20160123185308.89">def munge_arg(self, s):
    '''Add an annotation for s if possible.'''
    a = self.d.get(s)
    return '%s: %s' % (s, a) if a else s
</t>
<t tx="ekr.20160123185308.9"></t>
<t tx="ekr.20160123185308.90">def format_returns(self, node):
    '''Calculate the return type.'''
    def split(s):
        return '\n     ' + self.indent(s) if len(s) &gt; 30 else s
        
    r = list(self.returns)
    r = [self.format(z) for z in r]
    # if r: g.trace(r)
    if len(r) == 0:
        return 'None'
    if len(r) == 1:
        return split(r[0])
    elif 'None' in r:
        r.remove('None')
        return split('Optional[%s]' % ', '.join(r))
    else:
        # return 'Any'
        s = ', '.join(r)
        if len(s) &gt; 30:
            return ', '.join(['\n    ' + self.indent(z) for z in r])
        else:
            return split(', '.join(r))
</t>
<t tx="ekr.20160123185308.91">def visit_Return(self, node):

    self.returns.add(node.value)
</t>
</tnodes>
</leo_file>
