<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet ekr_test?>
<leo_file>
<leo_header file_format="2" tnodes="0" max_tnode_index="0" clone_windows="0"/>
<globals body_outline_ratio="0.5">
	<global_window_position top="93" left="213" height="720" width="890"/>
	<global_log_window_position top="0" left="0" height="0" width="0"/>
</globals>
<preferences/>
<find_panel_settings/>
<vnodes>
<v t="ekr.20080129151228"><vh>Startup</vh>
<v t="ekr.20080129151123"><vh>@chapters</vh></v>
<v t="ekr.20070315073704"><vh>@settings</vh>
<v t="ekr.20070315073704.1"><vh>@enabled-plugins</vh></v>
<v t="ekr.20070315073704.2"><vh>vim plugin</vh>
<v t="ekr.20070315073704.3"><vh>@string vim_cmd = c:\vim\vim63\gvim --servername LEO</vh></v>
<v t="ekr.20070315073704.4"><vh>@string vim_exe = c:\vim\vim63\gvim</vh></v>
</v>
</v>
<v t="ekr.20060901144246"><vh>buttons</vh>
<v t="ekr.20060901144331"><vh>@button prev-show  @key=Alt-4</vh></v>
<v t="ekr.20060901144149.3"><vh>@button next-show @key=Alt-5</vh></v>
<v t="ekr.20060901144149.2"><vh>@button prev-slide @key=Alt-6</vh></v>
<v t="ekr.20060901144359"><vh>@button next-slide @key=Alt-7</vh></v>
<v t="ekr.20060902092242"><vh>@button make-slide @key=Alt-0</vh></v>
</v>
</v>
<v t="ekr.20060901142356"><vh>Read me first</vh></v>
<v t="ekr.20060901144149.4"><vh>Sounds</vh>
<v t="ekr.20060901144149.5"><vh>@url http://mail.python.org/pipermail/python-list/2004-October/248738.html</vh></v>
<v t="ekr.20060901144149.6"><vh>@url c:\prog\Sounds\s1.wav</vh></v>
<v t="ekr.20060901144149.7"><vh>@url c:\prog\Sounds\s2.wav</vh></v>
</v>
<v t="ekr.20060902100840"><vh>To do: rst + python colorizing</vh></v>
<v t="ekr.20070315074504" a="TV"><vh>To be made into slides</vh>
<v t="ekr.20070315074504.1"><vh>a</vh></v>
<v t="ekr.20070315074504.2"><vh>b</vh></v>
</v>
<v t="ekr.20060902101656" a="E"><vh>Slide shows</vh>
<v t="ekr.20060901153101"><vh>@slideshow Introduction to Leo</vh>
<v t="ekr.20060901153101.1"><vh>@slide topic 1</vh>
<v t="ekr.20060901153101.2"><vh>@slide 2-1</vh></v>
<v t="ekr.20060901153101.3"><vh>@slide 2-2</vh></v>
</v>
<v t="ekr.20060901153101.4"><vh>@slide topic 2</vh>
<v t="ekr.20060901153101.5"><vh>@slide 2-3</vh></v>
<v t="ekr.20060901153101.6"><vh>@slide 2-4</vh></v>
</v>
</v>
<v t="ekr.20060901144149.8"><vh>@slideshow Using derived files</vh>
<v t="ekr.20060901144149.9"><vh>@slide Group 1</vh>
<v t="ekr.20060901144149.10"><vh>@slide 1-1</vh></v>
<v t="ekr.20060901144149.11"><vh>@slide 1-2</vh></v>
</v>
<v t="ekr.20060901144149.12"><vh>@slide Group 2</vh>
<v t="ekr.20060901144149.13"><vh>@slide 1-3</vh></v>
<v t="ekr.20060901144149.14"><vh>@slide 1-4</vh></v>
</v>
</v>
<v t="ekr.20060904104955"><vh>@ignore</vh>
<v t="ekr.20060904104955.1"><vh>@slideshow ignored</vh>
<v t="ekr.20060904104955.2"><vh>@slide ignored</vh></v>
</v>
</v>
<v t="ekr.20060902092259"><vh>@slideshow scripting Leo</vh>
<v t="ekr.20060902092341.4" rst_http_attribute=" "><vh>@slide Leo's classes and objects</vh></v>
<v t="ekr.20060902092341.5" rst_http_attribute=" "><vh>@slide g.es writes to the log pane</vh></v>
<v t="ekr.20060902092341.6" rst_http_attribute=" "><vh>@slide app.windowList: the list of all open frames</vh></v>
<v t="ekr.20060902092341.7" rst_http_attribute=" "><vh>@slide Getting and setting headline and body text</vh></v>
<v t="ekr.20060902092341.8" rst_http_attribute=" "><vh>@slide Traversing outlines</vh>
<v t="ekr.20060902092341.9"><vh>@slide About copying positions</vh></v>
<v t="ekr.20060902092341.10" rst_http_attribute=" "><vh>@slide c.allNodes_iter</vh></v>
<v t="ekr.20060902092341.11" rst_http_attribute=" "><vh>@slide p.children_iter</vh></v>
<v t="ekr.20060902092341.12" rst_http_attribute=" "><vh>@slide p.parents_iter &amp; p.self_and_parents_iter</vh></v>
<v t="ekr.20060902092341.13" rst_http_attribute=" "><vh>@slide p.siblings_iter &amp; p.following_siblings_iter</vh></v>
<v t="ekr.20060902092341.14" rst_http_attribute=" "><vh>@slide p.subtree_iter &amp; p.self_and_subtree_iter</vh></v>
<v t="ekr.20060902092341.15" rst_http_attribute=" "><vh>@slide Testing whether a position is valid</vh></v>
</v>
<v t="ekr.20060902092341.16" rst_http_attribute=" "><vh>@slide Updating the screen</vh></v>
<v t="ekr.20060902092341.17" rst_http_attribute=" "><vh>@slide Invoking commands from scripts</vh></v>
<v t="ekr.20060902092341.18"><vh>@slide Getting settings from @settings trees</vh></v>
<v t="ekr.20060902092341.19" rst_http_attribute=" "><vh>@slide Getting and setting preferences</vh></v>
<v t="ekr.20060902092341.20" rst_http_attribute=" "><vh>@slide Functions for finding and changing text from scripts</vh></v>
<v t="ekr.20060902092341.21" rst_http_attribute=" "><vh>@slide Running Leo in batch mode</vh></v>
<v t="ekr.20060902092341.22" rst_http_attribute=" "><vh>@slide Functions defined in leoGlobals.py</vh></v>
<v t="ekr.20060902092341.23" rst_http_attribute=" "><vh>@slide Redirecting output from scripts</vh></v>
<v t="ekr.20060902092341.24"><vh>@slide Adding new Tabs to the log pane</vh></v>
<v t="ekr.20060902092341.25" rst_http_attribute=" "><vh>@slide Summary of the vnode and position classes</vh>
<v t="ekr.20060902092341.26" rst_http_attribute=" "><vh>@slide Iterators</vh></v>
<v t="ekr.20060902092341.27" rst_http_attribute=" "><vh>@slide Getters</vh></v>
<v t="ekr.20060902092341.28" rst_http_attribute=" "><vh>@slide Setters</vh></v>
</v>
<v t="ekr.20060902092341.29"><vh>@slide Creating script buttons</vh></v>
<v t="ekr.20060902092341.30"><vh>@slide @test and @suite nodes</vh>
<v t="ekr.20060902095933"><vh>@slide @test nodes</vh></v>
<v t="ekr.20060902095933.1"><vh>@slide @suite nodes</vh></v>
</v>
<v t="ekr.20060902100250"><vh>@slide conclusion</vh></v>
</v>
</v>
</vnodes>
<tnodes>
<t tx="ekr.20060901142356">@nocolor

This file contains several slideshows illustrating Leo's features.

You control these slides shows using four buttons in the icon bar:

- 'prev-show' (Alt-4) and 'next-show' (Alt-5) move backward and forward to the start of a slideshow.

- 'prev-slide' (Alt-6) and 'next-slide' (Alt-7) move backward and forward to slides *within* a slideshow.

Now press the 'next-show' button (or type Alt-5, or type Alt-x next-show)
to take you to the first slideshow: 'Introduction to Leo'.</t>
<t tx="ekr.20060901144149.2">c.k.simulateCommand('prev-slide-command')</t>
<t tx="ekr.20060901144149.3">c.k.simulateCommand('next-slide-show-command')</t>
<t tx="ekr.20060901144149.4">from PMIDI import * 
from time import sleep </t>
<t tx="ekr.20060901144149.5"></t>
<t tx="ekr.20060901144149.6"></t>
<t tx="ekr.20060901144149.7"></t>
<t tx="ekr.20060901144149.8"></t>
<t tx="ekr.20060901144149.9"></t>
<t tx="ekr.20060901144149.10"># This is the first slide.</t>
<t tx="ekr.20060901144149.11"># This is the second slide.</t>
<t tx="ekr.20060901144149.12"></t>
<t tx="ekr.20060901144149.13">Slide 3</t>
<t tx="ekr.20060901144149.14">Slide 4
</t>
<t tx="ekr.20060901144246">@color

@ A point that can cause confusion:
    
The slideshow.py plugin defines four commands whose names end in -command. It
would be possible to bind shortcuts for *these* commands in leoSettings.leo or
myLeoSettings.leo

The buttons below define commands whose names do *not* end in -command. These
button define shortcuts for these buttons using the @key syntax.</t>
<t tx="ekr.20060901144331">c.k.simulateCommand('prev-slide-show-command')</t>
<t tx="ekr.20060901144359">c.k.simulateCommand('next-slide-command')</t>
<t tx="ekr.20060901153101">@nocolor 

This is the start of the slideshow that introduces you to Leo.</t>
<t tx="ekr.20060901153101.1"></t>
<t tx="ekr.20060901153101.2"># This is the first slide.</t>
<t tx="ekr.20060901153101.3"># This is the second slide.</t>
<t tx="ekr.20060901153101.4"></t>
<t tx="ekr.20060901153101.5">Slide 3</t>
<t tx="ekr.20060901153101.6">Slide 4
</t>
<t tx="ekr.20060902092242">c.beginUpdate()

try:
    p1 = p.copy()
    undoData = c.undoer.beforeChangeTree(p1)
    for p in c.currentPosition().self_and_subtree_iter():
        h = p.headString().strip()
        if not h.startswith('@slide'):
            p.setHeadString('@slide ' + h)
    c.undoer.afterChangeTree(p1,'make-slide',undoData)
finally:
    c.endUpdate()
</t>
<t tx="ekr.20060902092259">@nocolor

This slideshow describes the most useful functions, classes and methods in
leo.py. Keep in mind that *your scripts have complete access to all of Leo's
source code*, that is, all the code in LeoPy.leo. Your scripts can use Leo's
code in whatever ways are convenient. You are *not* limited by what you see in
this chapter.

**Important:** You can execute all the code in this slideshow. Just select the
code you want to execute and run the Execute Script command.

**Important**: Python is finicky about indentation, so you must be careful to
select the leading whitespace of the first line.</t>
<t tx="ekr.20060902092341.4">@nocolor
Leo's source code is a collection of classes, along with utility functions in
leoGlobals.py. Here are Leo's most important classes and objects:

**The Execute Script command predefines c, g and p**
    Leo's Execute Script command predefines c to be the commander of the
    outline containing the script. g and p are predefined as follows:
@color

    import leoGlobals as g
    p = c.currentPosition()
    
@nocolor
**g.app**
    The **application object** representing the entire Leo application.
    The ivars (instance variables) of g.app represent Leo's global variables.

**commander**
    An instance of the Commands class in leoCommands.py.
    Commanders represent commands for a *particular* window.
    Each open Leo window has its own commander.
    By convention, any variable named c is a commander.

**frame**
    An instance of the base leoFrame class in leoFrame.py.
    Frames contains all the internal data needed to manage a Leo window.
    Given a commander c, c.frame is commanders frame.
    Given a frame f, f.c is the frame's commander.

**position**
    An instance of the position class in leoNodes.py.
    A position object represents the location of a particular node *in a tree traversal*.
    By convention, variables named p, p1 or p2 are positions.
    For any position p, p.v is the vnode at that position and p.v.t is the tnode at that position.
    **Positions are the primary way to access data.**
    c.currentPosition and c.rootPosition return positions.
    From those starting point, it is possible to access the data in any node.

    **Important**:
    Positions can become *invalid* when the structure of the outline changes.
    Therefore, plugins and scripts must *not* store positions for use at a later time if the outline
    could have changed in the meantime.

    **Important**:
    For compatibility with old (pre-4.2) scripts, c.currentVnode and
    c.rootVnode methods return *positions* not vnodes. Old scripts appear to
    be using vnodes; in fact they are using positions. I call such scripts
    **confused** scripts. Confused scripts work because the position class
    is designed to make them work. We'll see how this works in detail in `About
    copying positions`_.  This section is **supremely important**.

**vnode**
    An instance of the vnode class in leoNodes.py.
    vnodes represent an outline node.
    Normally, scripts access vnodes via the position class described below. 
    By convention, variables named v, v1 or v2 refer to vnodes.
    **Important**: scripts normally should use positions, not vnodes.

**tnode**
    An instance of the tnode class in leoNodes.py.
    tnodes represent the actual data in a vnode, including headline and body text.
    Cloned *vnodes* share the tnode *of their first child*.
    For any vnode v, v.t is v's tnode.
    **Important**: If p is a position, p.v.t is the tnode associated with that position.
    Many positions may share the same tnode.</t>
<t tx="ekr.20060902092341.5">The g.es method prints its arguments to the Log tab of the log pane:
@color

    g.es("Hello world")
    
@nocolor
g.es converts non-string arguments using repr:
@color

    g.es(c)

@nocolor
g.es prints multiple arguments separated by commas:
@color

    g.es("Hello","world")

@nocolor
To create a tab named 'Test' or make it visible if it already exists:
@color
 
    c.frame.log.selectTab('Test')

@nocolor
When first created, a tab contains a Tk.Text widget.
To write to this widget, add the tabName argument to g.es:
@color

    g.es('Test',color='blue',tabName='Test')</t>
<t tx="ekr.20060902092341.6">@nocolor
The windowlist attribute of the application instance contains the list of the
frames of all open windows. The commands ivar of the frame gives the commander
for that frame:
@color

    windows = g.app.windowList # get the list of all open frames.
    g.es("windows...")
    for f in windows:
        c = f.c # c is f's commander
        g.es(f)
        g.es(f.shortFileName())
        g.es(c)
        g.es(c.rootPosition())</t>
<t tx="ekr.20060902092341.7">@nocolor
Here is how to access the data of a Leo window:
@color

    g.es(p) # p is already defined.
    p = c.currentPosition() # get the current position.
    g.es(p)
    g.es("head:",p.headString())
    g.es("body:",p.bodyString())

@nocolor
Here is how to access data at position p.
**Note**: these methods work whether or not p is the current position:
@color

    body = p.bodyString()
    head = p.headString()
    p.setBodyStringOrPane(body)     # set body text of p to body.
    p.setHeadStringOrHeadline(head) # set headline text of p to head.</t>
<t tx="ekr.20060902092341.8">The proper way to traverse an outline is with an iterator.
Iterators are defined only by the position class;
vnodes can not have iterators because vnodes may appear in multiple places in an outline.
</t>
<t tx="ekr.20060902092341.9">@nocolor
Understanding this section is **supremely important** for anyone who wants to
script Leo properly.

By default, all iterators discussed below use a **single** position to move
through the outline. This is a vital optimization; otherwise Leo would generate
one or more position object for each node of a tree traversal. However, it means
that it is **useless** to try to capture a position with:
@color

    p2 = p  # Wrong.  p2 will change after this assignment.

@nocolor
Instead, scripts and plugins should use p.copy() to 'capture' the value of a position:
@color

    p2 = p.copy()   # Correct: p2 will not change when p changes later.

@nocolor
Another way to solve this problem is to set copy=True when using an iterator:
@color

    d = {}
    for p in c.allNodes_iter(copy=True):
@color
        d[p.v.t] = p

@nocolor
This creates a dictionary of (unchanging!) positions, indexed via tnode.
**Warning** The positions in this dictionary will become invalid when the
outline's structure changes. It would be wrong to save a dictionary like this
for use between commands.

Setting the copy=True argument to iterators is an acceptable strategy for
infrequently used scripts; it is not acceptable for heavily used code in Leo's
core: it would create huge numbers of positions that would immediately be
candidates for garbage collection.

**Important**: 'Confused' scripts work because the position methods that
simulate the old vnode methods automatically create copies of positions when
'moving' through an outline. Thus, confused scripts generate many more positions
than would the equivalent script that uses position iterators. Such is the
price of compatibility.</t>
<t tx="ekr.20060902092341.10">@nocolor
The c.allNodes_iter iterator returns a list of all positions in the outline.
This script makes a list of all the nodes in an outline:
@color

    nodes = [p for p in c.allNodes_iter()]
    g.es("This outline contains %d nodes" % len(nodes))

@nocolor
Here is one way to count the nodes of an outline:
@color

    count = 0
    for p in c.allNodes_iter():
        count += 1
    g.es("This outline contains %d nodes" % count)

@nocolor
Here is a way to count the *distinct* vnodes of an outline:
@color

    positions = 0 ; tnodes = {}
    for p in c.allNodes_iter():
        positions += 1
        if not tnodes.get(p.v.t):
            tnodes[p.v.t] = p.v.t
    g.es("%8s positions" % positions)
    g.es("%8s vnodes" % len(tnodes.keys()))</t>
<t tx="ekr.20060902092341.11">@nocolor
The p.children_iter iterator returns a list of all children of position p:
@color

    parent = p.parent()
    g.es("children of %s" % parent.headString(),color="purple")
    for p in parent.children_iter():
        g.es(p.headString())</t>
<t tx="ekr.20060902092341.12">@nocolor
The p.parents_iter iterator returns a list of all parents of position p, excluding p:
@color

    current = p.copy()
    g.es("inclusive parents of %s" % current.headString(),color="purple")
    for p in current.self_and_parents_iter():
        g.es(p.headString())

@nocolor
The p.self_and_parents_iter iterator returns a list of all parents of position p, including p:
@color

    current = p.copy()
    g.es("exclusive of %s" % current.headString(),color="purple")
    for p in current.parents_iter():
        g.es(p.headString())</t>
<t tx="ekr.20060902092341.13">@nocolor
The p.siblings_iter iterator returns a list of all siblings of position p:
@color

    current = c.currentPosition()
    g.es("all siblings of %s" % current.headString(),color="purple")
    for p in current.self_and_siblings_iter():
        g.es(p.headString())

@nocolor
The p.following_siblings_iter iterator returns a list of all siblings that follow position p:
@color

    current = c.currentPosition()
    g.es("following siblings of %s" % current.headString(),color="purple")
    for p in current.following_siblings_iter():
        g.es(p.headString())</t>
<t tx="ekr.20060902092341.14">@nocolor
The p.subtree_iter iterator returns a list of all positions in p's subtree, excluding p:
@color

    parent = p.parent()
    g.es("inclusive subtree of %s" % parent.headString(),color="purple")
    for p in parent.self_and_subtree_iter():
        g.es(p.headString())

@nocolor
The p.self_and_subtree_iter iterator returns a list of all positions in p's subtree, including p:
@color

    parent = p.parent()
    g.es("exclusive subtree of %s" % parent.headString(),color="purple")
    for p in parent.subtree_iter():
        g.es(p.headString())</t>
<t tx="ekr.20060902092341.15">@nocolor
The tests:
@color

    if p:       # Right
    if not p:   # Right

@nocolor
are the **only** correct ways to test whether a position p is valid.
In particular, the following **will not work**:
@color

    if p is None:       # Wrong
    if p is not None:   # Wrong</t>
<t tx="ekr.20060902092341.16">@nocolor
You can use c.redraw_now to redraw the entire screen immediately:
@color

    c.redraw_now()

@nocolor
However, Leo's code redraws the screen using the following pattern:
@color
    
    c.beginUpdate()
    try:
        &lt;&lt; whatever &gt;&gt;
    finally:
        c.endUpdate()

@nocolor
This suppresses redraws inside &lt;&lt;whatever&gt;&gt; that would otherwise be caused by
c.endUpdate. c.endUpdate takes an optional argument:
@color

    c.endUpdate(flag)

@nocolor
redraws the screen only if flag is True. This is an important pattern. Leo uses
c.beginUpdate and c.endUpdate almost everywhere to redraw the screen, so
provided that &lt;&lt; whatever &gt;&gt; contains no calls to c.redraw_now this pattern
insures that at most one redraw occurs.</t>
<t tx="ekr.20060902092341.17">@nocolor
Leo dispatches commands using c.doCommand,
which calls the "command1" and "command2" hook routines for the given label.
c.doCommand catches all exceptions thrown by the command:
@color

    c.doCommand(c.markHeadline,label="markheadline")

@nocolor
You can also call command handlers directly so that hooks will not be called:
@color

    c.markHeadline()

@nocolor
You can invoke minibuffer commands by name.  For example:
@color

    c.executeMinibufferCommand('open-outline')

@nocolor
c.keyHandler.funcReturn contains the value returned from the command.
In many cases, as above, this value is simply 'break'.</t>
<t tx="ekr.20060902092341.18">@nocolor
Any .leo file may contain an @settings tree, so settings may be different for each commander.
Plugins and other scripts can get the value of settings as follows:
@color

    format_headlines = c.config.getBool('rst3_format_headlines')
    g.es('format_headlines',format_headlines)

@nocolor
The c.config class has the following getters.
See the configSettings in leoCommands.py for details:

    getBool
    getColor
    getDirectory
    getFloat
    getInt
    getLanguage
    getRatio
    getShortcut
    getString

You can set any *existing* item in an @settings tree with c.config.set(p,setting,val).
For example:
@color

    for val in (False,True):
        c.config.set(p,'rst3_format_headlines',val)
        format_headlines = c.config.getBool('rst3_format_headlines')
        g.es('format_headlines',format_headlines)

@nocolor
c.config.set does not change the @settings tree; it simply changes the values returned by the getters.</t>
<t tx="ekr.20060902092341.19">@nocolor
Each commander maintains its own preferences.
Your scripts can get the following ivars:
@color

    ivars = (
        'output_doc_flag',
        'page_width',
        'page_width',
        'tab_width',
        'tangle_batch_flag',
        'tangle_directory',
        'target_language',
        'untangle_batch_flag',
        'use_header_flag',
    )
    
    g.es("Prefs ivars...\n",color="purple")
    for ivar in ivars:
        g.es(getattr(c,ivar))

@nocolor
If your script sets c.tab_width your script may call f.setTabWidth to redraw the screen:
@color

    c.tab_width = -4    # Change this and see what happens.
    c.frame.setTabWidth(c.tab_width)</t>
<t tx="ekr.20060902092341.20">@nocolor
The file leoFindScript.py contains functions for finding and changing text
from within scripts.  See leoFindScript.py in LeoPy.leo for full details.

The findall function returns a list of tuples (v,pos) describing matches in
c's entire tree:
@color

    import leoFindScript

    pattern="import leoGlobals as g"
    result = leoFindScript.findAll(c,pattern,bodyFlag=1)
    
    g.es("%-3d instances of: '%s'...\n" % (len(result),pattern),color="purple")
    
    for v,pos in result:
        body = v.bodyString()
        g.es('\n%-4d %s' % (pos,v.headString()))
        g.es(g.get_line_after(body,pos))

@nocolor
The reFindall function returns a list of tuples (v,mo,pos), where mo
is a MatchObject. The reFlags argument are flags to re.search:
@color

    import leoFindScript

    pattern="from .* import"
    result = leoFindScript.reFindAll(c,pattern,bodyFlag=1,reFlags=None)

    g.es("%-3d instances of: '%s'...\n" % (len(result),pattern),color="purple")
    for v,mo,pos in result:
        body = v.bodyString()
        g.es('\n%-4d %s' % (pos,v.headString()))
        g.es(g.get_line_after(body,pos))</t>
<t tx="ekr.20060902092341.21">@nocolor
On startup, Leo looks for two arguments of the form:

    --script scriptFile

If found, Leo enters batch mode. In batch mode Leo does not show any windows.
Leo assumes the scriptFile contains a Python script and executes the contents of
that file using Leo's Execute Script command. By default, Leo sends all
output to the console window. Scripts in the scriptFile may disable or enable
this output by calling app.log.disable or app.log.enable

Scripts in the scriptFile may execute any of Leo's commands except the Edit Body
and Edit Headline commands. Those commands require interaction with the user.
For example, the following batch script reads a Leo file and prints all the
headlines in that file:
@color

    path = r"c:\prog\leoCVS\leo\test\test.leo"
   
    g.app.log.disable() # disable reading messages while opening the file
    flag,newFrame = g.openWithFileName(path,None)
    g.app.log.enable() # re-enable the log.
    
    for p in newFrame.c.allNodes_iter():
        g.es(g.toEncodedString(p.headString(),"utf-8"))</t>
<t tx="ekr.20060902092341.22">@nocolor
leoGlobals.py contains many utility functions and constants.
The following script prints all the names defined in leoGlobals.py:
@color

    g.es("Names defined in leoGlobals.py",color="purple")
    names = g.__dict__.keys()
    names.sort()
    for name in names:
        g.es(name)</t>
<t tx="ekr.20060902092341.23">@nocolor
leoGlobals.py defines 6 convenience methods for redirecting stdout and stderr:
@color

    g.redirectStderr() # Redirect stderr to the current log pane.
    g.redirectStdout() # Redirect stdout to the current log pane.
    g.restoreStderr()  # Restores stderr so it prints to the console window.
    g.restoreStdout()  # Restores stdout so it prints to the console window.
    g.stdErrIsRedirected() # Returns True if the stderr stream is redirected to the log pane.
    g.stdOutIsRedirected() # Returns True if the stdout stream is redirected to the log pane.

@nocolor
Calls need *not* be paired. Redundant calls are ignored and the last call made
controls where output for each stream goes.
**Note**: you must execute Leo in a console window to see non-redirected output from the print statement:
@color

    print "stdout isRedirected:", g.stdOutIsRedirected()
    print "stderr isRedirected:", g.stdErrIsRedirected()

    g.redirectStderr()
    print "stdout isRedirected:", g.stdOutIsRedirected()
    print "stderr isRedirected:", g.stdErrIsRedirected()

    g.redirectStdout()
    print "stdout isRedirected:", g.stdOutIsRedirected()
    print "stderr isRedirected:", g.stdErrIsRedirected()

    g.restoreStderr()
    print "stdout isRedirected:", g.stdOutIsRedirected()
    print "stderr isRedirected:", g.stdErrIsRedirected()

    g.restoreStdout()
    print "stdout isRedirected:", g.stdOutIsRedirected()
    print "stderr isRedirected:", g.stdErrIsRedirected()</t>
<t tx="ekr.20060902092341.24">@nocolor
**New in Leo 4.4a2**: Plugins and scripts can create new tabs in the log panel.
The following creates a tab named test or make it visible if it already exists:
@color
 
    c.frame.log.selectTab('Test')

@nocolor
When first created, a tab contains a text widget.
The c.frame.log class contains the following 'official' ivars:

- c.frame.log.tabName is the name of the active tab.
- c.frame.log.tabFrame is the Tk.Frame containing all the other widgets of the tab.
- c.frame.log.logCtrl is the initial Tk.Text widget.

The following line removes the initial text widget:
@color
    
    c.frame.log.logCtrl.pack_forget()

@nocolor
To make the text widget visible again:
@color

    c.frame.log.logCtrl.pack(side='top',expand=1,fill='both')

@nocolor
Plugins and scripts can pack any other widgets into c.frame.log.tabFrame.
For example, the following replaces the default text widget with a red box:
@color

    import Tkinter as Tk ; log = c.frame.log
    log.selectTab('Test')
    log.logCtrl.pack_forget()
    f = Tk.Frame(log.tabFrame,bg='red',height='1inch',width='2inch')
    f.pack(side='left',expand=0,fill='none')

@nocolor
Notes:

- g.es, g.enl, g.ecnl, g.ecnls write to the log tab specified by the optional
  tabName argument. The default for tabName is 'Log', so existing code works as
  before.

- The put and putnl methods of the tkinterLog class also take an optional
  tabName argument which defaults to 'Log'.</t>
<t tx="ekr.20060902092341.25">Most scripts will use methods of the position class to access information in an
outline. The following sections summarizes the most useful methods that your
scripts can use. For a complete list, see the leoNodes.py in of LeoPy.leo.</t>
<t tx="ekr.20060902092341.26">@nocolor
Iterators exist only in the position class:
@color

	c.allNodes_iter            # returns all positions in c's outline.
	p.children_iter            # returns all children of p.
	p.parents_iter             # returns all parents of p.
	p.self_and_parents_iter    # returns p and all parents of p.
	p.siblings_iter            # returns all siblings of p, including p.
	p.following_siblings_iter  # returns all siblings following p.
	p.subtree_iter             # returns all positions in p's subtree, excluding p.
	p.self_and_subtree_iter    # returns all positions in p's subtree, including p.</t>
<t tx="ekr.20060902092341.27">@nocolor
p.c is an 'official' ivar of the position class.  p.c is p's commander.

Here are the most useful getters of the vnode and position classes.
    
Returning strings:
@color

    p.bodyString() # the body string of p.
    p.headString() # the headline string of p.
    
@nocolor
Returning ints:
@color

    p.childIndex()
    p.numberOfChildren()
    p.level()
   
@nocolor 
Returning bools representing property bits:
@color

    p.hasChildren()
    p.isAncestorOf(v2) # True if v2 is a child, grandchild, etc. of p.
    p.isCloned()
    p.isDirty()
    p.isExpanded()
    p.isMarked()
    p.isVisible()
    p.isVisited()</t>
<t tx="ekr.20060902092341.28">@nocolor
Here are the most useful setters of the Commands and position classes.
The following setters of the position class regardless of whether
p is the presently selected position:
@color

    p.setBodyString(s)  # Sets the body text of p.
    p.setHeadStringOrHeadline(s)  # Sets the headline text of p.

@nocolor
Moving nodes:
@color

    p.moveAfter(v2)           # move p after v2
    p.moveToNthChildOf(v2,n)  # move p to the n'th child of v2
    p.moveToRoot(oldRoot)     # make p the root position.
                              # oldRoot must be the old root position if it exists.
                              
@nocolor
The "visited" bit may be used by commands or scripts for any purpose.
Many commands use this bits for tree traversal, so these bits do not persist:
@color

    c.clearAllVisited() # Clears all visited bits in c's tree.
    p.clearVisited()
    p.setVisited()</t>
<t tx="ekr.20060902092341.29">@nocolor
Creating a script button should be your first thought whenever you want to
automate any task. The scripting plugin, mod_scripting.py, puts two buttons
in the icon menu, a pink Run Script button and a yellow Script Button
button. The Run Script button does the same thing as the Execute Script
command. The Script Button button is the interesting one. It creates a
button, confusingly called a **script button** in the icon area. A script button
executes a script when you push it.

Suppose node N is selected. When you press the Script Button button a new
(pink) script button is created. The name of the new button is N's headline
text. The script associated with the new button is N's body text. Now whenever
you press the new button, N's script is executed on the **presently** selected
node. Script buttons are extraordinarily useful. In effect, each script button
defines an instant command! For example, sometimes my fingers get tired of
saving a file. I simply put Save in a node's headline and c.save() in
the body text. I hit the Script Button button and I get a new button called
Save that will save the outline when I press it.

Here's a more interesting example. The following script searches the present node
and its ancestors looking for an @rst node. When such a node is found the
script calls the `rst3 plugin`_ to format it. I don't have to select the actual
@rst node; I can select any of its children:
@color

    import leoPlugins
    rst3 = leoPlugins.getPluginModule('rst3')
    if rst3: # already loaded.
        controller = rst3.controllers.get(c)
        if controller:
            for p in p.self_and_parents_iter():
                if p.headString().startswith('@rst '):
                    controller.processTree(p)
                    break
    else: # Just load the plugin.
        rst3 = leoPlugins.loadOnePlugin('rst3',verbose=True)
        if rst3:
            g.es('rst3 loaded')
            rst3.onCreate('tag',{'c':c})
        else:
            # Ask to be removed.
            g.app.scriptDict['removeMe'] = True

@nocolor
**Notes**:

-   The scripting plugin pre-defines the c, g and p symbols
    just as the Execute Script command does.

-   By default a script button executes the **present** body text of the node that original created the script button.
    This is very handy: you can modify a script button's script at any time without having to recreate the script button.

-   You can delete any script button by right-clicking on it.

-   On startup, the scripting plugin scans the entire .leo file and creates a script button
    for every node whose headline starts with @button scriptName.
    **Warning**: this is indeed a security risk of the kind discussed later.
    This feature can be disabled by setting atButtonNodes = True at the start of mod_scripting.py.</t>
<t tx="ekr.20060902092341.30">@test and @suite nodes are a major advance in unit testing. Such nodes
have headlines that start with @test or @suite. The file test.leo
contains many examples of @test and @suite nodes. @test and
@suite nodes are a direct outgrowth of script buttons. The unit test
script button in test.leo scans the selected outline, creating one unit test
for each test node and zero or more unit tests for each @suite node. The
unit test script then runs all the selected unit tests.</t>
<t tx="ekr.20060902095933">@nocolor
@test nodes create a single unit test from the script in its body
**without having to create a subclass of unittest.TestCase**.
For example, here is a complete unit test.  The headline is:
@color

    @test p.t == p.v.t

@nocolor
The body text is:
@color

    # NOTE: p.__getattr__ must be enabled for this test to work.
    root = c.rootPosition()
    for p in root.allNodes_iter():
        assert(p.t == p.v.t)
        
@nocolor
**That's all!** The headline marks the node as containing a unit test.
The body text contains the meat of the test.  No cruft at all!

**Notes**: The unit tests created from @test nodes define setUp and
tearDown methods. These methods ensure that the script being executed is
the presently selected node. The scripts in @test nodes can not override
the setUp and tearDown methods. In practice, this is not a problem
because the scripts in @test nodes are typically very simple. Such
scripts can use try/finally if they need to clean up after themselves.
Scripts in @test nodes often assume that descendant nodes hold test
data. Scripts in @test nodes can generally define and use sections, but
scripts may not use the @others directive if descendant nodes hold
data.
</t>
<t tx="ekr.20060902095933.1">@nocolor
@suite are an easy way to run legacy unit tests. The Unit Test
button assumes that the body text of an @suite node is a script that
creates a test suite and leaves the result in g.app.scriptDict['suite'].
test.leo several examples of @suite nodes.
Here is an @suite node that executes all doctests in Leo's sources.
The headline is:
@color

    @suite run all doctests

The body text is:
@color

    import unittest
    import leoTest
    import sys
    
    # DocTestSuite exists in Python 2.3 and above.
    if g.CheckVersion(sys.version, "2.3"):
        path = g.os_path_join(g.app.loadDir,"..","src")
        modules = leoTest.importAllModulesInPath(path)
        suite = leoTest.createUnitTestsFromDoctests(modules)                     
        if suite:
            g.app.scriptDict['suite'] = suite
    else:
        # Create an empty suite to suppress a warning.
        g.app.scriptDict['suite'] = unittest.TestSuite()
        print "Can't create unit tests from doctests"
        print "doctest.DocTestSuite requires Python 2.3 or above."

@nocolor
The real work of creating the test suites is done by
leoTest.createUnitTestsFromDoctests.

**Important**: if the suite was created successfully, the script must pass the suite
to script in the unit test script button by as follows:
@color

    g.app.scriptDict['suite'] = suite

@nocolor
@button unit test
The script in the Unit Test script button in test.leo is just:
@color

    import leoTest
    leoTest.doTests(all=False)

@nocolor
test.leo defines the leoTest module. The doTests function is the
code that supports @test and @suite nodes. **Important**: you could
customize how @test and @suite nodes work by using your own script
in the @button unit test node.</t>
<t tx="ekr.20060902100250">This is the end of the 'Scripting Leo' slide show.</t>
<t tx="ekr.20060902100840">This would colorize only code blocks (as Python code).</t>
<t tx="ekr.20060902101656"># @language rst-python
@language python</t>
<t tx="ekr.20060904104955"></t>
<t tx="ekr.20060904104955.1"></t>
<t tx="ekr.20060904104955.2"></t>
<t tx="ekr.20070315073704"></t>
<t tx="ekr.20070315073704.1">plugins_menu.py
plugin_manager.py
open_with.py
mod_scripting.py
rst3.py
slideshow.py
UNL.py
nav_buttons.py</t>
<t tx="ekr.20070315073704.2">For MacOS X (darwin) the following are typical defaults:

vim_cmd = /Applications/gvim.app/Contents/MacOS/gvim --servername LEO
vim_exe = /Applications/gvim.app/Contents/MacOS/gvim
</t>
<t tx="ekr.20070315073704.3"></t>
<t tx="ekr.20070315073704.4"></t>
<t tx="ekr.20070315074504"># The children of this node can be made into slides using the make-slide button or make-slide command.</t>
<t tx="ekr.20070315074504.1"></t>
<t tx="ekr.20070315074504.2"></t>
<t tx="ekr.20080129151123"></t>
<t tx="ekr.20080129151228"></t>
</tnodes>
</leo_file>
