A more general version of this script is available here: http://leo.zwiki.org/LeoDirectory

To create @shadow nodes, a typical workflow is to do an @file import for each file, and then manually convert the headline to an @shadow node.

This can be improved somewhat by bypassing imports completely and just entering the @shadow headlines directly, and then restarting leo to find them (hopefully) properly imported/structured.

This is still fairly laborious for a small project. For a large one with many files and subfolders it can become very tedious, and the process naturally lends itself to automation.

To this end, this script attempts to provide that convenience. It basically looks at the current directory and recursively creates @shadow nodes (or any other kind of @node) for files and @path nodes for subdirectories. It also includes facilities to specify file or directory patterns to ignore and also to determine whether @path nodes contain absolute or relative references.

To use it, copy the code below into an @button node with an appropriate name ('create_shadows' is nice :-), select the target node and enjoy:

from os import listdir
from os.path import join, abspath, basename, normpath, isfile
from fnmatch import fnmatch

RELATIVE_PATHS = True

patterns_to_ignore = ['*.pyc', '*.leo', '*.gif', '*.png', '*.jpg', '*.json', '*.svg']

match = lambda s: any(fnmatch(s, p) for p in patterns_to_ignore)

is_ignorable = lambda s: any([ s.startswith('.'), match(s) ])

def shadow_walk(directory, parent=None, isroot=True):
    if not RELATIVE_PATHS: directory = abspath(directory)
    if isroot:
        body = "@path %s" % normpath(directory)
        c.setBodyString(p, body)
    for name in listdir(directory):
        if is_ignorable(name):
            continue
        path = join(directory, name)
        if isfile(path):
            g.es('file:', path)
            headline = '@shadow %s' % basename(path)
            if parent:
                node = parent
            else:
                node = p
            child = node.insertAsLastChild()
            child.initHeadString(headline)
        else:
            g.es('dir:', path)
            headline = basename(path)
            body = "@path %s" % name
            if parent:
                node = parent
            else:
                node = p
            child = node.insertAsLastChild()
            child.initHeadString(headline)
            child.initBodyString(body)
            shadow_walk(path, parent=child, isroot=False)

def main():
    try:
        shadow_walk('.')
    finally:
        c.redraw()

main()

After running this script, you will find your directory structure populated with .leo_shadow folders. As you adjust the parameters of the above script to refine the outcome, you may want to restart the whole process afresh as doing otherwise can lead to errors. In this case, create another @button called 'remove_shadows' to recursively remove older .leo_shadow folders. If you are working in linux, unix, or mac os x, it can probably look something like this:

import os
os.system('rm -rf `find . -type d -name .leo_shadow`')

Hopefully, these shortcuts should save you some time and also give you a small demonstration of the power and flexibility of leo.

AliaKhouri?

Sorted child nodes --thyrsus, Fri, 31 Oct 2008 10:27:12 -0700 reply

I like my nodes sorted, to I've added the following to my use of the above:

@@ -15,7 +15,9 @@
     if isroot:
         body = "@path %s" % normpath(directory)
         c.setBodyString(p, body)
-    for name in listdir(directory):
+    t = listdir(directory)
+    t.sort()
+    for name in t:
         if is_ignorable(name):
             continue
         path = join(directory, name)