colify handles ansi color input directly; no more decorator.
This commit is contained in:
parent
40b4fa5443
commit
11cffff943
5 changed files with 55 additions and 47 deletions
|
@ -145,18 +145,16 @@ def get_yes_or_no(prompt, **kwargs):
|
|||
|
||||
|
||||
def hline(label=None, **kwargs):
|
||||
"""Draw an optionally colored or labeled horizontal line.
|
||||
"""Draw a labeled horizontal line.
|
||||
Options:
|
||||
|
||||
char Char to draw the line with. Default '-'
|
||||
color Color of the label. Default is no color.
|
||||
max_width Maximum width of the line. Default is 64 chars.
|
||||
|
||||
See tty.color for possible color formats.
|
||||
"""
|
||||
char = kwargs.get('char', '-')
|
||||
color = kwargs.get('color', '')
|
||||
max_width = kwargs.get('max_width', 64)
|
||||
char = kwargs.pop('char', '-')
|
||||
max_width = kwargs.pop('max_width', 64)
|
||||
if kwargs:
|
||||
raise TypeError("'%s' is an invalid keyword argument for this function."
|
||||
% next(kwargs.iterkeys()))
|
||||
|
||||
rows, cols = terminal_size()
|
||||
if not cols:
|
||||
|
@ -166,15 +164,12 @@ def hline(label=None, **kwargs):
|
|||
cols = min(max_width, cols)
|
||||
|
||||
label = str(label)
|
||||
prefix = char * 2 + " " + label + " "
|
||||
suffix = (cols - len(prefix)) * char
|
||||
prefix = char * 2 + " "
|
||||
suffix = " " + (cols - len(prefix) - clen(label)) * char
|
||||
|
||||
out = StringIO()
|
||||
if color:
|
||||
prefix = char * 2 + " " + color + cescape(label) + "@. "
|
||||
cwrite(prefix, stream=out, color=True)
|
||||
else:
|
||||
out.write(prefix)
|
||||
out.write(prefix)
|
||||
out.write(label)
|
||||
out.write(suffix)
|
||||
|
||||
print out.getvalue()
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
from StringIO import StringIO
|
||||
|
||||
from llnl.util.tty import terminal_size
|
||||
from llnl.util.tty.color import clen
|
||||
|
||||
|
||||
class ColumnConfig:
|
||||
|
@ -40,7 +41,8 @@ def __init__(self, cols):
|
|||
self.cols = cols
|
||||
self.line_length = 0
|
||||
self.valid = True
|
||||
self.widths = [0] * cols
|
||||
self.widths = [0] * cols # does not include ansi colors
|
||||
self.cwidths = [0] * cols # includes ansi colors
|
||||
|
||||
def __repr__(self):
|
||||
attrs = [(a,getattr(self, a)) for a in dir(self) if not a.startswith("__")]
|
||||
|
@ -62,7 +64,10 @@ def config_variable_cols(elts, console_width, padding, cols=0):
|
|||
raise ValueError("cols must be non-negative.")
|
||||
|
||||
# Get a bound on the most columns we could possibly have.
|
||||
lengths = [len(elt) for elt in elts]
|
||||
# 'clen' ignores length of ansi color sequences.
|
||||
lengths = [clen(e) for e in elts]
|
||||
clengths = [len(e) for e in elts]
|
||||
|
||||
max_cols = max(1, console_width / (min(lengths) + padding))
|
||||
max_cols = min(len(elts), max_cols)
|
||||
|
||||
|
@ -71,17 +76,16 @@ def config_variable_cols(elts, console_width, padding, cols=0):
|
|||
|
||||
# Determine the most columns possible for the console width.
|
||||
configs = [ColumnConfig(c) for c in col_range]
|
||||
for elt, length in enumerate(lengths):
|
||||
for i, length in enumerate(lengths):
|
||||
for conf in configs:
|
||||
if conf.valid:
|
||||
col = elt / ((len(elts) + conf.cols - 1) / conf.cols)
|
||||
padded = length
|
||||
if col < (conf.cols - 1):
|
||||
padded += padding
|
||||
col = i / ((len(elts) + conf.cols - 1) / conf.cols)
|
||||
p = padding if col < (conf.cols - 1) else 0
|
||||
|
||||
if conf.widths[col] < padded:
|
||||
conf.line_length += padded - conf.widths[col]
|
||||
conf.widths[col] = padded
|
||||
if conf.widths[col] < (length + p):
|
||||
conf.line_length += length + p - conf.widths[col]
|
||||
conf.widths[col] = length + p
|
||||
conf.cwidths[col] = clengths[i] + p
|
||||
conf.valid = (conf.line_length < console_width)
|
||||
|
||||
try:
|
||||
|
@ -105,12 +109,17 @@ def config_uniform_cols(elts, console_width, padding, cols=0):
|
|||
if cols < 0:
|
||||
raise ValueError("cols must be non-negative.")
|
||||
|
||||
max_len = max(len(elt) for elt in elts) + padding
|
||||
# 'clen' ignores length of ansi color sequences.
|
||||
max_len = max(clen(e) for e in elts) + padding
|
||||
max_clen = max(len(e) for e in elts) + padding
|
||||
if cols == 0:
|
||||
cols = max(1, console_width / max_len)
|
||||
cols = min(len(elts), cols)
|
||||
|
||||
config = ColumnConfig(cols)
|
||||
config.widths = [max_len] * cols
|
||||
config.cwidths = [max_clen] * cols
|
||||
|
||||
return config
|
||||
|
||||
|
||||
|
@ -139,9 +148,8 @@ def colify(elts, **options):
|
|||
Variable-width columns are tighter, uniform columns are all the
|
||||
same width and fit less data on the screen.
|
||||
|
||||
decorator=<func> Function to add decoration (such as color) after columns have
|
||||
already been fitted. Useful for fitting based only on
|
||||
positive-width characters.
|
||||
len=<func> Function to use for calculating string length.
|
||||
Useful for ignoring ansi color. Default is 'len'.
|
||||
"""
|
||||
# Get keyword arguments or set defaults
|
||||
cols = options.pop("cols", 0)
|
||||
|
@ -151,7 +159,6 @@ def colify(elts, **options):
|
|||
tty = options.pop('tty', None)
|
||||
method = options.pop("method", "variable")
|
||||
console_cols = options.pop("width", None)
|
||||
decorator = options.pop("decorator", lambda x:x)
|
||||
|
||||
if options:
|
||||
raise TypeError("'%s' is an invalid keyword argument for this function."
|
||||
|
@ -162,13 +169,10 @@ def colify(elts, **options):
|
|||
if not elts:
|
||||
return (0, ())
|
||||
|
||||
# Use only one column if not a tty.
|
||||
if not tty:
|
||||
if tty is False or not output.isatty():
|
||||
for elt in elts:
|
||||
output.write("%s\n" % elt)
|
||||
|
||||
maxlen = max(len(str(s)) for s in elts)
|
||||
return (1, (maxlen,))
|
||||
cols = 1
|
||||
|
||||
# Specify the number of character columns to use.
|
||||
if not console_cols:
|
||||
|
@ -186,7 +190,7 @@ def colify(elts, **options):
|
|||
raise ValueError("method must be one of: " + allowed_methods)
|
||||
|
||||
cols = config.cols
|
||||
formats = ["%%-%ds" % width for width in config.widths[:-1]]
|
||||
formats = ["%%-%ds" % width for width in config.cwidths[:-1]]
|
||||
formats.append("%s") # last column has no trailing space
|
||||
|
||||
rows = (len(elts) + cols - 1) / cols
|
||||
|
@ -196,7 +200,7 @@ def colify(elts, **options):
|
|||
output.write(" " * indent)
|
||||
for col in xrange(cols):
|
||||
elt = col * rows + row
|
||||
output.write(decorator(formats[col] % elts[elt]))
|
||||
output.write(formats[col] % elts[elt])
|
||||
|
||||
output.write("\n")
|
||||
row += 1
|
||||
|
|
|
@ -149,6 +149,11 @@ def colorize(string, **kwargs):
|
|||
return re.sub(color_re, match_to_ansi(color), string)
|
||||
|
||||
|
||||
def clen(string):
|
||||
"""Return the length of a string, excluding ansi color sequences."""
|
||||
return len(re.sub(r'\033[^m]*m', '', string))
|
||||
|
||||
|
||||
def cwrite(string, stream=sys.stdout, color=None):
|
||||
"""Replace all color expressions in string with ANSI control
|
||||
codes and write the result to the stream. If color is
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
from external import argparse
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.tty.color import colorize
|
||||
from llnl.util.tty.colify import colify
|
||||
from llnl.util.lang import index_by
|
||||
|
||||
|
@ -96,9 +97,12 @@ def compiler_info(args):
|
|||
def compiler_list(args):
|
||||
tty.msg("Available compilers")
|
||||
index = index_by(spack.compilers.all_compilers(), 'name')
|
||||
for name, compilers in index.items():
|
||||
tty.hline(name, char='-', color=spack.spec.compiler_color)
|
||||
colify(reversed(sorted(compilers)), indent=4)
|
||||
for i, (name, compilers) in enumerate(index.items()):
|
||||
if i >= 1: print
|
||||
|
||||
cname = "%s{%s}" % (spack.spec.compiler_color, name)
|
||||
tty.hline(colorize(cname), char='-')
|
||||
colify(reversed(sorted(compilers)))
|
||||
|
||||
|
||||
def compiler(parser, args):
|
||||
|
|
|
@ -79,13 +79,16 @@ def find(parser, args):
|
|||
# Traverse the index and print out each package
|
||||
for i, (architecture, compiler) in enumerate(sorted(index)):
|
||||
if i > 0: print
|
||||
tty.hline("%s / %s" % (compiler, architecture), char='-')
|
||||
|
||||
specs = index[(architecture, compiler)]
|
||||
header = "%s{%s} / %s{%s}" % (
|
||||
spack.spec.architecture_color, architecture,
|
||||
spack.spec.compiler_color, compiler)
|
||||
tty.hline(colorize(header), char='-')
|
||||
|
||||
specs = index[(architecture,compiler)]
|
||||
specs.sort()
|
||||
|
||||
abbreviated = [s.format('$_$@$+$#', color=True) for s in specs]
|
||||
|
||||
if args.paths:
|
||||
# Print one spec per line along with prefix path
|
||||
width = max(len(s) for s in abbreviated)
|
||||
|
@ -99,7 +102,4 @@ def find(parser, args):
|
|||
for spec in specs:
|
||||
print spec.tree(indent=4, format='$_$@$+', color=True),
|
||||
else:
|
||||
max_len = max([len(s.name) for s in specs])
|
||||
max_len += 4
|
||||
|
||||
colify((s.format('$-_$@$+$#') for s in specs), decorator=spack.spec.colorize_spec)
|
||||
colify(s.format('$-_$@$+$#', color=True) for s in specs)
|
||||
|
|
Loading…
Reference in a new issue