comparison python/tree.py @ 391:cccfe246452e

rename
author Jeff Hammel <jhammel@mozilla.com>
date Sat, 27 Jul 2013 20:33:53 -0700
parents python/tree2.py@9d02187611ae
children 5417eb6364ee
comparison
equal deleted inserted replaced
390:9d02187611ae 391:cccfe246452e
7 7
8 import optparse 8 import optparse
9 import os 9 import os
10 import sys 10 import sys
11 11
12 here = os.path.dirname(os.path.realpath(__file__)) 12 # ASCII delimeters
13 ascii_delimeters = {
14 'vertical_line' : '|',
15 'item_marker' : '+',
16 'last_child' : '\\'
17 }
18
19 # unicode delimiters
20 unicode_delimeters = {
21 'vertical_line' : '│',
22 'item_marker' : '├',
23 'last_child' : '└'
24 }
13 25
14 def depth(directory): 26 def depth(directory):
27 """returns the integer depth of a directory or path relative to '/' """
28
15 directory = os.path.abspath(directory) 29 directory = os.path.abspath(directory)
16 level = 0 30 level = 0
17 while True: 31 while True:
18 directory, remainder = os.path.split(directory) 32 directory, remainder = os.path.split(directory)
19 level += 1 33 level += 1
20 if not remainder: 34 if not remainder:
21 break 35 break
22 return level 36 return level
23 37
24 def tree(directory): 38 def tree(directory,
39 item_marker=unicode_delimeters['item_marker'],
40 vertical_line=unicode_delimeters['vertical_line'],
41 last_child=unicode_delimeters['last_child'],
42 sort_key=lambda x: x.lower()):
43 """
44 display tree directory structure for `directory`
45 """
46
25 retval = [] 47 retval = []
26 level = depth(directory) 48 indent = []
27 pre = []
28 directories = {}
29 lvlndctr = []
30 last = {} 49 last = {}
31 passed_last = {} 50 top = depth(directory)
32 columns = [] 51
33 lastdepth = depth
34 indent = 0
35 for dirpath, dirnames, filenames in os.walk(directory, topdown=True): 52 for dirpath, dirnames, filenames in os.walk(directory, topdown=True):
36 basename = os.path.basename(dirpath)
37 parent = os.path.abspath(os.path.dirname(dirpath))
38 indent = depth(dirpath) - level
39 dirnames[:] = sorted(dirnames, key=lambda x: x.lower())
40 last[os.path.abspath(dirpath)] = dirnames and dirnames[-1] or None
41 directories[dirpath] = dirnames
42 53
43 retval.append('%s%s%s' % ('│' * (indent-1), 54 abspath = os.path.abspath(dirpath)
44 ('├' if basename == basename else '└') if indent else '', 55 basename = os.path.basename(abspath)
45 basename)) 56 parent = os.path.dirname(abspath)
46 filenames = sorted(filenames, key=lambda x: x.lower()) 57 level = depth(abspath) - top
47 retval.extend(['%s%s%s' % ('│' * (indent), 58
48 '├' if (((index < len(filenames) -1)) or dirnames) else '└', 59 # sort articles of interest
49 name) 60 for resource in (dirnames, filenames):
50 for index, name in 61 resource[:] = sorted(resource, key=sort_key)
51 enumerate(filenames) 62
52 ]) 63 files_end = item_marker
64 dirpath_marker = item_marker
65
66 if level > len(indent):
67 indent.append(vertical_line)
68 indent = indent[:level]
69
70 if dirnames:
71 files_end = item_marker
72 last[abspath] = dirnames[-1]
73 else:
74 files_end = last_child
75
76 if last.get(parent) == os.path.basename(abspath):
77 # last directory of parent
78 dirpath_mark = last_child
79 indent[-1] = ' '
80 elif not indent:
81 dirpath_mark = ''
82 else:
83 dirpath_mark = item_marker
84
85 # append the directory and piece of tree structure
86 # if the top-level entry directory, print as passed
87 retval.append('%s%s%s'% (''.join(indent[:-1]),
88 dirpath_mark,
89 basename if retval else directory))
90 # add the files
91 if filenames:
92 last_file = filenames[-1]
93 retval.extend([('%s%s%s' % (''.join(indent),
94 files_end if filename == last_file else item_marker,
95 filename))
96 for index, filename in enumerate(filenames)])
97
53 return '\n'.join(retval) 98 return '\n'.join(retval)
54 99
55 def main(args=sys.argv[1:]): 100 def main(args=sys.argv[1:]):
56 101
102 # parse command line options
57 usage = '%prog [options]' 103 usage = '%prog [options]'
58 parser = optparse.OptionParser(usage=usage, description=__doc__) 104 parser = optparse.OptionParser(usage=usage, description=__doc__)
105 parser.add_option('-a', '--ascii', dest='use_ascii',
106 action='store_true', default=False,
107 help="use ascii delimeters (%s)" % ascii_delimeters)
59 options, args = parser.parse_args(args) 108 options, args = parser.parse_args(args)
60 if not args: 109 if not args:
61 args = ['.'] 110 args = ['.']
62 111
112 # sanity check
63 not_directory = [arg for arg in args 113 not_directory = [arg for arg in args
64 if not os.path.isdir(arg)] 114 if not os.path.isdir(arg)]
65 if not_directory: 115 if not_directory:
66 parser.error("Not a directory: %s" % (', '.join(not_directory))) 116 parser.error("Not a directory: %s" % (', '.join(not_directory)))
67 117
118 delimeters = unicode_delimeters
119 if options.use_ascii:
120 delimeters = ascii_delimeters
121
122 # print the tree
68 for arg in args: 123 for arg in args:
69 print (tree(arg)) 124 print (tree(arg, **delimeters))
70 125
71 if __name__ == '__main__': 126 if __name__ == '__main__':
72 main() 127 main()