summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2009-06-16 21:53:17 +0000
committerZac Medico <zmedico@gentoo.org>2009-06-16 21:53:17 +0000
commit9f2484465799cf8dc74850938e3eceb7d54d5b72 (patch)
treeb018835d457f9d080e574a9829b4a3af6870edca
parenta88675dc78ea74f802984cb71ea4fab90a6b375d (diff)
downloadportage-9f2484465799cf8dc74850938e3eceb7d54d5b72.tar.gz
portage-9f2484465799cf8dc74850938e3eceb7d54d5b72.tar.bz2
portage-9f2484465799cf8dc74850938e3eceb7d54d5b72.zip
Bug #274279 - Add color.map support for mapping a color to a different color
(rather than just mapping a class/style to a different color). Thanks to Sebastian Mingramm (few) <s.mingramm@gmx.de> for this patch. svn path=/main/trunk/; revision=13643
-rw-r--r--man/color.map.54
-rw-r--r--pym/portage/__init__.py3
-rw-r--r--pym/portage/output.py296
3 files changed, 152 insertions, 151 deletions
diff --git a/man/color.map.5 b/man/color.map.5
index 9082e7693..9ce76ad26 100644
--- a/man/color.map.5
+++ b/man/color.map.5
@@ -9,9 +9,9 @@ Portage will check this file first for color classes settings. If no setting
of given color class is found in /etc/portage/color.map, Portage uses default
value defined internally.
.SH "SYNTAX"
-\fBVARIABLE\fR = \fI[space delimited list of attributes]\fR
+\fBVARIABLE\fR = \fI[space delimited list of attributes or ansi code pattern]\fR
.TP
-\fBATTRIBUTE\fR = \fI[space delimited list of attributes]\fR
+\fBATTRIBUTE\fR = \fI[space delimited list of attributes or ansi code pattern]\fR
.SH "VARIABLES"
.TP
\fBNORMAL\fR = \fI"normal"\fR
diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py
index 6854eea99..c17072870 100644
--- a/pym/portage/__init__.py
+++ b/pym/portage/__init__.py
@@ -5431,7 +5431,8 @@ def doebuild_environment(myebuild, mydo, myroot, mysettings, debug, use_cache, m
# Allow color.map to control colors associated with einfo, ewarn, etc...
mycolors = []
for c in ("GOOD", "WARN", "BAD", "HILITE", "BRACKET"):
- mycolors.append("%s=$'%s'" % (c, portage.output.codes[c]))
+ mycolors.append("%s=$'%s'" % \
+ (c, portage.output.map_code_to_color_code(c)))
mysettings["PORTAGE_COLORMAP"] = "\n".join(mycolors)
def prepare_build_dirs(myroot, mysettings, cleanup):
diff --git a/pym/portage/output.py b/pym/portage/output.py
index 983cbec60..2096b24be 100644
--- a/pym/portage/output.py
+++ b/pym/portage/output.py
@@ -4,6 +4,7 @@
__docformat__ = "epytext"
+import codecs
import commands
import errno
import formatter
@@ -24,68 +25,47 @@ from portage.exception import CommandNotFound, FileNotFound, \
havecolor=1
dotitles=1
+codes = {}
+color_codes = {}
+
esc_seq = "\x1b["
-g_attr = {}
-g_attr["normal"] = 0
-
-g_attr["bold"] = 1
-g_attr["faint"] = 2
-g_attr["standout"] = 3
-g_attr["underline"] = 4
-g_attr["blink"] = 5
-g_attr["overline"] = 6 # Why is overline actually useful?
-g_attr["reverse"] = 7
-g_attr["invisible"] = 8
-
-g_attr["no-attr"] = 22
-g_attr["no-standout"] = 23
-g_attr["no-underline"] = 24
-g_attr["no-blink"] = 25
-g_attr["no-overline"] = 26
-g_attr["no-reverse"] = 27
-# 28 isn't defined?
-# 29 isn't defined?
-g_attr["black"] = 30
-g_attr["red"] = 31
-g_attr["green"] = 32
-g_attr["yellow"] = 33
-g_attr["blue"] = 34
-g_attr["magenta"] = 35
-g_attr["cyan"] = 36
-g_attr["white"] = 37
-# 38 isn't defined?
-g_attr["default"] = 39
-g_attr["bg_black"] = 40
-g_attr["bg_red"] = 41
-g_attr["bg_green"] = 42
-g_attr["bg_yellow"] = 43
-g_attr["bg_blue"] = 44
-g_attr["bg_magenta"] = 45
-g_attr["bg_cyan"] = 46
-g_attr["bg_white"] = 47
-g_attr["bg_default"] = 49
-
-
-# make_seq("blue", "black", "normal")
+color_codes["normal"] = esc_seq + "0m"
+color_codes["reset"] = esc_seq + "39;49;00m"
+
+color_codes["bold"] = esc_seq + "01m"
+color_codes["faint"] = esc_seq + "02m"
+color_codes["standout"] = esc_seq + "03m"
+color_codes["underline"] = esc_seq + "04m"
+color_codes["blink"] = esc_seq + "05m"
+color_codes["overline"] = esc_seq + "06m"
+color_codes["reverse"] = esc_seq + "07m"
+color_codes["invisible"] = esc_seq + "08m"
+
+color_codes["no-attr"] = esc_seq + "22m"
+color_codes["no-standout"] = esc_seq + "23m"
+color_codes["no-underline"] = esc_seq + "24m"
+color_codes["no-blink"] = esc_seq + "25m"
+color_codes["no-overline"] = esc_seq + "26m"
+color_codes["no-reverse"] = esc_seq + "27m"
+
+color_codes["bg_black"] = esc_seq + "40m"
+color_codes["bg_darkred"] = esc_seq + "41m"
+color_codes["bg_darkgreen"] = esc_seq + "42m"
+color_codes["bg_brown"] = esc_seq + "43m"
+color_codes["bg_darkblue"] = esc_seq + "44m"
+color_codes["bg_purple"] = esc_seq + "45m"
+color_codes["bg_teal"] = esc_seq + "46m"
+color_codes["bg_lightgray"] = esc_seq + "47m"
+color_codes["bg_default"] = esc_seq + "49m"
+color_codes["bg_darkyellow"] = color_codes["bg_brown"]
+
def color(fg, bg="default", attr=["normal"]):
- mystr = esc_seq[:] + "%02d" % g_attr[fg]
+ mystr = color_codes[fg]
for x in [bg]+attr:
- mystr += ";%02d" % g_attr[x]
- return mystr+"m"
-
-
+ mystr += color_codes[x]
+ return mystr
-codes={}
-codes["reset"] = esc_seq + "39;49;00m"
-
-codes["bold"] = esc_seq + "01m"
-codes["faint"] = esc_seq + "02m"
-codes["standout"] = esc_seq + "03m"
-codes["underline"] = esc_seq + "04m"
-codes["blink"] = esc_seq + "05m"
-codes["overline"] = esc_seq + "06m" # Who made this up? Seriously.
-codes["reverse"] = esc_seq + "07m"
ansi_color_codes = []
for x in xrange(30, 38):
@@ -97,76 +77,67 @@ rgb_ansi_colors = ['0x000000', '0x555555', '0xAA0000', '0xFF5555', '0x00AA00',
'0xFF55FF', '0x00AAAA', '0x55FFFF', '0xAAAAAA', '0xFFFFFF']
for x in xrange(len(rgb_ansi_colors)):
- codes[rgb_ansi_colors[x]] = esc_seq + ansi_color_codes[x]
+ color_codes[rgb_ansi_colors[x]] = esc_seq + ansi_color_codes[x]
del x
-codes["black"] = codes["0x000000"]
-codes["darkgray"] = codes["0x555555"]
+color_codes["black"] = color_codes["0x000000"]
+color_codes["darkgray"] = color_codes["0x555555"]
-codes["red"] = codes["0xFF5555"]
-codes["darkred"] = codes["0xAA0000"]
+color_codes["red"] = color_codes["0xFF5555"]
+color_codes["darkred"] = color_codes["0xAA0000"]
-codes["green"] = codes["0x55FF55"]
-codes["darkgreen"] = codes["0x00AA00"]
+color_codes["green"] = color_codes["0x55FF55"]
+color_codes["darkgreen"] = color_codes["0x00AA00"]
-codes["yellow"] = codes["0xFFFF55"]
-codes["brown"] = codes["0xAA5500"]
+color_codes["yellow"] = color_codes["0xFFFF55"]
+color_codes["brown"] = color_codes["0xAA5500"]
-codes["blue"] = codes["0x5555FF"]
-codes["darkblue"] = codes["0x0000AA"]
+color_codes["blue"] = color_codes["0x5555FF"]
+color_codes["darkblue"] = color_codes["0x0000AA"]
-codes["fuchsia"] = codes["0xFF55FF"]
-codes["purple"] = codes["0xAA00AA"]
+color_codes["fuchsia"] = color_codes["0xFF55FF"]
+color_codes["purple"] = color_codes["0xAA00AA"]
-codes["turquoise"] = codes["0x55FFFF"]
-codes["teal"] = codes["0x00AAAA"]
+color_codes["turquoise"] = color_codes["0x55FFFF"]
+color_codes["teal"] = color_codes["0x00AAAA"]
-codes["white"] = codes["0xFFFFFF"]
-codes["lightgray"] = codes["0xAAAAAA"]
+color_codes["white"] = color_codes["0xFFFFFF"]
+color_codes["lightgray"] = color_codes["0xAAAAAA"]
-codes["darkteal"] = codes["turquoise"]
+color_codes["darkteal"] = color_codes["turquoise"]
# Some terminals have darkyellow instead of brown.
-codes["0xAAAA00"] = codes["brown"]
-codes["darkyellow"] = codes["0xAAAA00"]
+color_codes["0xAAAA00"] = color_codes["brown"]
+color_codes["darkyellow"] = color_codes["0xAAAA00"]
-codes["bg_black"] = esc_seq + "40m"
-codes["bg_darkred"] = esc_seq + "41m"
-codes["bg_darkgreen"] = esc_seq + "42m"
-codes["bg_brown"] = esc_seq + "43m"
-codes["bg_darkblue"] = esc_seq + "44m"
-codes["bg_purple"] = esc_seq + "45m"
-codes["bg_teal"] = esc_seq + "46m"
-codes["bg_lightgray"] = esc_seq + "47m"
-codes["bg_darkyellow"] = codes["bg_brown"]
# Colors from /etc/init.d/functions.sh
-codes["NORMAL"] = esc_seq + "0m"
-codes["GOOD"] = codes["green"]
-codes["WARN"] = codes["yellow"]
-codes["BAD"] = codes["red"]
-codes["HILITE"] = codes["teal"]
-codes["BRACKET"] = codes["blue"]
+codes["NORMAL"] = ( "normal", )
+codes["GOOD"] = ( "green", )
+codes["WARN"] = ( "yellow", )
+codes["BAD"] = ( "red", )
+codes["HILITE"] = ( "teal", )
+codes["BRACKET"] = ( "blue", )
# Portage functions
-codes["INFORM"] = codes["darkgreen"]
-codes["UNMERGE_WARN"] = codes["red"]
-codes["SECURITY_WARN"] = codes["red"]
-codes["MERGE_LIST_PROGRESS"] = codes["yellow"]
-codes["PKG_BLOCKER"] = codes["red"]
-codes["PKG_BLOCKER_SATISFIED"] = codes["darkblue"]
-codes["PKG_MERGE"] = codes["darkgreen"]
-codes["PKG_MERGE_SYSTEM"] = codes["darkgreen"]
-codes["PKG_MERGE_WORLD"] = codes["green"]
-codes["PKG_UNINSTALL"] = codes["red"]
-codes["PKG_NOMERGE"] = codes["darkblue"]
-codes["PKG_NOMERGE_SYSTEM"] = codes["darkblue"]
-codes["PKG_NOMERGE_WORLD"] = codes["blue"]
-codes["PROMPT_CHOICE_DEFAULT"] = codes["green"]
-codes["PROMPT_CHOICE_OTHER"] = codes["red"]
-
-def parse_color_map(onerror=None):
+codes["INFORM"] = ( "darkgreen", )
+codes["UNMERGE_WARN"] = ( "red", )
+codes["SECURITY_WARN"] = ( "red", )
+codes["MERGE_LIST_PROGRESS"] = ( "yellow", )
+codes["PKG_BLOCKER"] = ( "red", )
+codes["PKG_BLOCKER_SATISFIED"] = ( "darkblue", )
+codes["PKG_MERGE"] = ( "darkgreen", )
+codes["PKG_MERGE_SYSTEM"] = ( "darkgreen", )
+codes["PKG_MERGE_WORLD"] = ( "green", )
+codes["PKG_UNINSTALL"] = ( "red", )
+codes["PKG_NOMERGE"] = ( "darkblue", )
+codes["PKG_NOMERGE_SYSTEM"] = ( "darkblue", )
+codes["PKG_NOMERGE_WORLD"] = ( "blue", )
+codes["PROMPT_CHOICE_DEFAULT"] = ( "green", )
+codes["PROMPT_CHOICE_OTHER"] = ( "red", )
+
+def _parse_color_map(onerror=None):
"""
Parse /etc/portage/color.map and return a dict of error codes.
@@ -177,32 +148,40 @@ def parse_color_map(onerror=None):
@return: a dictionary mapping color classes to color codes
"""
myfile = COLOR_MAP_FILE
- ansi_code_pattern = re.compile("^[0-9;]*m$")
- def strip_quotes(token, quotes):
+ ansi_code_pattern = re.compile("^[0-9;]*m$")
+ quotes = '\'"'
+ def strip_quotes(token):
if token[0] in quotes and token[0] == token[-1]:
token = token[1:-1]
return token
try:
- s = shlex.shlex(open(myfile))
- s.wordchars = s.wordchars + ";" # for ansi codes
- while True:
- k, o, v = s.get_token(), s.get_token(), s.get_token()
- if k is s.eof:
- break
- if o != "=":
- e = ParseError("%s%s'%s'" % (
- s.error_leader(myfile, s.lineno),
- "expected '=' operator: ", o))
+ lineno=0
+ for line in codecs.open( myfile, mode = 'r', errors = 'replace' ):
+ lineno += 1
+
+ commenter_pos = line.find("#")
+ line = line[:commenter_pos].strip()
+
+ if len(line) == 0:
+ continue
+
+ split_line = line.split("=")
+ if len(split_line) != 2:
+ e = ParseError("'%s', line %s: %s" % (
+ myfile, lineno,
+ "expected exactly one occurence of '=' operator"))
+ raise e
if onerror:
onerror(e)
else:
raise e
continue
- k = strip_quotes(k, s.quotes)
- v = strip_quotes(v, s.quotes)
- if not k in codes:
- e = ParseError("%s%s'%s'" % (
- s.error_leader(myfile, s.lineno),
+
+ k = strip_quotes(split_line[0].strip())
+ v = strip_quotes(split_line[1].strip())
+ if not k in codes and not k in color_codes:
+ e = ParseError("'%s', line %s: %s'%s'" % (
+ myfile, lineno,
"Unknown variable: ", k))
if onerror:
onerror(e)
@@ -210,21 +189,30 @@ def parse_color_map(onerror=None):
raise e
continue
if ansi_code_pattern.match(v):
- codes[k] = esc_seq + v
+ if k in codes:
+ codes[k] = ( esc_seq + v, )
+ elif k in color_codes:
+ color_codes[k] = esc_seq + v
else:
code_list = []
- for x in v.split(" "):
- if x in codes:
- code_list.append(codes[x])
+ for x in v.split():
+ if x in color_codes:
+ if k in codes:
+ code_list.append(x)
+ elif k in color_codes:
+ code_list.append(color_codes[x])
else:
- e = ParseError("%s%s'%s'" % (
- s.error_leader(myfile, s.lineno),
+ e = ParseError("'%s', line %s: %s'%s'" % (
+ myfile, lineno,
"Undefined: ", x))
if onerror:
onerror(e)
else:
raise e
- codes[k] = "".join(code_list)
+ if k in codes:
+ codes[k] = tuple(code_list)
+ elif k in color_codes:
+ color_codes[k] = "".join(code_list)
except (IOError, OSError), e:
if e.errno == errno.ENOENT:
raise FileNotFound(myfile)
@@ -232,17 +220,6 @@ def parse_color_map(onerror=None):
raise PermissionDenied(myfile)
raise
-try:
- parse_color_map(onerror=lambda e: writemsg("%s\n" % str(e), noiselevel=-1))
-except FileNotFound:
- pass
-except PermissionDenied, e:
- writemsg("Permission denied: '%s'\n" % str(e), noiselevel=-1)
- del e
-except PortageException, e:
- writemsg("%s\n" % str(e), noiselevel=-1)
- del e
-
def nc_len(mystr):
tmp = re.sub(esc_seq + "^m]+m", "", mystr);
return len(tmp)
@@ -308,12 +285,24 @@ def nocolor():
havecolor=0
def resetColor():
- return codes["reset"]
+ return color_codes["reset"]
+
+def map_code_to_color_code(code):
+ ret = ""
+ for color_code in codes[code]:
+ # allow stuff that has found it's way through ansi_code_pattern
+ ret += color_codes.get(color_code, color_code)
+ return ret
def colorize(color_key, text):
global havecolor
if havecolor:
- return codes[color_key] + text + codes["reset"]
+ if color_key in color_codes:
+ return color_codes[color_key] + text + color_codes["reset"]
+ elif color_key in codes:
+ return map_code_to_color_code(color_key) + text + color_codes["reset"]
+ else:
+ return text
else:
return text
@@ -350,9 +339,9 @@ class ConsoleStyleFile(object):
global havecolor
if havecolor and self._styles:
for style in self._styles:
- self._file.write(codes[style])
+ self._file.write(color_codes[style])
self._file.write(s)
- self._file.write(codes["reset"])
+ self._file.write(color_codes["reset"])
else:
self._file.write(s)
if self.write_listener:
@@ -715,3 +704,14 @@ class TermProgressBar(ProgressBar):
image = image + "[" + (bar_width * "=") + \
">" + ((max_bar_width - bar_width) * " ") + "]"
return image
+
+try:
+ _parse_color_map(onerror=lambda e: writemsg("%s\n" % str(e), noiselevel=-1))
+except FileNotFound:
+ pass
+except PermissionDenied, e:
+ writemsg("Permission denied: '%s'\n" % str(e), noiselevel=-1)
+ del e
+except PortageException, e:
+ writemsg("%s\n" % str(e), noiselevel=-1)
+ del e