diff options
author | Erik Rose <erik@mozilla.com> | 2011-11-16 16:10:08 -0800 |
---|---|---|
committer | Erik Rose <erik@mozilla.com> | 2011-11-16 16:17:48 -0800 |
commit | 163838a93f4a4fac40ab881b6691bb1cecb6e898 (patch) | |
tree | cc3bef8c89581ec6dca2ad2242c595feb50c752d | |
parent | d739af35d4fe4f40df8aa43ca70aa59e87863d2d (diff) | |
download | blessings-163838a93f4a4fac40ab881b6691bb1cecb6e898.tar.gz |
Fix simple formatting attributes not working as wrappers.
-rw-r--r-- | blessings/__init__.py | 65 | ||||
-rw-r--r-- | blessings/tests.py | 2 |
2 files changed, 36 insertions, 31 deletions
diff --git a/blessings/__init__.py b/blessings/__init__.py index 1a4eee4..548d5b8 100644 --- a/blessings/__init__.py +++ b/blessings/__init__.py @@ -170,41 +170,26 @@ class Terminal(object): def _resolve_formatter(self, attr): """Resolve a sugary or plain capability name, color, or compound formatting function name into a callable string.""" - def split_into_formatters(compound): - """Split a possibly compound format string into segments. - - >>> split_into_formatters('bold_underline_bright_blue_on_red') - ['bold', 'underline', 'bright_blue', 'on_red'] - - """ - merged_segs = [] - # These occur only as prefixes, so they can always be merged: - mergeable_prefixes = ['on', 'bright', 'on_bright'] - for s in compound.split('_'): - if merged_segs and merged_segs[-1] in mergeable_prefixes: - merged_segs[-1] += '_' + s - else: - merged_segs.append(s) - return merged_segs - - if attr in colors: + if attr in COLORS: return self._resolve_color(attr) + elif attr in COMPOUNDABLES: + # Bold, underline, or something that takes no parameters + return FormattingString(self._resolve_capability(attr), self) else: formatters = split_into_formatters(attr) - if len(formatters) > 1 and all(f in compoundables for f in formatters): - # It's a compound formatter, like "bold_green_on_red". If we - # wanted, we could even get crazy and combine all formatting - # into a single escape sequence, but nobody's on a 300 baud - # modem anymore. + if all(f in COMPOUNDABLES for f in formatters): + # It's a compound formatter, like "bold_green_on_red". Future + # optimization: combine all formatting into a single escape + # sequence return FormattingString(''.join(self._resolve_formatter(s) for s in formatters), self) else: - return self._resolve_capability(attr) + return ParametrizingString(self._resolve_capability(attr)) def _resolve_capability(self, atom): """Return a terminal code for a capname or a sugary name, or ''.""" - return ParametrizingString(tigetstr(self._sugar.get(atom, atom)) or '') + return tigetstr(self._sugar.get(atom, atom)) or '' def _resolve_color(self, color): """Resolve a color like red or on_bright_green into a callable string.""" @@ -223,12 +208,12 @@ class Terminal(object): self) -colors = set(['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white']) -colors.update(set([('on_' + c) for c in colors] + - [('bright_' + c) for c in colors] + - [('on_bright_' + c) for c in colors])) +COLORS = set(['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white']) +COLORS.update(set([('on_' + c) for c in COLORS] + + [('bright_' + c) for c in COLORS] + + [('on_bright_' + c) for c in COLORS])) del c -compoundables = (colors | +COMPOUNDABLES = (COLORS | set(['bold', 'underline', 'reverse', 'blink', 'dim', 'italic', 'shadow', 'standout', 'subscript', 'superscript'])) @@ -279,7 +264,7 @@ class FormattingString(str): class NullCallableString(str): - """A callable string that returns '' when called with an int and itself when called otherwise.""" + """A callable string that returns '' when called with an int and the arg otherwise.""" def __call__(self, arg): if isinstance(arg, int): return '' @@ -299,6 +284,24 @@ def height_and_width(): return struct.unpack('hhhh', ioctl(0, TIOCGWINSZ, '\000' * 8))[0:2] +def split_into_formatters(compound): + """Split a possibly compound format string into segments. + + >>> split_into_formatters('bold_underline_bright_blue_on_red') + ['bold', 'underline', 'bright_blue', 'on_red'] + + """ + merged_segs = [] + # These occur only as prefixes, so they can always be merged: + mergeable_prefixes = ['on', 'bright', 'on_bright'] + for s in compound.split('_'): + if merged_segs and merged_segs[-1] in mergeable_prefixes: + merged_segs[-1] += '_' + s + else: + merged_segs.append(s) + return merged_segs + + class Location(object): """Context manager for temporarily moving the cursor diff --git a/blessings/tests.py b/blessings/tests.py index 8d7508a..d9e7d85 100644 --- a/blessings/tests.py +++ b/blessings/tests.py @@ -104,6 +104,7 @@ def test_mnemonic_colors(): def test_formatting_functions(): """Test crazy-ass formatting wrappers, both simple and compound.""" t = Terminal() + eq_(t.bold('hi'), t.bold + 'hi' + t.normal) eq_(t.green('hi'), t.green + 'hi' + t.normal) eq_(t.bold_green(u'boö'), t.bold + t.green + u'boö' + t.normal) # unicode eq_(t.bold_underline_green_on_red('boo'), @@ -116,6 +117,7 @@ def test_formatting_functions(): def test_formatting_functions_without_tty(): """Test crazy-ass formatting wrappers when there's no tty.""" t = Terminal(stream=StringIO()) + eq_(t.bold('hi'), 'hi') eq_(t.green('hi'), 'hi') eq_(t.bold_green(u'boö'), u'boö') # unicode eq_(t.bold_underline_green_on_red('boo'), 'boo') |