173 lines
4.6 KiB
Python
173 lines
4.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
# <Couleur - fancy shell output for python>
|
|
# Copyright (C) <2010> Gabriel Falcão <gabriel@nacaolivre.org>
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Lesser General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import sys
|
|
import uuid
|
|
|
|
__version__ = '0.2'
|
|
|
|
def ansify(number):
|
|
"""Wraps the given ansi code to a proper escaped python output
|
|
|
|
Arguments:
|
|
- `number`: the code in question
|
|
"""
|
|
number = unicode(number)
|
|
return '\033[%sm' % number
|
|
|
|
class modifiers:
|
|
reset = ansify(0)
|
|
bold = ansify(1)
|
|
blink = ansify(5)
|
|
italic = ansify(3)
|
|
underline = ansify(4)
|
|
inverse = ansify(7)
|
|
strikethrough = ansify(9)
|
|
up = '\r\033[A'
|
|
|
|
class forecolors:
|
|
black = ansify(30)
|
|
red = ansify(31)
|
|
green = ansify(32)
|
|
yellow = ansify(33)
|
|
blue = ansify(34)
|
|
magenta = ansify(35)
|
|
cyan = ansify(36)
|
|
white = ansify(37)
|
|
normal = ansify(39)
|
|
|
|
class backcolors:
|
|
black = ansify(40)
|
|
red = ansify(41)
|
|
green = ansify(42)
|
|
yellow = ansify(43)
|
|
blue = ansify(44)
|
|
magenta = ansify(45)
|
|
cyan = ansify(46)
|
|
white = ansify(47)
|
|
normal = ansify(49)
|
|
|
|
class empty(object):
|
|
def __getattr__(self, attr):
|
|
if attr != 'up':
|
|
return ''
|
|
else:
|
|
return modifiers.up
|
|
|
|
_sep1 = '_on_'
|
|
_sep2 = '_and_'
|
|
|
|
class Shell(object):
|
|
def __init__(self, indent=2, linebreak=False, bold=False, disabled=False):
|
|
self._indentation_factor = indent
|
|
self._indent = 0
|
|
self._linebreak = linebreak
|
|
self._bold = bold
|
|
self._in_format = False
|
|
self._disabled = disabled
|
|
self._backcolors = backcolors()
|
|
self._forecolors = forecolors()
|
|
self._modifiers = modifiers()
|
|
if disabled:
|
|
self._backcolors = empty()
|
|
self._forecolors = empty()
|
|
self._modifiers = empty()
|
|
|
|
def indent(self):
|
|
self._indent += self._indentation_factor
|
|
|
|
def dedent(self):
|
|
self._indent -= self._indentation_factor
|
|
|
|
|
|
def _fore(self, color):
|
|
def get(what):
|
|
try:
|
|
r = getattr(self._modifiers, what)
|
|
except AttributeError:
|
|
r = getattr(self._forecolors, what)
|
|
return r
|
|
|
|
args = map(get, color.split("_"))
|
|
return "".join(args)
|
|
|
|
def _back(self, color):
|
|
return getattr(self._backcolors, color)
|
|
|
|
def _printer_for(self, color):
|
|
colors = color.split(_sep1)
|
|
|
|
parts = [
|
|
self._fore(colors.pop(0)),
|
|
"%s",
|
|
self._modifiers.reset
|
|
]
|
|
|
|
if colors:
|
|
parts.insert(0, self._back(colors[0]))
|
|
|
|
if not self._in_format:
|
|
if self._bold:
|
|
parts.insert(0, self._modifiers.bold)
|
|
|
|
if self._indent:
|
|
parts.insert(0, ' ' * self._indent)
|
|
|
|
if self._linebreak:
|
|
parts.append("\n")
|
|
|
|
string = "".join(parts)
|
|
|
|
def dec(z, replace=False):
|
|
pre = (replace and self._modifiers.up or '')
|
|
sys.stdout.write(pre + (string % z))
|
|
|
|
return dec
|
|
|
|
|
|
def __getattr__(self, attr):
|
|
if not attr.startswith("_"):
|
|
if _sep2 in attr:
|
|
self._in_format = True
|
|
printers = map(self._printer_for, attr.split(_sep2))
|
|
def dec(string, replace=False):
|
|
unique = str(uuid.uuid4())
|
|
string = string.replace(r'\|', unique)
|
|
parts = string.split("|")
|
|
if replace:
|
|
sys.stdout.write(self._modifiers.up)
|
|
|
|
if self._indent:
|
|
sys.stdout.write(' ' * self._indent)
|
|
|
|
if self._bold:
|
|
sys.stdout.write(self._modifiers.bold)
|
|
|
|
for part, output in zip(parts, printers):
|
|
output(part.replace(unique, "|"))
|
|
|
|
if self._linebreak:
|
|
sys.stdout.write("\n")
|
|
|
|
self._in_format = False
|
|
|
|
return dec
|
|
|
|
return self._printer_for(attr)
|
|
|
|
return super(Shell, self).__getattribute__(attr)
|