Mercurial > hg > config
annotate python/tree2.py @ 388:3678770e8c52
changes
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Sat, 27 Jul 2013 18:45:43 -0700 |
parents | 0aee0da6b06b |
children | 2d4dfe1dc632 |
rev | line source |
---|---|
382 | 1 #!/usr/bin/env python |
2 # -*- coding: utf-8 -*- | |
3 | |
4 """ | |
5 tree in python | |
6 """ | |
7 | |
8 import optparse | |
9 import os | |
10 import sys | |
11 | |
387 | 12 # ASCII delimeters |
388 | 13 ascii_delimeters = { |
14 VERTICAL_LINE = '|' | |
15 ITEM = '+' | |
16 END = '\\' | |
17 } | |
387 | 18 |
19 # unicode delimiters | |
20 VERTICAL_LINE = '│' | |
385 | 21 ITEM = '├' |
22 END = '└' | |
382 | 23 |
24 def depth(directory): | |
387 | 25 """returns the integer depth of a directory or path relative to '/' """ |
26 | |
382 | 27 directory = os.path.abspath(directory) |
28 level = 0 | |
29 while True: | |
30 directory, remainder = os.path.split(directory) | |
31 level += 1 | |
32 if not remainder: | |
33 break | |
34 return level | |
35 | |
388 | 36 def tree(directory, |
37 item_marker='', | |
38 sort_key=lambda x: x.lower()): | |
39 """ | |
40 display tree directory structure for `directory` | |
41 """ | |
383
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
42 |
385 | 43 retval = [] |
383
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
44 indent = [] |
384 | 45 last = {} |
386 | 46 top = depth(directory) |
47 | |
382 | 48 for dirpath, dirnames, filenames in os.walk(directory, topdown=True): |
383
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
49 |
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
50 abspath = os.path.abspath(dirpath) |
384 | 51 basename = os.path.basename(abspath) |
52 parent = os.path.dirname(abspath) | |
383
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
53 level = depth(abspath) - top |
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
54 |
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
55 # sort articles of interest |
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
56 for resource in (dirnames, filenames): |
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
57 resource[:] = sorted(resource, key=sort_key) |
382 | 58 |
385 | 59 files_end = ITEM |
60 dirpath_marker = ITEM | |
61 | |
62 if level > len(indent): | |
387 | 63 indent.append(VERTICAL_LINE) |
385 | 64 indent = indent[:level] |
65 | |
383
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
66 if dirnames: |
385 | 67 files_end = ITEM |
68 last[abspath] = dirnames[-1] | |
69 else: | |
70 files_end = END | |
384 | 71 |
385 | 72 if last.get(parent) == os.path.basename(abspath): |
73 # last directory of parent | |
74 dirpath_mark = END | |
75 indent[-1] = ' ' | |
76 elif not indent: | |
77 dirpath_mark = '' | |
78 else: | |
79 dirpath_mark = ITEM | |
80 | |
388 | 81 # append the directory and piece of tree structure |
82 # if the top-level entry directory, print as passed | |
83 retval.append('%s%s%s'% (''.join(indent[:-1]), | |
84 dirpath_mark, | |
85 basename if retval else directory)) | |
86 # add the files | |
385 | 87 if filenames: |
88 last_file = filenames[-1] | |
387 | 89 retval.extend([('%s%s%s' % (''.join(indent), |
385 | 90 files_end if filename == last_file else ITEM, |
91 filename)) | |
92 for index, filename in enumerate(filenames)]) | |
93 | |
382 | 94 return '\n'.join(retval) |
95 | |
96 def main(args=sys.argv[1:]): | |
97 | |
98 usage = '%prog [options]' | |
99 parser = optparse.OptionParser(usage=usage, description=__doc__) | |
100 options, args = parser.parse_args(args) | |
101 if not args: | |
102 args = ['.'] | |
103 | |
104 not_directory = [arg for arg in args | |
105 if not os.path.isdir(arg)] | |
106 if not_directory: | |
107 parser.error("Not a directory: %s" % (', '.join(not_directory))) | |
108 | |
109 for arg in args: | |
110 print (tree(arg)) | |
111 | |
112 if __name__ == '__main__': | |
113 main() |