Mercurial > hg > config
annotate python/tree.py @ 392:1b6d7be776ca
add pushbug command
| author | Jeff Hammel <jhammel@mozilla.com> |
|---|---|
| date | Mon, 29 Jul 2013 13:44:05 -0700 (2013-07-29) |
| parents | cccfe246452e |
| children | 5417eb6364ee |
| 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 = { |
| 389 | 14 'vertical_line' : '|', |
| 15 'item_marker' : '+', | |
| 16 'last_child' : '\\' | |
| 388 | 17 } |
| 387 | 18 |
| 19 # unicode delimiters | |
| 389 | 20 unicode_delimeters = { |
| 21 'vertical_line' : '│', | |
| 22 'item_marker' : '├', | |
| 23 'last_child' : '└' | |
| 24 } | |
| 382 | 25 |
| 26 def depth(directory): | |
| 387 | 27 """returns the integer depth of a directory or path relative to '/' """ |
| 28 | |
| 382 | 29 directory = os.path.abspath(directory) |
| 30 level = 0 | |
| 31 while True: | |
| 32 directory, remainder = os.path.split(directory) | |
| 33 level += 1 | |
| 34 if not remainder: | |
| 35 break | |
| 36 return level | |
| 37 | |
| 388 | 38 def tree(directory, |
| 389 | 39 item_marker=unicode_delimeters['item_marker'], |
| 40 vertical_line=unicode_delimeters['vertical_line'], | |
| 41 last_child=unicode_delimeters['last_child'], | |
| 388 | 42 sort_key=lambda x: x.lower()): |
| 43 """ | |
| 44 display tree directory structure for `directory` | |
| 45 """ | |
|
383
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
46 |
| 385 | 47 retval = [] |
|
383
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
48 indent = [] |
| 384 | 49 last = {} |
| 386 | 50 top = depth(directory) |
| 51 | |
| 382 | 52 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
|
53 |
|
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
54 abspath = os.path.abspath(dirpath) |
| 384 | 55 basename = os.path.basename(abspath) |
| 56 parent = os.path.dirname(abspath) | |
|
383
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
57 level = depth(abspath) - top |
|
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
58 |
|
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
59 # sort articles of interest |
|
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
60 for resource in (dirnames, filenames): |
|
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
61 resource[:] = sorted(resource, key=sort_key) |
| 382 | 62 |
| 389 | 63 files_end = item_marker |
| 64 dirpath_marker = item_marker | |
| 385 | 65 |
| 66 if level > len(indent): | |
| 389 | 67 indent.append(vertical_line) |
| 385 | 68 indent = indent[:level] |
| 69 | |
|
383
8d1ad56761b0
this still, somehow, eludes my tired brain
Jeff Hammel <jhammel@mozilla.com>
parents:
382
diff
changeset
|
70 if dirnames: |
| 389 | 71 files_end = item_marker |
| 385 | 72 last[abspath] = dirnames[-1] |
| 73 else: | |
| 389 | 74 files_end = last_child |
| 384 | 75 |
| 385 | 76 if last.get(parent) == os.path.basename(abspath): |
| 77 # last directory of parent | |
| 389 | 78 dirpath_mark = last_child |
| 385 | 79 indent[-1] = ' ' |
| 80 elif not indent: | |
| 81 dirpath_mark = '' | |
| 82 else: | |
| 389 | 83 dirpath_mark = item_marker |
| 385 | 84 |
| 388 | 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 | |
| 385 | 91 if filenames: |
| 92 last_file = filenames[-1] | |
| 387 | 93 retval.extend([('%s%s%s' % (''.join(indent), |
| 389 | 94 files_end if filename == last_file else item_marker, |
| 385 | 95 filename)) |
| 96 for index, filename in enumerate(filenames)]) | |
| 97 | |
| 382 | 98 return '\n'.join(retval) |
| 99 | |
| 100 def main(args=sys.argv[1:]): | |
| 101 | |
|
390
9d02187611ae
make delimeters CLI switchable
Jeff Hammel <jhammel@mozilla.com>
parents:
389
diff
changeset
|
102 # parse command line options |
| 382 | 103 usage = '%prog [options]' |
| 104 parser = optparse.OptionParser(usage=usage, description=__doc__) | |
|
390
9d02187611ae
make delimeters CLI switchable
Jeff Hammel <jhammel@mozilla.com>
parents:
389
diff
changeset
|
105 parser.add_option('-a', '--ascii', dest='use_ascii', |
|
9d02187611ae
make delimeters CLI switchable
Jeff Hammel <jhammel@mozilla.com>
parents:
389
diff
changeset
|
106 action='store_true', default=False, |
|
9d02187611ae
make delimeters CLI switchable
Jeff Hammel <jhammel@mozilla.com>
parents:
389
diff
changeset
|
107 help="use ascii delimeters (%s)" % ascii_delimeters) |
| 382 | 108 options, args = parser.parse_args(args) |
| 109 if not args: | |
| 110 args = ['.'] | |
| 111 | |
|
390
9d02187611ae
make delimeters CLI switchable
Jeff Hammel <jhammel@mozilla.com>
parents:
389
diff
changeset
|
112 # sanity check |
| 382 | 113 not_directory = [arg for arg in args |
| 114 if not os.path.isdir(arg)] | |
| 115 if not_directory: | |
| 116 parser.error("Not a directory: %s" % (', '.join(not_directory))) | |
| 117 | |
|
390
9d02187611ae
make delimeters CLI switchable
Jeff Hammel <jhammel@mozilla.com>
parents:
389
diff
changeset
|
118 delimeters = unicode_delimeters |
|
9d02187611ae
make delimeters CLI switchable
Jeff Hammel <jhammel@mozilla.com>
parents:
389
diff
changeset
|
119 if options.use_ascii: |
|
9d02187611ae
make delimeters CLI switchable
Jeff Hammel <jhammel@mozilla.com>
parents:
389
diff
changeset
|
120 delimeters = ascii_delimeters |
|
9d02187611ae
make delimeters CLI switchable
Jeff Hammel <jhammel@mozilla.com>
parents:
389
diff
changeset
|
121 |
|
9d02187611ae
make delimeters CLI switchable
Jeff Hammel <jhammel@mozilla.com>
parents:
389
diff
changeset
|
122 # print the tree |
| 382 | 123 for arg in args: |
|
390
9d02187611ae
make delimeters CLI switchable
Jeff Hammel <jhammel@mozilla.com>
parents:
389
diff
changeset
|
124 print (tree(arg, **delimeters)) |
| 382 | 125 |
| 126 if __name__ == '__main__': | |
| 127 main() |
