##// END OF EJS Templates
* ConsoleWidget now has better support for non-GUI tab completion. Multiple matches are formatted into columns....
* ConsoleWidget now has better support for non-GUI tab completion. Multiple matches are formatted into columns. * Tab width can now be set at runtime rather than only during initialization. * Added external module columnize.py

File last commit:

r2723:226529a9
r2723:226529a9
Show More
columnize.py
160 lines | 5.7 KiB | text/x-python | PythonLexer
"""Return compact set of columns as a string with newlines for an
array of strings.
Adapted from the routine of the same name inside cmd.py
Author: Rocky Bernstein.
License: MIT Open Source License.
"""
import types
def columnize(array, displaywidth=80, colsep = ' ',
arrange_vertical=True, ljust=True, lineprefix=''):
"""Return a list of strings as a compact set of columns arranged
horizontally or vertically.
For example, for a line width of 4 characters (arranged vertically):
['1', '2,', '3', '4'] => '1 3\n2 4\n'
or arranged horizontally:
['1', '2,', '3', '4'] => '1 2\n3 4\n'
Each column is only as wide as necessary. By default, columns are
separated by two spaces - one was not legible enough. Set "colsep"
to adjust the string separate columns. Set `displaywidth' to set
the line width.
Normally, consecutive items go down from the top to bottom from
the left-most column to the right-most. If "arrange_vertical" is
set false, consecutive items will go across, left to right, top to
bottom."""
if not isinstance(array, list) and not isinstance(array, tuple):
raise TypeError, (
'array needs to be an instance of a list or a tuple')
array = [str(i) for i in array]
# Some degenerate cases
size = len(array)
if 0 == size:
return "<empty>\n"
elif size == 1:
return '%s\n' % str(array[0])
displaywidth = max(4, displaywidth - len(lineprefix))
if arrange_vertical:
array_index = lambda nrows, row, col: nrows*col + row
# Try every row count from 1 upwards
for nrows in range(1, size):
ncols = (size+nrows-1) // nrows
colwidths = []
totwidth = -len(colsep)
for col in range(ncols):
# get max column width for this column
colwidth = 0
for row in range(nrows):
i = array_index(nrows, row, col)
if i >= size: break
x = array[i]
colwidth = max(colwidth, len(x))
pass
colwidths.append(colwidth)
totwidth += colwidth + len(colsep)
if totwidth > displaywidth:
break
pass
if totwidth <= displaywidth:
break
pass
# The smallest number of rows computed and the
# max widths for each column has been obtained.
# Now we just have to format each of the
# rows.
s = ''
for row in range(nrows):
texts = []
for col in range(ncols):
i = row + nrows*col
if i >= size:
x = ""
else:
x = array[i]
texts.append(x)
while texts and not texts[-1]:
del texts[-1]
for col in range(len(texts)):
if ljust:
texts[col] = texts[col].ljust(colwidths[col])
else:
texts[col] = texts[col].rjust(colwidths[col])
pass
pass
s += "%s%s\n" % (lineprefix, str(colsep.join(texts)))
pass
return s
else:
array_index = lambda nrows, row, col: ncols*(row-1) + col
# Try every column count from size downwards
prev_colwidths = []
colwidths = []
for ncols in range(size, 0, -1):
# Try every row count from 1 upwards
min_rows = (size+ncols-1) // ncols
for nrows in range(min_rows, size):
rounded_size = nrows * ncols
colwidths = []
totwidth = -len(colsep)
for col in range(ncols):
# get max column width for this column
colwidth = 0
for row in range(1, nrows+1):
i = array_index(nrows, row, col)
if i >= rounded_size: break
elif i < size:
x = array[i]
colwidth = max(colwidth, len(x))
pass
pass
colwidths.append(colwidth)
totwidth += colwidth + len(colsep)
if totwidth >= displaywidth:
break
pass
if totwidth <= displaywidth and i >= rounded_size-1:
# Found the right nrows and ncols
nrows = row
break
elif totwidth >= displaywidth:
# Need to reduce ncols
break
pass
if totwidth <= displaywidth and i >= rounded_size-1:
break
pass
# The smallest number of rows computed and the
# max widths for each column has been obtained.
# Now we just have to format each of the
# rows.
s = ''
for row in range(1, nrows+1):
texts = []
for col in range(ncols):
i = array_index(nrows, row, col)
if i >= size:
break
else: x = array[i]
texts.append(x)
pass
for col in range(len(texts)):
if ljust:
texts[col] = texts[col].ljust(colwidths[col])
else:
texts[col] = texts[col].rjust(colwidths[col])
pass
pass
s += "%s%s\n" % (lineprefix, str(colsep.join(texts)))
pass
return s
pass