On Sat, Mar 29, 2008 at 3:22 AM, zpcspm <[EMAIL PROTECTED]> wrote:

So my question is: is it possible to get the clean derived files
> without having to convert manually each @file node in the outline to a
> @nosent node? The reason for this is that I can have hundreds of
> derived files and I might need clean snapshots often.


The answer must be 'yes', because Leo is highly scriptable.  Let's see how
to do this.  I'll write the script in easy steps, so this should be a good
example.

1. Run Leo from the console.  I like to run Leo from a console at all times,
so I can see the output of print statements.

2. Create an @button node in your outline.

The headline is @button write-cleaned-files.  The body text will contain the
script.  While testing, I'll execute the script with control-b (Leo's
execute-script command).  We can also execute the script by hitting the
yellow 'script-button' button in the icon bar.  This will create a new
script button called write-cleaned-file (the title gets truncated).
Creating a script button also creates a corresponding command, which we can
execute with <alt-x>write-cleaned-files<return> or more easily, using tab
completion, <alt-x>write-cl<tab><return>

BTW, when you reload the outline later, Leo will create a write-cleaned-file
button automatically.

2. Turn on autocompletion and calltips.

Type Alt-1 and Alt-2.  This saves typing and can be useful to see what
methods exists.

3.  Put the following script in the body pane of the @button node:

@others

for p in c.allNodes_iter():
    if p.isAnyAtFileNode():
        print p.headString()

With autocompletion on, you will actually only have to type:

for p in c.allN():
    if p.isA():
        print p.he():

Run this script by typing control-b, or by executing the script button as
discussed above.  You will see a list of all the @thin, @auto, @file, etc
nodes in the outline.

4. Create a helper function, called clean_node, in a child node.

The headline will be clean_file, and the body text will contain the
function.

For now, but the following in body:

def clean_file(p):
    g.trace(p)

In order for the script to access this function, add the @others directive
to the @button node.  We'll also call clean_node, so the body of the @button
node will be:

@others

for p in c.allNodes_iter():
    if p.isAnyAtFileNode():
        clean_file(p):

Now comes the interesting part.  We want to use Leo's write code in
leoAtFile.py to write the derived file, but we want to modify that code in
two ways: we want to disable writing of sentinels, and we want write the
cleaned file to a 'cleaned' directory.

The leoAtFile.write method, in leoPy.leo in the node

Code-->Core classes...-->@thin leoAtFile.py-->Writing...-->Writing (top
level)-->Don't override in plugins-->write

is the general-purpose method that writes (most) derived files.

In the body of the clean_file, type:

c.atFileCommands.write(

(because of autocompletion, you actually won't have to type all this).  You
will see

c.atFileCommands.write(root, nosentinels=False, thinFile=False,
scriptWrite=False, toString=False, write_strips_blank_lines=None

Clear the selection, and add a closing ')'.

Looking at the source code, we see that the write method 'writes' the file
to the .stringOutput ivar.  So here is our preliminary code:

def clean_file(p):

    at = c.atFileCommands

    at.write(
        root=p,nosentinels=True,
        thinFile=False,
        scriptWrite=True,
        toString=True,
        write_strips_blank_lines=False)

    g.trace(p.headString(),len(at.stringOutput))

If we execute this script in test.leo, we get the following output:

clean_file: @thin gtkOutlineDemo.py 27847
clean_file: @file server.py 666
clean_file: @file hello.html 1098
clean_file: @file cgi-bin/edward.py 3089
clean_file: @thin cgi-bin/leo.js 3684
clean_file: @thin leoBridgeTest.py 1174
clean_file: @thin leoDynamicTest.py 991

We still must write the result.  We use p.anyAtFileNodeName() to get the
'raw' file name.  We can use the .default_directory ivar (inited by at.write)
to get the proper directory.  This directory is set by at.scanAllDirectives,
so @path and other details are handled properly.

So we add the following lines:

    fileName = g.os_path_normpath(
        g.os_path_join(
            at.default_directory,'clean',p.anyAtFileNodeName()))

    g.trace(p.headString(),len(at.stringOutput),fileName)

The output of executing the script is now:

clean_file: @thin gtkOutlineDemo.py 27847
C:\leo.repo\leo-editor\trunk\leo\test\clean\gtkOutlineDemo.py
clean_file: @file server.py 666
C:\leo.repo\leo-editor\trunk\leo\test\clean\server.py
clean_file: @file hello.html 1098
C:\leo.repo\leo-editor\trunk\leo\test\clean\hello.html
clean_file: @file cgi-bin/edward.py 3089
C:\leo.repo\leo-editor\trunk\leo\test\clean\cgi-bin\edward.py
clean_file: @thin cgi-bin/leo.js 3684
C:\leo.repo\leo-editor\trunk\leo\test\clean\cgi-bin\leo.js
clean_file: @thin leoBridgeTest.py 1174
C:\leo.repo\leo-editor\trunk\leo\test\clean\leoBridgeTest.py
clean_file: @thin leoDynamicTest.py 991
C:\leo.repo\leo-editor\trunk\leo\test\clean\leoDynamicTest.py

So the last piece of the puzzle is to actually write at.stringOutput to
fileName.

BTW, I never remember the names of ivars, or indeed much of anything except
the highest-level details.  I found the name of the .default_directory ivar
from the at.openFileForWritingHelper.

Looking at at.openFileForWritingHelper, we see that it has code to create
the 'clean' directory if it does not exist.  We could duplicate that code in
our script, or simply issue an error message if the directory does not
exist.

Let's assume that the 'clean' directory does exist, and issue an error
otherwise.  So the final version of clean_file is:

def clean_file(p):

    at = c.atFileCommands

    at.write(
        root=p,nosentinels=True,
        thinFile=False,
        scriptWrite=True,
        toString=True,
        write_strips_blank_lines=False)

    fileName = g.os_path_normpath(
        g.os_path_join(
            at.default_directory,'clean',p.anyAtFileNodeName()))

    # g.trace(p.headString(),len(at.stringOutput),fileName)

    # Adapted from at.openFileForWritingHelper
    path = g.os_path_dirname(fileName)
    if not g.os_path_exists(path):
        g.es('clean directory does not exist',path)
        return
    try:
        f = file(fileName,'w')
        f.write(at.stringOutput)
        f.close()
        g.es_print('wrote',fileName)
    except IOError:
        g.es_print('can not write',fileName,color='red')
        g.es_exception()

So that was pretty easy :-)  I'll push test.leo containing this script to
the trunk shortly.

HTH.

Edward

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/leo-editor?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to