diff options
author | Erik Rose <erik@mozilla.com> | 2011-11-30 23:44:47 -0800 |
---|---|---|
committer | Erik Rose <erik@mozilla.com> | 2011-11-30 23:44:47 -0800 |
commit | 15293bc24d35d4c60dbce75528bde571c1a60b63 (patch) | |
tree | 5c237f796aec172aff38564da09a3f496e6a1e12 /blessings/__init__.py | |
parent | 3c711a9ce95856239a451f6c8dae2a2865979ffc (diff) | |
download | blessings-15293bc24d35d4c60dbce75528bde571c1a60b63.tar.gz |
Allow `color` attr to act as an unparametrized string, not just a callable.
Also have FormattingString stop reaching into the Terminal to pull out `normal`.
Diffstat (limited to 'blessings/__init__.py')
-rw-r--r-- | blessings/__init__.py | 63 |
1 files changed, 38 insertions, 25 deletions
diff --git a/blessings/__init__.py b/blessings/__init__.py index b4b2ecb..f46ee66 100644 --- a/blessings/__init__.py +++ b/blessings/__init__.py @@ -185,27 +185,28 @@ class Terminal(object): """ return Location(self, x, y) - def color(self, num): + @property + def color(self): """Return a capability that sets the foreground color. - :arg num: The number, 0-15, of the color + The capability is unparametrized until called and passed a number + (0-15), at which point it returns another string which represents a + specific color change. This second string can further be called to + color a piece of text and set everything back to normal afterward. - The returned string can also be called on another string to wrap it in - the color and set the formatting to normal afterward. + :arg num: The number, 0-15, of the color """ - return self._resolve_numeric_color(num, self._foreground_color) + return ParametrizingString(self._foreground_color, self.normal) - def on_color(self, num): + @property + def on_color(self): """Return a capability that sets the background color. - :arg num: The number, 0-15, of the color - - The returned string can also be called on another string to wrap it in - the color and set the formatting to normal afterward. + See ``color()``. """ - return self._resolve_numeric_color(num, self._background_color) + return ParametrizingString(self._background_color, self.normal) def _resolve_formatter(self, attr): """Resolve a sugary or plain capability name, color, or compound formatting function name into a callable capability.""" @@ -213,16 +214,15 @@ class Terminal(object): return self._resolve_color(attr) elif attr in COMPOUNDABLES: # Bold, underline, or something that takes no parameters - return FormattingString(self._resolve_capability(attr), self) + return self._formatting_string(self._resolve_capability(attr)) else: formatters = split_into_formatters(attr) 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( - u''.join(self._resolve_formatter(s) for s in formatters), - self) + return self._formatting_string( + u''.join(self._resolve_formatter(s) for s in formatters)) else: return ParametrizingString(self._resolve_capability(attr)) @@ -253,13 +253,8 @@ class Terminal(object): # bright colors at 8-15: offset = 8 if 'bright_' in color else 0 base_color = color.rsplit('_', 1)[-1] - return self._resolve_numeric_color( - getattr(curses, 'COLOR_' + base_color.upper()) + offset, - color_cap) - - def _resolve_numeric_color(self, num, cap): - """Resolve a numeric base color to a ``FormattingString``.""" - return FormattingString(cap(num), self) + return self._formatting_string( + color_cap(getattr(curses, 'COLOR_' + base_color.upper()) + offset)) @property def _foreground_color(self): @@ -269,6 +264,10 @@ class Terminal(object): def _background_color(self): return self.setab or self.setb + def _formatting_string(self, formatting): + """Return a new ``FormattingString`` which implicitly receives my notion of "normal".""" + return FormattingString(formatting, self.normal) + def derivative_colors(colors): """Return the names of valid color variants, given the base colors.""" @@ -286,12 +285,26 @@ COMPOUNDABLES = (COLORS | class ParametrizingString(unicode): """A Unicode string which can be called to parametrize it as a terminal capability""" + def __new__(cls, formatting, normal=None): + """Instantiate. + + :arg normal: If non-None, indicates that, once parametrized, this can + be used as a ``FormattingString``. The value is used as the + "normal" capability. + + """ + new = unicode.__new__(cls, formatting) + new._normal = normal + return new + def __call__(self, *args): try: # Re-encode the cap, because tparm() takes a bytestring in Python # 3. However, appear to be a plain Unicode string otherwise so # concats work. - return tparm(self.encode('utf-8'), *args).decode('utf-8') + parametrized = tparm(self.encode('utf-8'), *args).decode('utf-8') + return (parametrized if self._normal is None else + FormattingString(parametrized, self._normal)) except curses.error: # Catch "must call (at least) setupterm() first" errors, as when # running simply `nosetests` (without progressive) on nose- @@ -314,9 +327,9 @@ class ParametrizingString(unicode): class FormattingString(unicode): """A Unicode string which can be called upon a piece of text to wrap it in formatting""" - def __new__(cls, formatting, term): + def __new__(cls, formatting, normal): new = unicode.__new__(cls, formatting) - new._normal = term.normal + new._normal = normal return new def __call__(self, text): |