diff options
author | Jan Pokorný <jpokorny@redhat.com> | 2012-03-09 15:25:39 +0100 |
---|---|---|
committer | Jan Pokorný <jpokorny@redhat.com> | 2012-03-09 15:25:39 +0100 |
commit | 486635d185284f6ee99fc3e6a208acef5e5dbee3 (patch) | |
tree | a914faa9cc14eb0577d693fe0403514d80111ad3 | |
parent | da9c29a6b924b7b2373d1ab176bd90489e2aef30 (diff) | |
download | watch-bz-486635d185284f6ee99fc3e6a208acef5e5dbee3.tar.gz watch-bz-486635d185284f6ee99fc3e6a208acef5e5dbee3.tar.xz watch-bz-486635d185284f6ee99fc3e6a208acef5e5dbee3.zip |
add missing table-data script
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
-rwxr-xr-x | table_data | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/table_data b/table_data new file mode 100755 index 0000000..2206e0e --- /dev/null +++ b/table_data @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# pretty much copy of http://code.activestate.com/recipes/267662/ +# with some other changes +from sys import stdin, argv +import cStringIO,operator +from threading import Timer, RLock + +def indent(rows, hasHeader=False, headerChar='-', delim=' | ', justify='left', + separateRows=False, prefix='', postfix='', wrapfunc=lambda x:x): + """Indents a table by column. + - rows: A sequence of sequences of items, one sequence per row. + - hasHeader: True if the first row consists of the columns' names. + - headerChar: Character to be used for the row separator line + (if hasHeader==True or separateRows==True). + - delim: The column delimiter. + - justify: Determines how are data justified in their column. + Valid values are 'left','right' and 'center'. + - separateRows: True if rows are to be separated by a line + of 'headerChar's. + - prefix: A string prepended to each printed row. + - postfix: A string appended to each printed row. + - wrapfunc: A function f(text) for wrapping text; each element in + the table is first wrapped by this function.""" + # closure for breaking logical rows to physical, using wrapfunc + def rowWrapper(row): + newRows = [wrapfunc(item).split('\n') for item in row] + return [[substr or '' for substr in item] for item in map(None,*newRows)] + # break each logical row into one or more physical ones + logicalRows = [rowWrapper(row) for row in rows] + # columns of physical rows + columns = map(None,*reduce(operator.add,logicalRows)) + # get the maximum of each column by the string length of its items + maxWidths = [max([len(str(item)) for item in column]) for column in columns] + rowSeparator = headerChar * (len(prefix) + len(postfix) + sum(maxWidths) + \ + len(delim)*(len(maxWidths)-1)) + # select the appropriate justify method + justify = {'center':str.center, 'right':str.rjust, 'left':str.ljust}[justify.lower()] + output=cStringIO.StringIO() + if separateRows: print >> output, rowSeparator + for physicalRows in logicalRows: + for row in physicalRows: + print >> output, \ + prefix \ + + delim.join([justify(str(item),width) for (item,width) in zip(row,maxWidths)]) \ + + postfix + if separateRows or hasHeader: print >> output, rowSeparator; hasHeader=False + return output.getvalue() + +# written by Mike Brown +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061 +def wrap_onspace(text, width): + """ + A word-wrap function that preserves existing line breaks + and most spaces in the text. Expects that existing line + breaks are posix newlines (\n). + """ + return reduce(lambda line, word, width=width: '%s%s%s' % + (line, + ' \n'[(len(line[line.rfind('\n')+1:]) + + len(word.split('\n',1)[0] + ) >= width)], + word), + text.split(' ') + ) + +import re +def wrap_onspace_strict(text, width): + """Similar to wrap_onspace, but enforces the width constraint: + words longer than width are split.""" + wordRegex = re.compile(r'\S{'+str(width)+r',}') + return wrap_onspace(wordRegex.sub(lambda m: wrap_always(m.group(),width),text),width) + +import math +def wrap_always(text, width): + """A simple word-wrap function that wraps text on exactly width characters. + It doesn't split the text in words.""" + return '\n'.join([ text[width*i:width*(i+1)] \ + for i in xrange(int(math.ceil(1.*len(text)/width))) ]) + + +if __name__ == '__main__': + def timer(lock, data): + with lock: + data.append[False] + + lock = RLock() + ret, data = True, [True] + + while ret and (not len(data) or data[-1] != ''): # EOF + t = Timer(15, timer, args=(lock, data)) + while ret and data[-1]: + ret = stdin.readline() + #print "read", ret + with lock: + if not isinstance(data[-1], str): + data = data[:-1] + data.append(ret) + t.cancel() + #if not isinstance(data[-1], str): + # data = data[:-1] + sep = ',' + if len(argv) > 1: + sep = argv[1] + rows = [row.strip().split(sep) for row in data] + + #print 'Without wrapping function\n' + print indent(rows, hasHeader=False) + # test indent with different wrapping functions + #width = 10 + #for wrapper in (wrap_always,wrap_onspace,wrap_onspace_strict): + # print 'Wrapping function: %s(x,width=%d)\n' % (wrapper.__name__,width) + # print indent(rows, hasHeader=False, separateRows=True, + # prefix='| ', postfix=' |', + # wrapfunc=lambda x: wrapper(x,width)) |