# HG changeset patch # User Jeff Hammel # Date 1374982433 25200 # Node ID cccfe246452e57b75c6a5180a6589fb30bdd59d9 # Parent 9d02187611ae590702f06ac067d95fa1f0569087 rename diff -r 9d02187611ae -r cccfe246452e python/tree.py --- a/python/tree.py Sat Jul 27 20:09:49 2013 -0700 +++ b/python/tree.py Sat Jul 27 20:33:53 2013 -0700 @@ -9,9 +9,23 @@ import os import sys -here = os.path.dirname(os.path.realpath(__file__)) +# ASCII delimeters +ascii_delimeters = { + 'vertical_line' : '|', + 'item_marker' : '+', + 'last_child' : '\\' + } + +# unicode delimiters +unicode_delimeters = { + 'vertical_line' : '│', + 'item_marker' : '├', + 'last_child' : '└' + } def depth(directory): + """returns the integer depth of a directory or path relative to '/' """ + directory = os.path.abspath(directory) level = 0 while True: @@ -21,52 +35,93 @@ break return level -def tree(directory): +def tree(directory, + item_marker=unicode_delimeters['item_marker'], + vertical_line=unicode_delimeters['vertical_line'], + last_child=unicode_delimeters['last_child'], + sort_key=lambda x: x.lower()): + """ + display tree directory structure for `directory` + """ + retval = [] - level = depth(directory) - pre = [] - directories = {} - lvlndctr = [] + indent = [] last = {} - passed_last = {} - columns = [] - lastdepth = depth - indent = 0 + top = depth(directory) + for dirpath, dirnames, filenames in os.walk(directory, topdown=True): - basename = os.path.basename(dirpath) - parent = os.path.abspath(os.path.dirname(dirpath)) - indent = depth(dirpath) - level - dirnames[:] = sorted(dirnames, key=lambda x: x.lower()) - last[os.path.abspath(dirpath)] = dirnames and dirnames[-1] or None - directories[dirpath] = dirnames + + abspath = os.path.abspath(dirpath) + basename = os.path.basename(abspath) + parent = os.path.dirname(abspath) + level = depth(abspath) - top + + # sort articles of interest + for resource in (dirnames, filenames): + resource[:] = sorted(resource, key=sort_key) + + files_end = item_marker + dirpath_marker = item_marker + + if level > len(indent): + indent.append(vertical_line) + indent = indent[:level] + + if dirnames: + files_end = item_marker + last[abspath] = dirnames[-1] + else: + files_end = last_child - retval.append('%s%s%s' % ('│' * (indent-1), - ('├' if basename == basename else '└') if indent else '', - basename)) - filenames = sorted(filenames, key=lambda x: x.lower()) - retval.extend(['%s%s%s' % ('│' * (indent), - '├' if (((index < len(filenames) -1)) or dirnames) else '└', - name) - for index, name in - enumerate(filenames) - ]) + if last.get(parent) == os.path.basename(abspath): + # last directory of parent + dirpath_mark = last_child + indent[-1] = ' ' + elif not indent: + dirpath_mark = '' + else: + dirpath_mark = item_marker + + # append the directory and piece of tree structure + # if the top-level entry directory, print as passed + retval.append('%s%s%s'% (''.join(indent[:-1]), + dirpath_mark, + basename if retval else directory)) + # add the files + if filenames: + last_file = filenames[-1] + retval.extend([('%s%s%s' % (''.join(indent), + files_end if filename == last_file else item_marker, + filename)) + for index, filename in enumerate(filenames)]) + return '\n'.join(retval) def main(args=sys.argv[1:]): + # parse command line options usage = '%prog [options]' parser = optparse.OptionParser(usage=usage, description=__doc__) + parser.add_option('-a', '--ascii', dest='use_ascii', + action='store_true', default=False, + help="use ascii delimeters (%s)" % ascii_delimeters) options, args = parser.parse_args(args) if not args: args = ['.'] + # sanity check not_directory = [arg for arg in args if not os.path.isdir(arg)] if not_directory: parser.error("Not a directory: %s" % (', '.join(not_directory))) + delimeters = unicode_delimeters + if options.use_ascii: + delimeters = ascii_delimeters + + # print the tree for arg in args: - print (tree(arg)) + print (tree(arg, **delimeters)) if __name__ == '__main__': main() diff -r 9d02187611ae -r cccfe246452e python/tree2.py --- a/python/tree2.py Sat Jul 27 20:09:49 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -tree in python -""" - -import optparse -import os -import sys - -# ASCII delimeters -ascii_delimeters = { - 'vertical_line' : '|', - 'item_marker' : '+', - 'last_child' : '\\' - } - -# unicode delimiters -unicode_delimeters = { - 'vertical_line' : '│', - 'item_marker' : '├', - 'last_child' : '└' - } - -def depth(directory): - """returns the integer depth of a directory or path relative to '/' """ - - directory = os.path.abspath(directory) - level = 0 - while True: - directory, remainder = os.path.split(directory) - level += 1 - if not remainder: - break - return level - -def tree(directory, - item_marker=unicode_delimeters['item_marker'], - vertical_line=unicode_delimeters['vertical_line'], - last_child=unicode_delimeters['last_child'], - sort_key=lambda x: x.lower()): - """ - display tree directory structure for `directory` - """ - - retval = [] - indent = [] - last = {} - top = depth(directory) - - for dirpath, dirnames, filenames in os.walk(directory, topdown=True): - - abspath = os.path.abspath(dirpath) - basename = os.path.basename(abspath) - parent = os.path.dirname(abspath) - level = depth(abspath) - top - - # sort articles of interest - for resource in (dirnames, filenames): - resource[:] = sorted(resource, key=sort_key) - - files_end = item_marker - dirpath_marker = item_marker - - if level > len(indent): - indent.append(vertical_line) - indent = indent[:level] - - if dirnames: - files_end = item_marker - last[abspath] = dirnames[-1] - else: - files_end = last_child - - if last.get(parent) == os.path.basename(abspath): - # last directory of parent - dirpath_mark = last_child - indent[-1] = ' ' - elif not indent: - dirpath_mark = '' - else: - dirpath_mark = item_marker - - # append the directory and piece of tree structure - # if the top-level entry directory, print as passed - retval.append('%s%s%s'% (''.join(indent[:-1]), - dirpath_mark, - basename if retval else directory)) - # add the files - if filenames: - last_file = filenames[-1] - retval.extend([('%s%s%s' % (''.join(indent), - files_end if filename == last_file else item_marker, - filename)) - for index, filename in enumerate(filenames)]) - - return '\n'.join(retval) - -def main(args=sys.argv[1:]): - - # parse command line options - usage = '%prog [options]' - parser = optparse.OptionParser(usage=usage, description=__doc__) - parser.add_option('-a', '--ascii', dest='use_ascii', - action='store_true', default=False, - help="use ascii delimeters (%s)" % ascii_delimeters) - options, args = parser.parse_args(args) - if not args: - args = ['.'] - - # sanity check - not_directory = [arg for arg in args - if not os.path.isdir(arg)] - if not_directory: - parser.error("Not a directory: %s" % (', '.join(not_directory))) - - delimeters = unicode_delimeters - if options.use_ascii: - delimeters = ascii_delimeters - - # print the tree - for arg in args: - print (tree(arg, **delimeters)) - -if __name__ == '__main__': - main()