Source code for fin.color


import os
import sys

import fin.string


[docs]class Color(object): """ A simple class for producing pretty terminal output. While :class:`Color` is abstract, :class:`VtColor` provides common VT-100 (xterm) compatible output. This is a very light, small library, and doesn't deal with curses or terminfo. The module global ``C`` is created at import time. If standard out appears to support color output, then this will be an instance of :class:`VtColor`, otherwise, :class:`NoColor`. Typical Usage:: c = fin.color.C print c.blue + "I'm blue, da-ba-dee da-ba-dai" + c.reset print c.red.bold("Color") + c.red.blue("Blind") print c.green("In") + c.bg_green.black("verse") # Note assumes a white-on-black color scheme. """ def __init__(self, parts=()): self.parts = parts def __call__(self, *data): return self + "".join(data) + self.only_reset def __getattr__(self, name): return self[name] def __getitem__(self, name): raise NotImplemented("__getitem__") def __add__(self, other): if isinstance(other, Color): return self.__class__(self.parts + other.parts) return str(self) + other def __radd__(self, other): if isinstance(other, Color): return self.__class__(other.parts + self.parts) return other + str(self) def __str__(self): raise NotImplemented()
[docs]class NoColor(Color): """ A color class for when no color information should be output. For example, if output can be redirected to a terminal OR a log file, NoColor can be transparently swapped in for the VtColor class to ensure that the data in the log file does not include a large number of escape codes. """ def __getitem__(self, name): return self def __str__(self): return ""
[docs]class VtColor(Color): """ The color class for VT-compatible terminals (basically all non-windows terminals). The color attributes may be used in two ways. Getting a color is a matter of referencing the correct attribute:: >>> C.red <fin.color.VtColor at 0x7f904012fb90> This may then be converted to a string, for printing:: >>> str(C.red) '\\x1b[34m' >>> C.red + "foo" + C.reset '\\x1b[31mfoo\\x1b[0m' The alternate syntax is to `call` the color, passing in a string, which implicitly add the color code before the string, and adds a reset afterwards (NOTE: the reset will reset all color information, including any inherited):: >>> C.red("hello") + C.blue("world") '\\x1b[31mhello\\x1b[0m\\x1b[34mworld\\x1b[0m' Printing any of the above in a standard (non-windows) terminal, will result in the correct colored output. The available colors are listed below. All colors may be prefixed with 'bg_', and colors may be combined by further attribute access:: >>> C.bg_blue.white.bold("Bold, white-on-blue text") '\\x1b[44;37;1mBold, white-on-blue text\\x1b[0m' Two special attributes: 'bold', and 'reset' respectively turn the text bold (or use bright colors, depending on console) and reset all color attributes. """ COLORS = ["black", "red", "green", "yellow", "blue", "purple", "cyan", "white"] """ All colors that may be referenced """ FG_BASE = 30 BG_BASE = 40 EXTRA = { "bold": 1, "reset": 0, } """ Non-color attributes """ def _get_value(self, name): name = name.lower() if name in self.EXTRA: return self.EXTRA[name] base = self.FG_BASE bg_name = fin.string.ltrim(name, "bg_", "background_", "b_") if bg_name != name: name = bg_name base = self.BG_BASE try: offset = self.COLORS.index(name) except ValueError: raise AttributeError(name) return base + offset def __getitem__(self, name): current_parts = self.parts only_name = fin.string.ltrim(name, "only_") if only_name != name: name = only_name current_parts = () return VtColor(current_parts + (self._get_value(name), )) def __str__(self): data = ";".join("%i" % p for p in self.parts) return "\x1b[" + data + "m"
KNOWN_TERMINAL_TYPES = set([ "linux", "term", "vt200" ])
[docs]def auto_color(stream=sys.stdin): """ This does some simple tests to determine if the output stream supports colors, returning the corect Color class for the stream. The lookup is intentionally kept simple, as this has proved to capture 99% of cases without adding the burden of more complicated capabilities databases. """ term_name = os.environ.get("TERM", "").lower() if (stream.isatty() and (term_name in KNOWN_TERMINAL_TYPES or "xterm" in term_name)): return VtColor() return NoColor()
C = auto_color() """ An instance of :class:`Color` that is most appropriate for sys.stdout. Typically this will be a VtColor object, but when stdout is redirected to a file, or other non-terminal output then it will revert to NoColor. This constant allows code to simply refer to, for example:: >>> fin.color.C.blue('hi') '\\x1b[34mhi\\x1b[0m' """