Colify now supports fixing the number of columns.
This commit is contained in:
parent
22e4d11010
commit
72c753b93e
1 changed files with 32 additions and 12 deletions
|
@ -47,7 +47,7 @@ def __repr__(self):
|
||||||
return "<Config: %s>" % ", ".join("%s: %r" % a for a in attrs)
|
return "<Config: %s>" % ", ".join("%s: %r" % a for a in attrs)
|
||||||
|
|
||||||
|
|
||||||
def config_variable_cols(elts, console_width, padding):
|
def config_variable_cols(elts, console_width, padding, cols=0):
|
||||||
"""Variable-width column fitting algorithm.
|
"""Variable-width column fitting algorithm.
|
||||||
|
|
||||||
This function determines the most columns that can fit in the
|
This function determines the most columns that can fit in the
|
||||||
|
@ -55,20 +55,28 @@ def config_variable_cols(elts, console_width, padding):
|
||||||
the width of the longest element in the list, each column takes
|
the width of the longest element in the list, each column takes
|
||||||
the width of its own longest element. This packs elements more
|
the width of its own longest element. This packs elements more
|
||||||
efficiently on screen.
|
efficiently on screen.
|
||||||
|
|
||||||
|
If cols is nonzero, force
|
||||||
"""
|
"""
|
||||||
|
if cols < 0:
|
||||||
|
raise ValueError("cols must be non-negative.")
|
||||||
|
|
||||||
# Get a bound on the most columns we could possibly have.
|
# Get a bound on the most columns we could possibly have.
|
||||||
lengths = [len(elt) for elt in elts]
|
lengths = [len(elt) for elt in elts]
|
||||||
max_cols = max(1, console_width / (min(lengths) + padding))
|
max_cols = max(1, console_width / (min(lengths) + padding))
|
||||||
max_cols = min(len(elts), max_cols)
|
max_cols = min(len(elts), max_cols)
|
||||||
|
|
||||||
|
# Range of column counts to try. If forced, use the supplied value.
|
||||||
|
col_range = [cols] if cols else xrange(1, max_cols+1)
|
||||||
|
|
||||||
# Determine the most columns possible for the console width.
|
# Determine the most columns possible for the console width.
|
||||||
configs = [ColumnConfig(c) for c in xrange(1, max_cols+1)]
|
configs = [ColumnConfig(c) for c in col_range]
|
||||||
for elt, length in enumerate(lengths):
|
for elt, length in enumerate(lengths):
|
||||||
for i, conf in enumerate(configs):
|
for conf in configs:
|
||||||
if conf.valid:
|
if conf.valid:
|
||||||
col = elt / ((len(elts) + i) / (i + 1))
|
col = elt / ((len(elts) + conf.cols - 1) / conf.cols)
|
||||||
padded = length
|
padded = length
|
||||||
if col < i:
|
if col < (conf.cols - 1):
|
||||||
padded += padding
|
padded += padding
|
||||||
|
|
||||||
if conf.widths[col] < padded:
|
if conf.widths[col] < padded:
|
||||||
|
@ -87,14 +95,18 @@ def config_variable_cols(elts, console_width, padding):
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
def config_uniform_cols(elts, console_width, padding):
|
def config_uniform_cols(elts, console_width, padding, cols=0):
|
||||||
"""Uniform-width column fitting algorithm.
|
"""Uniform-width column fitting algorithm.
|
||||||
|
|
||||||
Determines the longest element in the list, and determines how
|
Determines the longest element in the list, and determines how
|
||||||
many columns of that width will fit on screen. Returns a
|
many columns of that width will fit on screen. Returns a
|
||||||
corresponding column config.
|
corresponding column config.
|
||||||
"""
|
"""
|
||||||
|
if cols < 0:
|
||||||
|
raise ValueError("cols must be non-negative.")
|
||||||
|
|
||||||
max_len = max(len(elt) for elt in elts) + padding
|
max_len = max(len(elt) for elt in elts) + padding
|
||||||
|
if cols == 0:
|
||||||
cols = max(1, console_width / max_len)
|
cols = max(1, console_width / max_len)
|
||||||
cols = min(len(elts), cols)
|
cols = min(len(elts), cols)
|
||||||
config = ColumnConfig(cols)
|
config = ColumnConfig(cols)
|
||||||
|
@ -115,6 +127,10 @@ def colify(elts, **options):
|
||||||
output=<stream> A file object to write to. Default is sys.stdout.
|
output=<stream> A file object to write to. Default is sys.stdout.
|
||||||
indent=<int> Optionally indent all columns by some number of spaces.
|
indent=<int> Optionally indent all columns by some number of spaces.
|
||||||
padding=<int> Spaces between columns. Default is 2.
|
padding=<int> Spaces between columns. Default is 2.
|
||||||
|
width=<int> Width of the output. Default is 80 if tty is not detected.
|
||||||
|
|
||||||
|
cols=<int> Force number of columns. Default is to size to terminal,
|
||||||
|
or single-column if no tty
|
||||||
|
|
||||||
tty=<bool> Whether to attempt to write to a tty. Default is to
|
tty=<bool> Whether to attempt to write to a tty. Default is to
|
||||||
autodetect a tty. Set to False to force single-column output.
|
autodetect a tty. Set to False to force single-column output.
|
||||||
|
@ -123,15 +139,19 @@ def colify(elts, **options):
|
||||||
Variable-width columns are tighter, uniform columns are all the
|
Variable-width columns are tighter, uniform columns are all the
|
||||||
same width and fit less data on the screen.
|
same width and fit less data on the screen.
|
||||||
|
|
||||||
width=<int> Width of the output. Default is 80 if tty is not detected.
|
decorator=<func> Function to add decoration (such as color) after columns have
|
||||||
|
already been fitted. Useful for fitting based only on
|
||||||
|
positive-width characters.
|
||||||
"""
|
"""
|
||||||
# Get keyword arguments or set defaults
|
# Get keyword arguments or set defaults
|
||||||
|
cols = options.pop("cols", 0)
|
||||||
output = options.pop("output", sys.stdout)
|
output = options.pop("output", sys.stdout)
|
||||||
indent = options.pop("indent", 0)
|
indent = options.pop("indent", 0)
|
||||||
padding = options.pop("padding", 2)
|
padding = options.pop("padding", 2)
|
||||||
tty = options.pop('tty', None)
|
tty = options.pop('tty', None)
|
||||||
method = options.pop("method", "variable")
|
method = options.pop("method", "variable")
|
||||||
console_cols = options.pop("width", None)
|
console_cols = options.pop("width", None)
|
||||||
|
decorator = options.pop("decorator", lambda x:x)
|
||||||
|
|
||||||
if options:
|
if options:
|
||||||
raise TypeError("'%s' is an invalid keyword argument for this function."
|
raise TypeError("'%s' is an invalid keyword argument for this function."
|
||||||
|
@ -159,9 +179,9 @@ def colify(elts, **options):
|
||||||
|
|
||||||
# Choose a method. Variable-width colums vs uniform-width.
|
# Choose a method. Variable-width colums vs uniform-width.
|
||||||
if method == "variable":
|
if method == "variable":
|
||||||
config = config_variable_cols(elts, console_cols, padding)
|
config = config_variable_cols(elts, console_cols, padding, cols)
|
||||||
elif method == "uniform":
|
elif method == "uniform":
|
||||||
config = config_uniform_cols(elts, console_cols, padding)
|
config = config_uniform_cols(elts, console_cols, padding, cols)
|
||||||
else:
|
else:
|
||||||
raise ValueError("method must be one of: " + allowed_methods)
|
raise ValueError("method must be one of: " + allowed_methods)
|
||||||
|
|
||||||
|
@ -176,7 +196,7 @@ def colify(elts, **options):
|
||||||
output.write(" " * indent)
|
output.write(" " * indent)
|
||||||
for col in xrange(cols):
|
for col in xrange(cols):
|
||||||
elt = col * rows + row
|
elt = col * rows + row
|
||||||
output.write(formats[col] % elts[elt])
|
output.write(formats[col] % decorator(elts[elt]))
|
||||||
|
|
||||||
output.write("\n")
|
output.write("\n")
|
||||||
row += 1
|
row += 1
|
||||||
|
|
Loading…
Reference in a new issue