From 460b12658378f5320b081421f31a5dee075c4232 Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Thu, 19 Sep 2013 11:50:39 +0200 Subject: [PATCH 001/116] Better colorization of the linker in the g++ theme --- colout/colout_g++.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/colout/colout_g++.py b/colout/colout_g++.py index d86b9e7..adc3e79 100644 --- a/colout/colout_g++.py +++ b/colout/colout_g++.py @@ -26,16 +26,17 @@ def theme(): enc = locale.getpreferredencoding() if "UTF" in enc: # gcc will use unicode quotes - qo = "‘" - qc = "’" + qo = "[‘`]" + qc = "[’']" else: # rather than ascii ones - qo = "'" + qo = "['`]" qc = "'" return [ [ _("error: "), "red", "bold" ], [ _("warning: "), "magenta", "bold" ], + [ _("undefined reference to "), "red", "bold" ], # [-Wflag] [ "\[-W.*\]", "magenta"], From f7c73833b451a3df74dd92190a7a0e4bf97191fb Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Thu, 19 Sep 2013 14:02:24 +0200 Subject: [PATCH 002/116] Correct small errors in cmake theme Do not use nested groups for "Linking" messages. Allow "-" in file names for "Building" messages. --- colout/colout_cmake.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index d58e6c1..27644f9 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -23,13 +23,13 @@ def theme(): [ "^(Scanning dependencies of target)(.*)$", performing, "normal,bold" ], # Link - [ "^(Linking .* (library|executable) )(.*/)+(.+(\.[aso]+)*)$", + [ "^(Linking .* )(library|executable) (.*/)+(.+(\.[aso]+)*)$", performing, "normal,normal,bold" ], # [percent] Built [ "^\[\s*[0-9]+%\]\s(Built target)(\s.*)$", performed, "normal,bold" ], # [percent] Building - [ "^\[\s*[0-9]+%\]\s(Building \w* object)(\s.*/)(\w+.c.*)(.o)$", + [ "^\[\s*[0-9]+%\]\s(Building \w* object)(\s+.*/)([-\w]+.c.*)(.o)$", performing, "normal,normal,bold,normal"], # make errors [ "make\[[0-9]+\].*", "yellow"], From 94e9d04866e68ba8977cac817bf929a3cb1fcda2 Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Mon, 23 Sep 2013 12:35:41 +0200 Subject: [PATCH 003/116] bugfix in the cmake theme Color the Linking sections with no slash --- colout/colout_cmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index 27644f9..74580b1 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -23,7 +23,7 @@ def theme(): [ "^(Scanning dependencies of target)(.*)$", performing, "normal,bold" ], # Link - [ "^(Linking .* )(library|executable) (.*/)+(.+(\.[aso]+)*)$", + [ "^(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", performing, "normal,normal,bold" ], # [percent] Built [ "^\[\s*[0-9]+%\]\s(Built target)(\s.*)$", From f30838cc57b2ec190a0f5da39bba5f03d39d9208 Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Wed, 25 Sep 2013 00:04:20 +0200 Subject: [PATCH 004/116] Allow big group matching for "scale" special color When matching a group with "scale", filter out everything that does not seem to be necessary to interpret the string as a number this permits to transform "[95%]" to "95" before number conversion, and thus allows to color a group larger than the matched number Update the cmake theme accordingly. --- README.md | 15 ++++++++++++--- colout/colout.py | 15 +++++++++++++-- colout/colout_cmake.py | 9 +++++++-- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 779777b..c6993aa 100644 --- a/README.md +++ b/README.md @@ -35,9 +35,14 @@ the 256 color escape sequences). `Random` will color each matching pattern with a random color among the 255 available in the ANSI table. `random` will do the same in 8 colors mode. -`scale` (8 colors) and `Scale` (36 colors) will parse the matching text as -a decimal number and apply the rainbow colormap according to its position -on the scale defined by the `-l` option (see below, "0,100" by default). +`scale` (8 colors) and `Scale` (36 colors) will parse the numbers characters in +the matching text as a decimal number and apply the rainbow colormap according +to its position on the scale defined by the `-l` option (see below, "0,100" by +default). + +Before interpreting the matched string as a number, colout will remove any +character not supposed to be used to write down numbers. This permits to apply +this special color on a large group, while interpreting only its numerical part. If the python-pygments library is installed, you can use the name of a syntax-coloring "lexer" as a color (for example: "Cpp", "ruby", "xml+django", etc.). @@ -219,6 +224,10 @@ Don't use nested groups or colout will duplicate the corresponding input text wi * Color a source code substring: `echo "There is an error in 'static void Functor::operator()( EOT& indiv ) { return indiv; }' you should fix it" | colout "'(.*)'" Cpp monokai` +* Color the percent of progress part of a CMake's makefile output, with a color + related to the value of the progress (from 0%=blue to 100%=red): + `cmake .. && make | colout "^(\[\s*[0-9]+%\])" Scale` + ### Bash alias diff --git a/colout/colout.py b/colout/colout.py index 70e4b16..fdc523d 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -14,6 +14,7 @@ import math import importlib import logging import signal +import string # set the SIGPIPE handler to kill the program instead of # ending in a write error when a broken pipe occurs @@ -326,11 +327,21 @@ def colorin(text, color="red", style="normal"): colormap_idx = 0 elif color.lower() == "scale": # "scale" or "Scale" + + # filter out everything that does not seem to be necessary to interpret the string as a number + # this permits to transform "[ 95%]" to "95" before number conversion, + # and thus allows to color a group larger than the matched number + chars_in_numbers = "-+.,e" + allowed = string.digits + chars_in_numbers + nb = "".join([i for i in filter(allowed.__contains__, text)]) + + # interpret as decimal try: + # babel is a specialized module import babel.numbers as bn - f = float(bn.parse_decimal(text)) + f = float(bn.parse_decimal(nb)) except ImportError: - f = float(text) + f = float(nb) # if out of scale, do not color if f < scale[0] or f > scale[1]: diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index 74580b1..0a78395 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -5,6 +5,8 @@ def theme(): performing="cyan" # actions performed in green performed="green" + # actions taking an unknown time + untimed="blue" return [ # Configure... @@ -24,16 +26,19 @@ def theme(): performing, "normal,bold" ], # Link [ "^(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", - performing, "normal,normal,bold" ], + untimed, "normal,normal,bold" ], # [percent] Built [ "^\[\s*[0-9]+%\]\s(Built target)(\s.*)$", performed, "normal,bold" ], # [percent] Building [ "^\[\s*[0-9]+%\]\s(Building \w* object)(\s+.*/)([-\w]+.c.*)(.o)$", performing, "normal,normal,bold,normal"], + # [percent] Generating + [ "^\[\s*[0-9]+%\]\s(Generating)(\s+.*)$", + performing, "normal,bold"], # make errors [ "make\[[0-9]+\].*", "yellow"], [ "(make: \*\*\* \[.+\] )(.* [0-9]+)", "red", "normal,bold"], # progress percentage - [ "^\[\s*([0-9]+)%\]","Scale" ] + [ "^(\[\s*[0-9]+%\])","Scale" ] ] From f59b9dfaf12c0ab1ffc4d080b1355b709566c83d Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Thu, 10 Oct 2013 15:55:45 +0200 Subject: [PATCH 005/116] color "fatal error" in red in g++ theme --- colout/colout_g++.py | 1 + 1 file changed, 1 insertion(+) diff --git a/colout/colout_g++.py b/colout/colout_g++.py index adc3e79..179a122 100644 --- a/colout/colout_g++.py +++ b/colout/colout_g++.py @@ -35,6 +35,7 @@ def theme(): return [ [ _("error: "), "red", "bold" ], + [ _("fatal error: "), "red", "bold" ], [ _("warning: "), "magenta", "bold" ], [ _("undefined reference to "), "red", "bold" ], # [-Wflag] From 410aaf16237694b9fc645435620230822a80e3a5 Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Thu, 10 Oct 2013 15:56:24 +0200 Subject: [PATCH 006/116] add the "orange" and "purple" color synonyms --- colout/colout.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index fdc523d..e07d61c 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -138,8 +138,8 @@ styles = { # Available color names in 8-colors mode colors = { - "black": 0, "red": 1, "green": 2, "yellow": 3, "blue": 4, - "magenta": 5, "cyan": 6, "white": 7, "none": -1 + "black": 0, "red": 1, "green": 2, "yellow": 3, "orange":3, "blue": 4, + "magenta": 5, "purple": 5, "cyan": 6, "white": 7, "none": -1 } themes = {} From 2616166f76e5475aa5cfdef4f1f81a677eb13926 Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Thu, 10 Oct 2013 22:17:50 +0200 Subject: [PATCH 007/116] strip the color name before parsing it This permits to use spaces to indent themes. --- colout/colout.py | 1 + 1 file changed, 1 insertion(+) diff --git a/colout/colout.py b/colout/colout.py index e07d61c..fc1982c 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -290,6 +290,7 @@ def colorin(text, color="red", style="normal"): if style in styles: style_code = str(styles[style]) + color = color.strip() if color == "none": # if no color, style cannot be applied if not debug: From 50a77bb22e21847eb03bf9b84e837f7e8c683d60 Mon Sep 17 00:00:00 2001 From: nojhan Date: Thu, 10 Oct 2013 22:18:36 +0200 Subject: [PATCH 008/116] add a theme for python stack traces --- colout/colout_python.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 colout/colout_python.py diff --git a/colout/colout_python.py b/colout/colout_python.py new file mode 100644 index 0000000..7f3d9b0 --- /dev/null +++ b/colout/colout_python.py @@ -0,0 +1,20 @@ + +def theme(): + return [ + # traceback header + ["^Traceback .*$", "blue" ], + # File, line, in + [ + "^\s{2}(File \")(/.*?/)*([^/:]+)(\", line) ([0-9]+)(, in) (.*)$", + "blue, none, white,blue, yellow,blue", + "normal,normal,bold, normal,normal,bold" + ], + # ["^\s{2}File \"(.*)\", line ([0-9]+), in (.*)$", "white,yellow,white", "normal,normal,bold" ], + # Error name + ["^([A-Za-z]*Error):*", "red", "bold" ], + ["^([A-Za-z]*Exception):*", "red", "bold" ], + # any quoted things + ["Error.*['\"](.*)['\"]", "magenta" ], + # python code + ["^\s{4}.*$", "Python", "monokai" ], + ] From 483bb886d7a84eb165a460c1260e0d181ddb9f77 Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 6 Nov 2013 11:23:32 +0100 Subject: [PATCH 009/116] bugfix path match for python theme --- colout/colout_python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/colout/colout_python.py b/colout/colout_python.py index 7f3d9b0..cdbbb3e 100644 --- a/colout/colout_python.py +++ b/colout/colout_python.py @@ -5,7 +5,7 @@ def theme(): ["^Traceback .*$", "blue" ], # File, line, in [ - "^\s{2}(File \")(/.*?/)*([^/:]+)(\", line) ([0-9]+)(, in) (.*)$", + "^\s{2}(File \")(/*.*?/)*([^/:]+)(\", line) ([0-9]+)(, in) (.*)$", "blue, none, white,blue, yellow,blue", "normal,normal,bold, normal,normal,bold" ], From 6c3075eed583bac3a3b660c8a752d777d21b9cbc Mon Sep 17 00:00:00 2001 From: Dimitri Merejkowsky Date: Tue, 7 Jan 2014 09:56:46 +0100 Subject: [PATCH 010/116] README: remove non-ascii characters This prevented setup.py from working on my box --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c6993aa..975f7bc 100644 --- a/README.md +++ b/README.md @@ -206,7 +206,7 @@ Don't use nested groups or colout will duplicate the corresponding input text wi * Color a make output, line numbers in yellow, errors in bold red, warning in magenta, pragma in green and C++ file base names in cyan: `make 2>&1 | colout ':([0-9]+):[0-9]*' yellow normal | colout error | colout warning magenta | colout pragma green normal | colout '/(\w+)*\.(h|cpp)' cyan normal` Or using themes: - `make 2>&³ | colout -t cmake | colout -t g++` + `make 2>&1 | colout -t cmake | colout -t g++` * Color each word in the head of auth.log with a rainbow color map, starting a new colormap at each new line (the beginning of the command is just bash magic to repeat the string "(\\w+)\\W+": From 6092addb10828b0f978bc3a495f78a3e77cd4b96 Mon Sep 17 00:00:00 2001 From: Louis-Kenzo Cahier Date: Thu, 16 Jan 2014 10:46:40 +0100 Subject: [PATCH 011/116] Handle Unicode decode errors by continuing to process Used to result in an uncaught exception. --- colout/colout.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/colout/colout.py b/colout/colout.py index fdc523d..6548caa 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -567,6 +567,8 @@ def map_write( stream_in, stream_out, function, *args ): while True: try: item = stream_in.readline() + except UnicodeDecodeError: + continue except KeyboardInterrupt: break if not item: From 185be07c809c87f2829b874db72b0a245ada9a91 Mon Sep 17 00:00:00 2001 From: Louis-Kenzo Furuya Cahier Date: Sat, 7 Dec 2013 22:53:14 +0100 Subject: [PATCH 012/116] Add Hash special coloring mode The Hash coloring mode computes a hash for a matched string segment, and always associates the same color with the same string, yet varies colors with even small changes. --- colout/colout.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/colout/colout.py b/colout/colout.py index fdc523d..449b0e6 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -15,6 +15,8 @@ import importlib import logging import signal import string +import hashlib +import functools # set the SIGPIPE handler to kill the program instead of # ending in a write error when a broken pipe occurs @@ -364,6 +366,31 @@ def colorin(text, color="red", style="normal"): color = cmap[i] color_code = str(color) + # "hash" or "Hash"; useful to randomly but consistently color strings + elif color.lower() == "hash": + hasher = hashlib.md5() + hasher.update(text.encode('utf-8')) + hash = hasher.hexdigest() + + f = float(functools.reduce(lambda x, y: x+ord(y), hash, 0) % 101) + + if color[0].islower(): + mode = 8 + cmap = colormaps["rainbow"] + + # normalize and scale over the nb of colors in cmap + i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(cmap)-1) ) ) + + color = cmap[i] + color_code = str(30 + colors[color]) + + else: + mode = 256 + cmap = colormaps["Rainbow"] + i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(cmap)-1) ) ) + color = cmap[i] + color_code = str(color) + # Really useful only when using colout as a library # thus you can change the "colormap" variable to your favorite one before calling colorin elif color == "colormap": @@ -801,7 +828,7 @@ if __name__ == "__main__": print("Available resources:") print("STYLES: %s" % ", ".join(styles) ) print("COLORS: %s" % ", ".join(colors) ) - print("SPECIAL: %s" % ", ".join(["random", "Random", "scale", "Scale", "colormap"]) ) + print("SPECIAL: %s" % ", ".join(["random", "Random", "scale", "Scale", "hash", "Hash", "colormap"]) ) if len(themes) > 0: print("THEMES: %s" % ", ".join(themes.keys()) ) From 2231cd89bd15aaf8714f3bd060a552e619fb02ef Mon Sep 17 00:00:00 2001 From: nojhan Date: Sun, 2 Feb 2014 17:39:28 +0100 Subject: [PATCH 013/116] Add a mandatory argument to --resources. It should be use at least with an "all" argument. Partially fix #49 --- README.md | 10 +++++----- colout/colout.py | 52 +++++++++++++++++++++++++++++++----------------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 975f7bc..fecc9ef 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ colout(1) -- Color Up Arbitrary Command Output ## SYNOPSIS -`colout` [-h] [-r] +`colout` [-h] [-r RESOURCE] `colout` [-g] [-c] [-l] [-a] [-t] [-T] [-P] [-s] PATTERN [COLOR(S) [STYLE(S)]] @@ -125,10 +125,10 @@ Gentoo * `-P DIR`, `--palettes-dir DIR`: Search for additional palettes (*.gpl files) in this directory. -* `-r`, `--resources`: - Print the names of all available colors, styles, themes and palettes. - A bug currently made it mandatory to use an additional dummy argument to this option - to make it work correctly, use `-r x`. +* `-r TYPE(S)`, `--resources TYPE(S)`: + Print the names of available resources. Use a comma-separated list of resources names + (styles, colors, special, themes, palettes, colormaps or lexers), + use 'all' to print everything. * `-s`, `--source`: Interpret PATTERN as source code readable by the Pygments library. If the first letter of PATTERN diff --git a/colout/colout.py b/colout/colout.py index dffd223..644ef84 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -710,7 +710,7 @@ def __args_parse__(argv, usage=""): parser.add_argument("-c", "--colormap", action="store_true", help="Use the given colors as a colormap (cycle the colors at each match)") - parser.add_argument("-l", "--scale", + parser.add_argument("-l", "--scale", metavar="SCALE", help="When using the 'scale' colormap, parse matches as decimal numbers (taking your locale into account) \ and apply the rainbow colormap linearly between the given SCALE=min,max") @@ -728,8 +728,14 @@ def __args_parse__(argv, usage=""): parser.add_argument("-P", "--palettes-dir", metavar="DIR", action="append", help="Search for additional palettes (*.gpl files) in this directory") + # This normally should be an option with an argument, but this would end in an error, + # as no regexp is supposed to be passed after calling this option, + # we use it as the argument to this option. + # The only drawback is that the help message lacks a metavar... parser.add_argument("-r", "--resources", action="store_true", - help="Print the names of all available colors, styles, themes and palettes.") + help="Print the names of available resources. Use a comma-separated list of resources names \ + (styles, colors, special, themes, palettes, colormaps or lexers), \ + use 'all' to print everything.") parser.add_argument("--debug", action="store_true", help="Debug mode: print what's going on internally, useful if you want to check what features are available.") @@ -827,25 +833,35 @@ if __name__ == "__main__": sys.exit( error_codes["DuplicatedPalette"] ) if resources: - print("Available resources:") - print("STYLES: %s" % ", ".join(styles) ) - print("COLORS: %s" % ", ".join(colors) ) - print("SPECIAL: %s" % ", ".join(["random", "Random", "scale", "Scale", "hash", "Hash", "colormap"]) ) + asked=[r.lower() for r in pattern.split(",")] + # print("Available resources:") + for res in asked: + if "style" in res or "all" in res: + print("STYLES: %s" % ", ".join(styles) ) - if len(themes) > 0: - print("THEMES: %s" % ", ".join(themes.keys()) ) - else: - print("NO THEME") + if "color" in res or "all" in res: + print("COLORS: %s" % ", ".join(colors) ) - if len(colormaps) > 0: - print("COLORMAPS: %s" % ", ".join(colormaps) ) - else: - print("NO COLORMAPS") + if "special" in res or "all" in res: + print("SPECIAL: %s" % ", ".join(["random", "Random", "scale", "Scale", "hash", "Hash", "colormap"]) ) - if len(lexers) > 0: - print("LEXERS: %s" % ", ".join(lexers) ) - else: - print("NO LEXER") + if "theme" in res or "all" in res: + if len(themes) > 0: + print("THEMES: %s" % ", ".join(themes.keys()) ) + else: + print("NO THEME") + + if "colormap" in res or "all" in res: + if len(colormaps) > 0: + print("COLORMAPS: %s" % ", ".join(colormaps) ) + else: + print("NO COLORMAPS") + + if "lexer" in res or "all" in res: + if len(lexers) > 0: + print("LEXERS: %s" % ", ".join(lexers) ) + else: + print("NO LEXER") sys.exit(0) # not an error, we asked for help From b9176eab52112748d1f73d5c3d99b70656799023 Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 10 Feb 2014 10:56:16 +0100 Subject: [PATCH 014/116] Color the g++ command line call Useful when your build system shows the commad line. For example, set VERBOSE=1 with make. --- colout/colout_g++.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/colout/colout_g++.py b/colout/colout_g++.py index 179a122..17f9952 100644 --- a/colout/colout_g++.py +++ b/colout/colout_g++.py @@ -34,6 +34,19 @@ def theme(): qc = "'" return [ + # Command line + [ "[/\s]([cg]\+\+-*[0-9]*\.*[0-9]*)", "white", "bold" ], + [ "\s(\-D)(\s*[^\s]+\s)", "none,green", "normal,bold" ], + [ "\s-g\s", "green", "normal" ], + [ "\s-O[0-4]*\s", "green", "normal" ], + [ "\s-[Wf][^\s]*", "magenta", "normal" ], + [ "\s(-I)(/*[^\s]+/)([^/\s]+)", "none,blue", "normal,normal,bold" ], + [ "\s(-L)(/*[^\s]+/)([^/\s]+)", "none,cyan", "normal,normal,bold" ], + [ "\s(-l)([^/\s]+)", "none,cyan", "normal,bold" ], + [ "\s-[oc]", "red", "bold" ], + [ "\s(-+std)=*([^s]+)", "red", "normal,bold" ], + + # Important messages [ _("error: "), "red", "bold" ], [ _("fatal error: "), "red", "bold" ], [ _("warning: "), "magenta", "bold" ], From 796246e78945864db92b3861e48e01d84c887d95 Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 10 Feb 2014 21:05:21 +0100 Subject: [PATCH 015/116] Dynamic warning if babel or pygments are not installed --- README.md | 4 ++-- colout/colout.py | 26 +++++++++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c6993aa..00b2eb3 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Before interpreting the matched string as a number, colout will remove any character not supposed to be used to write down numbers. This permits to apply this special color on a large group, while interpreting only its numerical part. -If the python-pygments library is installed, you can use the name of a +If the python3-pygments library is installed, you can use the name of a syntax-coloring "lexer" as a color (for example: "Cpp", "ruby", "xml+django", etc.). If GIMP palettes files (*.gpl) are available, you can also use their names as a @@ -58,7 +58,7 @@ When not specified, a *COLOR* defaults to _red_ and a *STYLE* defaults to _bold_ `colout` comes with some predefined themes to rapidly color well-known outputs (see the `-t` switch below). -If the python-pygments library is available, `colout` can be used as an interface +If the python3-pygments library is available, `colout` can be used as an interface to it (see also the `-s` switch below). To have a list of all colors, styles, special colormaps, themes, palettes and lexers, diff --git a/colout/colout.py b/colout/colout.py index fc1982c..6cebf88 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -666,10 +666,17 @@ def __args_parse__(argv, usage=""): parser.add_argument("pattern", metavar="REGEX", type=str, nargs=1, help="A regular expression") + pygments_warn=" You can also use a language name to activate syntax coloring (see `-r all` for a list)." + try: + import pygments + except ImportError: + pygments_warn=" (WARNING: python3-pygments is not available, \ + install it if you want to be able to use syntax coloring)" + parser.add_argument("color", metavar="COLOR", type=str, nargs='?', default="red", help="A number in [0…255], a color name, a colormap name, \ - a palette or a comma-separated list of those values.") + a palette or a comma-separated list of those values."+pygments_warn) parser.add_argument("style", metavar="STYLE", type=str, nargs='?', default="bold", @@ -682,9 +689,18 @@ def __args_parse__(argv, usage=""): parser.add_argument("-c", "--colormap", action="store_true", help="Use the given colors as a colormap (cycle the colors at each match)") + + babel_warn=" (numbers will be parsed according to your locale)" + try: + # babel is a specialized module + import babel.numbers + except ImportError: + babel_warn=" (WARNING: python3-babel is not available, install it \ + if you want to be able to parse numbers according to your locale)" + parser.add_argument("-l", "--scale", - help="When using the 'scale' colormap, parse matches as decimal numbers (taking your locale into account) \ - and apply the rainbow colormap linearly between the given SCALE=min,max") + help="When using the 'scale' colormap, parse matches as decimal numbers \ + and apply the rainbow colormap linearly between the given SCALE=min,max" + babel_warn) parser.add_argument("-a", "--all", action="store_true", help="Color the whole input at once instead of line per line \ @@ -815,9 +831,9 @@ if __name__ == "__main__": print("NO COLORMAPS") if len(lexers) > 0: - print("LEXERS: %s" % ", ".join(lexers) ) + print("SYNTAX COLORING: %s" % ", ".join(lexers) ) else: - print("NO LEXER") + print("NO SYNTAX COLORING (check that python3-pygments is installed)") sys.exit(0) # not an error, we asked for help From 488c2a2f8894746b38b4011bb0b3c4443c80dc4c Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 10 Feb 2014 21:16:28 +0100 Subject: [PATCH 016/116] Better help messages --- colout/colout.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 4591271..dc144ba 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -695,7 +695,7 @@ def __args_parse__(argv, usage=""): parser.add_argument("pattern", metavar="REGEX", type=str, nargs=1, help="A regular expression") - pygments_warn=" You can also use a language name to activate syntax coloring (see `-r all` for a list)." + pygments_warn=" You can use a language name to activate syntax coloring (see `-r all` for a list)." try: import pygments except ImportError: @@ -705,14 +705,14 @@ def __args_parse__(argv, usage=""): parser.add_argument("color", metavar="COLOR", type=str, nargs='?', default="red", help="A number in [0…255], a color name, a colormap name, \ - a palette or a comma-separated list of those values."+pygments_warn) + a palette or a comma-separated list of those values." + pygments_warn) parser.add_argument("style", metavar="STYLE", type=str, nargs='?', default="bold", help="One of the available styles or a comma-separated list of styles.") parser.add_argument("-g", "--groups", action="store_true", - help="For color maps (random, rainbow), iterate over matching groups \ + help="For color maps (random, rainbow, etc.), iterate over matching groups \ in the pattern instead of over patterns") parser.add_argument("-c", "--colormap", action="store_true", @@ -739,10 +739,10 @@ def __args_parse__(argv, usage=""): help="Interpret REGEX as a theme.") parser.add_argument("-T", "--themes-dir", metavar="DIR", action="append", - help="Search for additional themes (colout_*.py files) in this directory") + help="Search for additional themes (colout_*.py files) in the given directory") parser.add_argument("-P", "--palettes-dir", metavar="DIR", action="append", - help="Search for additional palettes (*.gpl files) in this directory") + help="Search for additional palettes (*.gpl files) in the given directory") # This normally should be an option with an argument, but this would end in an error, # as no regexp is supposed to be passed after calling this option, @@ -753,14 +753,14 @@ def __args_parse__(argv, usage=""): (styles, colors, special, themes, palettes, colormaps or lexers), \ use 'all' to print everything.") - parser.add_argument("--debug", action="store_true", - help="Debug mode: print what's going on internally, useful if you want to check what features are available.") - parser.add_argument("-s", "--source", action="store_true", help="Interpret REGEX as a source code readable by the Pygments library. \ - If the first letter of PATTERN is upper case, use the 256 colors mode, \ - if it is lower case, use the 8 colors mode. \ - Interpret COLOR as a Pygments style.") + If the first letter of PATTERN is upper case, use the 256 colors mode, \ + if it is lower case, use the 8 colors mode. \ + Interpret COLOR as a Pygments style." + pygments_warn) + + parser.add_argument("--debug", action="store_true", + help="Debug mode: print what's going on internally, useful if you want to check what features are available.") args = parser.parse_args() From 3def9779a4718a00706ed41553dc50313284a6d7 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 21 Feb 2014 11:01:40 +0100 Subject: [PATCH 017/116] Add a theme for java --- colout/colout_java.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 colout/colout_java.py diff --git a/colout/colout_java.py b/colout/colout_java.py new file mode 100644 index 0000000..c8fbfb4 --- /dev/null +++ b/colout/colout_java.py @@ -0,0 +1,15 @@ +#encoding: utf-8 + +def theme(): + style="monokai" + return [ + [ "^(.*\.java):([0-9]+):\s*(warning:.*)$", "white,yellow,magenta", "normal,normal,bold" ], + [ "^(.*\.java):([0-9]+):(.*)$", "white,yellow,red", "normal,normal,bold" ], + [ "^(symbol|location)\s*:\s*(.*)$", "blue,Java", "bold,"+style ], + [ "^(found)\s*:\s*(.*)", "red,Java", "bold,"+style ], + [ "^(required)\s*:\s*(.*)", "green,Java", "bold,"+style ], + [ "^\s*\^$", "cyan", "bold" ], + [ "^\s+.*$", "Java", style ], + [ "[0-9]+ error[s]*", "red", "bold" ], + [ "[0-9]+ warning[s]*", "magenta", "bold" ], + ] From 230f1909bcc109f4cd47f64a880b169a3c79e1b0 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 21 Feb 2014 14:51:15 +0100 Subject: [PATCH 018/116] Rename java theme as javac --- colout/{colout_java.py => colout_javac.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename colout/{colout_java.py => colout_javac.py} (100%) diff --git a/colout/colout_java.py b/colout/colout_javac.py similarity index 100% rename from colout/colout_java.py rename to colout/colout_javac.py From 7d589a68babd6428868d586e1cd51a9371581f9f Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 14 Mar 2014 21:28:03 +0100 Subject: [PATCH 019/116] Adds a LaTeX theme --- colout/colout_latex.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 colout/colout_latex.py diff --git a/colout/colout_latex.py b/colout/colout_latex.py new file mode 100644 index 0000000..dbd96b5 --- /dev/null +++ b/colout/colout_latex.py @@ -0,0 +1,26 @@ + +def theme(): + return [ + # LaTeX + ["This is .*TeX.*$", "white", "bold"], + ["(LaTeX Warning): (.*) `(.*)' on page [0-9] (.*) on input line [0-9]+.$", + "magenta,magenta,white,magenta", "normal,bold,normal" ], + ["(LaTeX Warning): (.*)", "magenta", "normal,bold" ], + # ["on (page [0-9]+)", "yellow", "normal" ], + ["on input (line [0-9]+)", "yellow", "normal" ], + ["^! .*$", "red", "bold"], + ["(.*erfull) ([^\s]+).* in [^\s]+ at (lines [0-9]+--[0-9]+)", + "magenta,magenta,yellow", "normal"], + ["\\[^\s]+\s", "white", "bold"], + ["^l\.([0-9]+) ", "yellow"], + ["(Output written on) (.*) \(([0-9]+ pages), [0-9]+ bytes\).", + "blue,white,blue", "normal,bold,normal"], + ["WARNING.*", "magenta", "normal"], + ["warning.*", "magenta", "normal"], + + # BiBTeX + ["^(I couldn't) (.*)", "red", "normal,bold"], + ["(I found) no (.*)", "red"], + ["^---(line [0-9]+) of file (.*)", "yellow,white", "normal"], + ] + From 127b01e6f5093b784eb9ac987a514d5610d49c40 Mon Sep 17 00:00:00 2001 From: Philippe Daouadi Date: Thu, 3 Apr 2014 16:02:57 +0200 Subject: [PATCH 020/116] Make cmake coloring work with Ninja --- colout/colout.py | 33 +++++++++++++++++++++++++++++++++ colout/colout_cmake.py | 17 +++++++++++------ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index dc144ba..5c12aaf 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -367,6 +367,39 @@ def colorin(text, color="red", style="normal"): color = cmap[i] color_code = str(color) + elif color.lower() == "fraction": # "fraction" or "Fraction" + + # get the different numbers in a list + nbs = re.split(r'[^0-9+.,e-]+', text) + nbs = [nb for nb in nbs if nb] + + # interpret as decimal + try: + f = float(nbs[0])/float(nbs[1]) + except Exception as e: + return text + + # if out of scale, do not color + if f < 0 or f > 1: + return text + + if color[0].islower(): + mode = 8 + cmap = colormaps["spectrum"] + + # normalize and scale over the nb of colors in cmap + i = int( math.ceil( f * (len(cmap)-1) ) ) + + color = cmap[i] + color_code = str(30 + colors[color]) + + else: + mode = 256 + cmap = colormaps["Spectrum"] + i = int( math.ceil( f * (len(cmap)-1) ) ) + color = cmap[i] + color_code = str(color) + # "hash" or "Hash"; useful to randomly but consistently color strings elif color.lower() == "hash": hasher = hashlib.md5() diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index 0a78395..5ce9dec 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -24,21 +24,26 @@ def theme(): # Scan [ "^(Scanning dependencies of target)(.*)$", performing, "normal,bold" ], - # Link + # Link (make) [ "^(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", untimed, "normal,normal,bold" ], + # Link (ninja) + [ "^\[[0-9/]+\]\s?(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", + untimed, "normal,normal,bold" ], # [percent] Built - [ "^\[\s*[0-9]+%\]\s(Built target)(\s.*)$", + [ "^\[\s*[0-9/]+%?\]\s(Built target)(\s.*)$", performed, "normal,bold" ], # [percent] Building - [ "^\[\s*[0-9]+%\]\s(Building \w* object)(\s+.*/)([-\w]+.c.*)(.o)$", + [ "^\[\s*[0-9/]+%?\]\s(Building \w* object)(\s+.*/)([-\w]+.c.*)(.o)$", performing, "normal,normal,bold,normal"], # [percent] Generating - [ "^\[\s*[0-9]+%\]\s(Generating)(\s+.*)$", + [ "^\[\s*[0-9/]+%?\]\s(Generating)(\s+.*)$", performing, "normal,bold"], # make errors [ "make\[[0-9]+\].*", "yellow"], [ "(make: \*\*\* \[.+\] )(.* [0-9]+)", "red", "normal,bold"], - # progress percentage - [ "^(\[\s*[0-9]+%\])","Scale" ] + # progress percentage (make) + [ "^(\[\s*[0-9]+%\])","Scale" ], + # progress percentage (ninja) + [ "^(\[[0-9]+/[0-9]+\])","Fraction" ] ] From bdc90eb6c51f3f3dcf73dd9e1346104079800b2c Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 7 Apr 2014 09:59:26 +0200 Subject: [PATCH 021/116] Replace the "Fraction" special by a string evaluation Fractions are interpreted automagically, without the need to indicate a special. This is thus a valid call: `echo "[1/3-0.1%]" | colout -l 0,1 "^\[.*%\]$" Scale` --- colout/colout.py | 52 ++++++++++++++++-------------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 5c12aaf..4fb2a88 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -300,6 +300,7 @@ def colorin(text, color="red", style="normal"): else: return ""+text+"" + elif color == "random": mode = 8 color_code = random.choice(list(colors.values())) @@ -310,6 +311,7 @@ def colorin(text, color="red", style="normal"): color_nb = random.randint(0, 255) color_code = str(color_nb) + elif color in colormaps.keys(): if color[0].islower(): # lower case first letter mode = 8 @@ -329,22 +331,33 @@ def colorin(text, color="red", style="normal"): else: colormap_idx = 0 + elif color.lower() == "scale": # "scale" or "Scale" # filter out everything that does not seem to be necessary to interpret the string as a number # this permits to transform "[ 95%]" to "95" before number conversion, # and thus allows to color a group larger than the matched number - chars_in_numbers = "-+.,e" + chars_in_numbers = "-+.,e/*" allowed = string.digits + chars_in_numbers nb = "".join([i for i in filter(allowed.__contains__, text)]) # interpret as decimal + # First, try with the babel module, if available + # if not, use python itself, + # if thoses fails, try to `eval` the string + # (this allow strings like "1/2+0.9*2") try: # babel is a specialized module import babel.numbers as bn - f = float(bn.parse_decimal(nb)) + try: + f = float(bn.parse_decimal(nb)) + except NumberFormatError: + f = eval(nb) # Note: in python2, `eval(2/3)` would produce `0`, in python3 `0.666` except ImportError: - f = float(nb) + try: + f = float(nb) + except ValueError: + f = eval(nb) # if out of scale, do not color if f < scale[0] or f > scale[1]: @@ -367,38 +380,6 @@ def colorin(text, color="red", style="normal"): color = cmap[i] color_code = str(color) - elif color.lower() == "fraction": # "fraction" or "Fraction" - - # get the different numbers in a list - nbs = re.split(r'[^0-9+.,e-]+', text) - nbs = [nb for nb in nbs if nb] - - # interpret as decimal - try: - f = float(nbs[0])/float(nbs[1]) - except Exception as e: - return text - - # if out of scale, do not color - if f < 0 or f > 1: - return text - - if color[0].islower(): - mode = 8 - cmap = colormaps["spectrum"] - - # normalize and scale over the nb of colors in cmap - i = int( math.ceil( f * (len(cmap)-1) ) ) - - color = cmap[i] - color_code = str(30 + colors[color]) - - else: - mode = 256 - cmap = colormaps["Spectrum"] - i = int( math.ceil( f * (len(cmap)-1) ) ) - color = cmap[i] - color_code = str(color) # "hash" or "Hash"; useful to randomly but consistently color strings elif color.lower() == "hash": @@ -425,6 +406,7 @@ def colorin(text, color="red", style="normal"): color = cmap[i] color_code = str(color) + # Really useful only when using colout as a library # thus you can change the "colormap" variable to your favorite one before calling colorin elif color == "colormap": From d6452a6246bc145867f170378a4c25b31fd36f97 Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 7 Apr 2014 10:12:39 +0200 Subject: [PATCH 022/116] Sort ressources before printing them --- colout/colout.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 4fb2a88..d774a9d 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -865,32 +865,44 @@ if __name__ == "__main__": if resources: asked=[r.lower() for r in pattern.split(",")] + + def join_sort( l ): + """ + Sort the given list in lexicographical order, + with upper-cases first, then lower cases + join the list with a comma. + + >>> join_sort(["a","B","A","b"]) + 'A, a, B, b' + """ + return ", ".join(sorted(l, key=lambda s: s.lower()+s)) + # print("Available resources:") for res in asked: if "style" in res or "all" in res: - print("STYLES: %s" % ", ".join(styles) ) + print("STYLES: %s" % join_sort(styles) ) if "color" in res or "all" in res: - print("COLORS: %s" % ", ".join(colors) ) + print("COLORS: %s" % join_sort(colors) ) if "special" in res or "all" in res: - print("SPECIAL: %s" % ", ".join(["random", "Random", "scale", "Scale", "hash", "Hash", "colormap"]) ) + print("SPECIAL: %s" % join_sort(["random", "Random", "scale", "Scale", "hash", "Hash", "colormap"]) ) if "theme" in res or "all" in res: if len(themes) > 0: - print("THEMES: %s" % ", ".join(themes.keys()) ) + print("THEMES: %s" % join_sort(themes.keys()) ) else: print("NO THEME") if "colormap" in res or "all" in res: if len(colormaps) > 0: - print("COLORMAPS: %s" % ", ".join(colormaps) ) + print("COLORMAPS: %s" % join_sort(colormaps) ) else: print("NO COLORMAPS") if "lexer" in res or "all" in res: if len(lexers) > 0: - print("SYNTAX COLORING: %s" % ", ".join(lexers) ) + print("SYNTAX COLORING: %s" % join_sort(lexers) ) else: print("NO SYNTAX COLORING (check that python3-pygments is installed)") From 3e0535db25b78fdc3d826b7e8d6126d09615671d Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 7 Apr 2014 11:40:13 +0200 Subject: [PATCH 023/116] Adds default colormaps and update README And bugfix: --debug in 256-colors mode --- README.md | 45 +++++++++++++++++++++++++++++++++------------ colout/colout.py | 41 ++++++++++++++++++++++++++++++----------- 2 files changed, 63 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 6dcf55a..80ac984 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ colout(1) -- Color Up Arbitrary Command Output `colout` [-h] [-r RESOURCE] -`colout` [-g] [-c] [-l] [-a] [-t] [-T] [-P] [-s] PATTERN [COLOR(S) [STYLE(S)]] +`colout` [-g] [-c] [-l min,max] [-a] [-t] [-T DIR] [-P DIR] [-d COLORMAP] [-s] [--debug] PATTERN [COLOR(S) [STYLE(S)]] ## DESCRIPTION @@ -21,25 +21,32 @@ If you ask for fewer colors, the last one will be duplicated across remaining groups. Available colors are: blue, black, yellow, cyan, green, magenta, white, red, -rainbow, random, Random, scale, none, an RGB hexadecimal triplet or any number -between 0 and 255. +rainbow, random, Random, Spectrum, spectrum, scale, Scale, hash, Hash, none, an +RGB hexadecimal triplet or any number between 0 and 255. Available styles are: normal, bold, faint, italic, underline, blink, -rapid_blink, reverse, conceal or random (some styles may have no effect, depending +rapid\_blink, reverse, conceal or random (some styles may have no effect, depending on your terminal). -`rainbow` will cycle over a 8 colors rainbow at each matching pattern. +`rainbow` will cycle over a 6 colors rainbow at each matching pattern. `Rainbow` will do the same over 24 colors (this requires a terminal that supports the 256 color escape sequences). `Random` will color each matching pattern with a random color among the 255 available in the ANSI table. `random` will do the same in 8 colors mode. -`scale` (8 colors) and `Scale` (36 colors) will parse the numbers characters in -the matching text as a decimal number and apply the rainbow colormap according +`spectrum` and `Spectrum` are like rainbows, but with more colors (8 and 36 +colors). + +`scale` (8 colors) and `Scale` (256 colors) will parse the numbers characters in +the matching text as a decimal number and apply the default colormap according to its position on the scale defined by the `-l` option (see below, "0,100" by default). +`hash` (8 colors) and `Hash` (256 colors) will take a fingerprint of the matching +text and apply the default colormap according to it. This ensure that matching +texts appearing several times will always get the same color. + Before interpreting the matched string as a number, colout will remove any character not supposed to be used to write down numbers. This permits to apply this special color on a large group, while interpreting only its numerical part. @@ -47,7 +54,7 @@ this special color on a large group, while interpreting only its numerical part. If the python3-pygments library is installed, you can use the name of a syntax-coloring "lexer" as a color (for example: "Cpp", "ruby", "xml+django", etc.). -If GIMP palettes files (*.gpl) are available, you can also use their names as a +If GIMP palettes files (\*.gpl) are available, you can also use their names as a colormap (see the `-P` switch below). Note that the RGB colors (either the hex triplets or the palettes's colors) will @@ -120,10 +127,17 @@ Gentoo Interpret PATTERN as a predefined theme (perm, cmake, g++, etc.). * `-T DIR`, `--themes-dir DIR`: - Search for additional themes (colout_*.py files) in this directory. + Search for additional themes (colout\_\*.py files) in this directory. * `-P DIR`, `--palettes-dir DIR`: - Search for additional palettes (*.gpl files) in this directory. + Search for additional palettes (\*.gpl files) in this directory. + +* `-d COLORMAP`, `--default COLORMAP`: + When using special colormaps (`scale` or `hash`), use this COLORMAP instead of the `spectrum` one. + This can be either one of the available colormaps or a comma-separated list of colors. + WARNING: be sure to specify a default colormap that is compatible with the special colormap's mode. + For instance, if you indicate `scale`, you can use `-d red,green,blue`, but `-d 12,13,14` will fail. + Also, if you specify `Scale`, you cannot use `-d red,green,blue`, but `-d Rainbow` will work. * `-r TYPE(S)`, `--resources TYPE(S)`: Print the names of available resources. Use a comma-separated list of resources names @@ -160,7 +174,11 @@ Recommended packages: ## LIMITATIONS -Don't use nested groups or colout will duplicate the corresponding input text with each matching colors. +Don't use nested groups or colout will duplicate the corresponding input text +with each matching colors. + +Using a default colormap that is incompatible with the special colormap's mode +will end badly. ## EXAMPLES @@ -228,11 +246,14 @@ Don't use nested groups or colout will duplicate the corresponding input text wi related to the value of the progress (from 0%=blue to 100%=red): `cmake .. && make | colout "^(\[\s*[0-9]+%\])" Scale` +* Color hosts and users in `auth.log`, with consistent colors: + `cat /var/log/auth.log | colout "^(\S+\s+){3}(\S+)\s(\S+\s+){3}(\S+)\s+(\S+\s+){2}(\S+)\s*" none,hash,none,hash,none,hash` + ### Bash alias The following bash function color the output of any command with the -cmake and g77 themes: +cmake and g++ themes: function cm() { diff --git a/colout/colout.py b/colout/colout.py index d774a9d..8ac771b 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -365,7 +365,8 @@ def colorin(text, color="red", style="normal"): if color[0].islower(): mode = 8 - cmap = colormaps["spectrum"] + # Use the default colormap in lower case = 8-colors mode + cmap = colormap # normalize and scale over the nb of colors in cmap i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(cmap)-1) ) ) @@ -375,7 +376,7 @@ def colorin(text, color="red", style="normal"): else: mode = 256 - cmap = colormaps["Spectrum"] + cmap = colormap i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(cmap)-1) ) ) color = cmap[i] color_code = str(color) @@ -391,7 +392,7 @@ def colorin(text, color="red", style="normal"): if color[0].islower(): mode = 8 - cmap = colormaps["rainbow"] + cmap = colormap # normalize and scale over the nb of colors in cmap i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(cmap)-1) ) ) @@ -401,7 +402,7 @@ def colorin(text, color="red", style="normal"): else: mode = 256 - cmap = colormaps["Rainbow"] + cmap = colormap i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(cmap)-1) ) ) color = cmap[i] color_code = str(color) @@ -472,7 +473,7 @@ def colorin(text, color="red", style="normal"): if not debug: return start + style_code + endmarks[mode] + color_code + "m" + text + stop else: - return start + style_code + endmarks[mode] + color_code + "m<" + color + ">" + text + "" + stop + return start + style_code + endmarks[mode] + color_code + "m<" + str(color) + ">" + text + "" + stop def colorout(text, match, prev_end, color="red", style="normal", group=0): @@ -731,7 +732,8 @@ def __args_parse__(argv, usage=""): in the pattern instead of over patterns") parser.add_argument("-c", "--colormap", action="store_true", - help="Use the given colors as a colormap (cycle the colors at each match)") + help="Interpret the given COLOR comma-separated list of colors as a colormap \ + (cycle the colors at each match)") babel_warn=" (numbers will be parsed according to your locale)" try: @@ -741,7 +743,7 @@ def __args_parse__(argv, usage=""): babel_warn=" (WARNING: python3-babel is not available, install it \ if you want to be able to parse numbers according to your locale)" - parser.add_argument("-l", "--scale", + parser.add_argument("-l", "--scale", metavar="SCALE", help="When using the 'scale' colormap, parse matches as decimal numbers \ and apply the rainbow colormap linearly between the given SCALE=min,max" + babel_warn) @@ -759,6 +761,11 @@ def __args_parse__(argv, usage=""): parser.add_argument("-P", "--palettes-dir", metavar="DIR", action="append", help="Search for additional palettes (*.gpl files) in the given directory") + parser.add_argument("-d", "--default", metavar="COLORMAP", default="spectrum", + help="When using special colormaps (`scale` or `hash`), use this COLORMAP. \ + This can be either one of the available colormaps or a comma-separated list of colors. \ + WARNING: be sure to specify a default colormap that is compatible with the special colormap's mode.") + # This normally should be an option with an argument, but this would end in an error, # as no regexp is supposed to be passed after calling this option, # we use it as the argument to this option. @@ -781,7 +788,7 @@ def __args_parse__(argv, usage=""): return args.pattern[0], args.color, args.style, args.groups, \ args.colormap, args.theme, args.source, args.all, args.scale, args.debug, args.resources, args.palettes_dir, \ - args.themes_dir + args.themes_dir, args.default def write_all( as_all, stream_in, stream_out, function, *args ): @@ -816,7 +823,7 @@ if __name__ == "__main__": # if argparse is available else: pattern, color, style, on_groups, as_colormap, as_theme, as_source, as_all, myscale, \ - debug, resources, palettes_dirs, themes_dirs \ + debug, resources, palettes_dirs, themes_dirs, default_colormap \ = __args_parse__(sys.argv, usage) if debug: @@ -917,8 +924,20 @@ if __name__ == "__main__": scale = tuple([float(i) for i in myscale.split(",")]) logging.debug("user-defined scale: %f,%f" % scale) - # use the generator: output lines as they come - if as_colormap is True and color != "rainbow": + if default_colormap and default_colormap not in colormaps: + colormap = default_colormap.split(",") + logging.debug("used-defined default colormap: %s" % ",".join([str(i) for i in colormap]) ) + elif default_colormap and default_colormap in colormaps: + # Configure the default colormap to be in the same mode than the given color + if color[0].islower(): + cmap = default_colormap.lower() + else: + cmap = default_colormap[0].upper() + default_colormap[1:] + logging.debug("used-defined default colormap: %s" % cmap ) + colormap = colormaps[cmap] + logging.debug("used-defined default colormap: %s" % colormap ) + + if as_colormap is True and color not in colormaps: colormap = color.split(",") # replace the colormap by the given colors color = "colormap" # use the keyword to switch to colormap instead of list of colors logging.debug("used-defined colormap: %s" % ",".join(colormap) ) From e29119417314a8cdc9a9ccae92c9bac8e3d3d8fd Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 16 Apr 2014 00:10:30 +0200 Subject: [PATCH 024/116] Refactor colorin Move conditional branches in subfunctions. --- colout/colout.py | 311 ++++++++++++++++++++++++++--------------------- 1 file changed, 174 insertions(+), 137 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 8ac771b..77b4f2d 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -258,6 +258,166 @@ def load_resources( themes_dir, palettes_dir ): # Library ############################################################################### +def mode( color ): + if color in colors: + return 8 + elif color in colormaps.keys(): + if color[0].islower(): + return 8 + elif color[0].isupper(): + return 256 + elif color.lower() in ("scale","hash","random") or color.lower() in lexers: + if color[0].islower(): + return 8 + elif color[0].isupper(): + return 256 + elif color[0] == "#": + return 256 + elif color.isdigit() and (ansi_min < int(color) and int(color) < ansi_max) : + return 256 + else: + raise UnknownColor(color) + + +def next_in_map( color ): + # loop over indices in colormap + return (colormap_idx+1) % len(colormaps[color]) + + +def color_random( color ): + m = mode(color) + if m == 8: + color_code = random.choice(list(colors.values())) + color_code = str(30 + color_code) + + elif m == 256: + color_nb = random.randint(0, 255) + color_code = str(color_nb) + + return color_code + + +def color_in_colormaps( color ): + m = mode(color) + if m == 8: + c = colormaps[color][colormap_idx] + if c.isdigit(): + color_code = str(30 + c) + else: + color_code = str(30 + colors[c]) + + else: + color_nb = colormaps[color][colormap_idx] + color_code = str( color_nb ) + + colormap_idx = next_in_map(color) + + return color_code + + +def color_scale( color, text ): + # filter out everything that does not seem to be necessary to interpret the string as a number + # this permits to transform "[ 95%]" to "95" before number conversion, + # and thus allows to color a group larger than the matched number + chars_in_numbers = "-+.,e/*" + allowed = string.digits + chars_in_numbers + nb = "".join([i for i in filter(allowed.__contains__, text)]) + + # interpret as decimal + # First, try with the babel module, if available + # if not, use python itself, + # if thoses fails, try to `eval` the string + # (this allow strings like "1/2+0.9*2") + try: + # babel is a specialized module + import babel.numbers as bn + try: + f = float(bn.parse_decimal(nb)) + except NumberFormatError: + f = eval(nb) # Note: in python2, `eval(2/3)` would produce `0`, in python3 `0.666` + except ImportError: + try: + f = float(nb) + except ValueError: + f = eval(nb) + + # if out of scale, do not color + if f < scale[0] or f > scale[1]: + return text + + # normalize and scale over the nb of colors in cmap + i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(colormap)-1) ) ) + + m = mode(color) + color = colormap[i] + + if m == 8: + color_code = str(30 + colors[color]) + else: + color_code = str(color) + + return color_code + + +def color_hash( color, text ): + hasher = hashlib.md5() + hasher.update(text.encode('utf-8')) + hash = hasher.hexdigest() + + f = float(functools.reduce(lambda x, y: x+ord(y), hash, 0) % 101) + + # normalize and scale over the nb of colors in cmap + i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(colormap)-1) ) ) + + m = mode(color) + color = colormap[i] + if m == 8: + color_code = str(30 + colors[color]) + else: + color_code = str(color) + + return color_code + + +def color_map(): + # current color + color = colormap[colormap_idx] + + m = mode(color) + if m == 8: + color_code = str(30 + colors[color]) + + else: + color_nb = int(color) + assert( ansi_min <= color_nb <= ansi_max ) + color_code = str(color_nb) + + colormap_idx = next_in_map(color) + + return color_code + + +def color_lexer( color, style, text ): + lexer = get_lexer_by_name(color.lower()) + # Python => 256 colors, python => 8 colors + m = mode(color) + if m == 256: + try: + formatter = Terminal256Formatter(style=style) + except: # style not found + formatter = Terminal256Formatter() + else: + if style not in ("light","dark"): + style = "dark" # dark color scheme by default + formatter = TerminalFormatter(bg=style) + # We should return all but the last character, + # because Pygments adds a newline char. + if not debug: + return highlight(text, lexer, formatter)[:-1] + else: + return "<"+color+">"+ highlight(text, lexer, formatter)[:-1] + "" + + def colorin(text, color="red", style="normal"): """ Return the given text, surrounded by the given color ASCII markers. @@ -293,6 +453,8 @@ def colorin(text, color="red", style="normal"): style_code = str(styles[style]) color = color.strip() + m = mode(color) + if color == "none": # if no color, style cannot be applied if not debug: @@ -300,180 +462,55 @@ def colorin(text, color="red", style="normal"): else: return ""+text+"" - - elif color == "random": - mode = 8 - color_code = random.choice(list(colors.values())) - color_code = str(30 + color_code) - - elif color == "Random": - mode = 256 - color_nb = random.randint(0, 255) - color_code = str(color_nb) - + elif color.lower() == "random": + color_code = color_random( color ) elif color in colormaps.keys(): - if color[0].islower(): # lower case first letter - mode = 8 - c = colormaps[color][colormap_idx] - if c.isdigit(): - color_code = str(30 + c) - else: - color_code = str(30 + colors[c]) - - else: # upper case - mode = 256 - color_nb = colormaps[color][colormap_idx] - color_code = str( color_nb ) - - if colormap_idx < len(colormaps[color])-1: - colormap_idx += 1 - else: - colormap_idx = 0 - + color_code = color_in_colormaps( color ) elif color.lower() == "scale": # "scale" or "Scale" - - # filter out everything that does not seem to be necessary to interpret the string as a number - # this permits to transform "[ 95%]" to "95" before number conversion, - # and thus allows to color a group larger than the matched number - chars_in_numbers = "-+.,e/*" - allowed = string.digits + chars_in_numbers - nb = "".join([i for i in filter(allowed.__contains__, text)]) - - # interpret as decimal - # First, try with the babel module, if available - # if not, use python itself, - # if thoses fails, try to `eval` the string - # (this allow strings like "1/2+0.9*2") - try: - # babel is a specialized module - import babel.numbers as bn - try: - f = float(bn.parse_decimal(nb)) - except NumberFormatError: - f = eval(nb) # Note: in python2, `eval(2/3)` would produce `0`, in python3 `0.666` - except ImportError: - try: - f = float(nb) - except ValueError: - f = eval(nb) - - # if out of scale, do not color - if f < scale[0] or f > scale[1]: - return text - - if color[0].islower(): - mode = 8 - # Use the default colormap in lower case = 8-colors mode - cmap = colormap - - # normalize and scale over the nb of colors in cmap - i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(cmap)-1) ) ) - - color = cmap[i] - color_code = str(30 + colors[color]) - - else: - mode = 256 - cmap = colormap - i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(cmap)-1) ) ) - color = cmap[i] - color_code = str(color) - + color_code = color_scale( color, text ) # "hash" or "Hash"; useful to randomly but consistently color strings elif color.lower() == "hash": - hasher = hashlib.md5() - hasher.update(text.encode('utf-8')) - hash = hasher.hexdigest() - - f = float(functools.reduce(lambda x, y: x+ord(y), hash, 0) % 101) - - if color[0].islower(): - mode = 8 - cmap = colormap - - # normalize and scale over the nb of colors in cmap - i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(cmap)-1) ) ) - - color = cmap[i] - color_code = str(30 + colors[color]) - - else: - mode = 256 - cmap = colormap - i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(cmap)-1) ) ) - color = cmap[i] - color_code = str(color) - + color_code = color_hash( color, text ) # Really useful only when using colout as a library # thus you can change the "colormap" variable to your favorite one before calling colorin elif color == "colormap": - color = colormap[colormap_idx] - if color in colors: - mode = 8 - color_code = str(30 + colors[color]) - else: - mode = 256 - color_nb = int(color) - assert(0 <= color_nb <= 255) - color_code = str(color_nb) - - if colormap_idx < len(colormap)-1: - colormap_idx += 1 - else: - colormap_idx = 0 + color_code = color_map() # 8 colors modes elif color in colors: - mode = 8 color_code = str(30 + colors[color]) # hexadecimal color elif color[0] == "#": - mode = 256 color_nb = rgb_to_ansi(*hex_to_rgb(color)) assert(0 <= color_nb <= 255) color_code = str(color_nb) # 256 colors mode elif color.isdigit(): - mode = 256 color_nb = int(color) assert(0 <= color_nb <= 255) color_code = str(color_nb) # programming language elif color.lower() in lexers: - lexer = get_lexer_by_name(color.lower()) - # Python => 256 colors, python => 8 colors - ask_256 = color[0].isupper() - if ask_256: - try: - formatter = Terminal256Formatter(style=style) - except: # style not found - formatter = Terminal256Formatter() - else: - if style not in ("light","dark"): - style = "dark" # dark color scheme by default - formatter = TerminalFormatter(bg=style) - # We should return all but the last character, - # because Pygments adds a newline char. - if not debug: - return highlight(text, lexer, formatter)[:-1] - else: - return "<"+color+">"+ highlight(text, lexer, formatter)[:-1] + "" + # bypass color encoding and return text colored by the lexer + return color_lexer(color,style,text) # unrecognized else: raise UnknownColor(color) if not debug: - return start + style_code + endmarks[mode] + color_code + "m" + text + stop + return start + style_code + endmarks[m] + color_code + "m" + text + stop else: - return start + style_code + endmarks[mode] + color_code + "m<" + str(color) + ">" + text + "" + stop + return start + style_code + endmarks[m] + color_code + "m" \ + + "" \ + + text + "" + stop def colorout(text, match, prev_end, color="red", style="normal", group=0): From 5f03dd11b883d120db2df71f136b7949a1e4c39b Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 16 Apr 2014 00:38:48 +0200 Subject: [PATCH 025/116] fix mode detection for scale and hash --- colout/colout.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 77b4f2d..a60bdb2 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -159,7 +159,7 @@ colormaps = { "Spectrum" : [91, 92, 56, 57, 21, 27, 26, 32, 31, 37, 36, 35, 41, 40, 41, 77, 83, 84, 120, 121, 157, 194, 231, 254, 255, 231, 230, 229, 228, 227, 226, 220, 214, 208, 202, 196] } # colormaps -colormap = colormaps["rainbow"] # default colormap to rainbow +colormap = colormaps["rainbow"] colormap_idx = 0 scale = (0,100) @@ -348,8 +348,9 @@ def color_scale( color, text ): # normalize and scale over the nb of colors in cmap i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(colormap)-1) ) ) - m = mode(color) color = colormap[i] + # infer mode from the color in the colormap + m = mode(color) if m == 8: color_code = str(30 + colors[color]) @@ -369,8 +370,10 @@ def color_hash( color, text ): # normalize and scale over the nb of colors in cmap i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(colormap)-1) ) ) - m = mode(color) color = colormap[i] + # infer mode from the color in the colormap + m = mode(color) + if m == 8: color_code = str(30 + colors[color]) else: From dcf5a843163ac8a16277a7d26a751d5fdd46d289 Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 16 Apr 2014 00:39:34 +0200 Subject: [PATCH 026/116] replace Fraction with Scale in cmake theme --- colout/colout_cmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index 5ce9dec..d2efefa 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -45,5 +45,5 @@ def theme(): # progress percentage (make) [ "^(\[\s*[0-9]+%\])","Scale" ], # progress percentage (ninja) - [ "^(\[[0-9]+/[0-9]+\])","Fraction" ] + [ "^(\[[0-9]+/[0-9]+\])","Scale" ] ] From f0ab462fc15391fa1e56710ab7091fba29304f7d Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 16 Apr 2014 01:11:05 +0200 Subject: [PATCH 027/116] simplify default colormap change --- colout/colout.py | 68 ++++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index a60bdb2..3eaba66 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -159,7 +159,13 @@ colormaps = { "Spectrum" : [91, 92, 56, 57, 21, 27, 26, 32, 31, 37, 36, 35, 41, 40, 41, 77, 83, 84, 120, 121, 157, 194, 231, 254, 255, 231, 230, 229, 228, 227, 226, 220, 214, 208, 202, 196] } # colormaps -colormap = colormaps["rainbow"] +colormaps["scale"] = colormaps["spectrum"] +colormaps["Scale"] = colormaps["Spectrum"] +colormaps["hash"] = colormaps["rainbow"] +colormaps["Hash"] = colormaps["Rainbow"] +colormaps["default"] = colormaps["spectrum"] +colormaps["Default"] = colormaps["Spectrum"] + colormap_idx = 0 scale = (0,100) @@ -280,6 +286,7 @@ def mode( color ): def next_in_map( color ): + global colormap_idx # loop over indices in colormap return (colormap_idx+1) % len(colormaps[color]) @@ -298,6 +305,7 @@ def color_random( color ): def color_in_colormaps( color ): + global colormap_idx m = mode(color) if m == 8: c = colormaps[color][colormap_idx] @@ -315,7 +323,7 @@ def color_in_colormaps( color ): return color_code -def color_scale( color, text ): +def color_scale( name, text ): # filter out everything that does not seem to be necessary to interpret the string as a number # this permits to transform "[ 95%]" to "95" before number conversion, # and thus allows to color a group larger than the matched number @@ -346,9 +354,10 @@ def color_scale( color, text ): return text # normalize and scale over the nb of colors in cmap + colormap = colormaps[name] i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(colormap)-1) ) ) - color = colormap[i] + # infer mode from the color in the colormap m = mode(color) @@ -360,7 +369,7 @@ def color_scale( color, text ): return color_code -def color_hash( color, text ): +def color_hash( name, text ): hasher = hashlib.md5() hasher.update(text.encode('utf-8')) hash = hasher.hexdigest() @@ -368,9 +377,10 @@ def color_hash( color, text ): f = float(functools.reduce(lambda x, y: x+ord(y), hash, 0) % 101) # normalize and scale over the nb of colors in cmap + colormap = colormaps[name] i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(colormap)-1) ) ) - color = colormap[i] + # infer mode from the color in the colormap m = mode(color) @@ -382,14 +392,14 @@ def color_hash( color, text ): return color_code -def color_map(): +def color_map(name): + global colormap_idx # current color - color = colormap[colormap_idx] + color = colormaps[name][colormap_idx] m = mode(color) if m == 8: color_code = str(30 + colors[color]) - else: color_nb = int(color) assert( ansi_min <= color_nb <= ansi_max ) @@ -400,10 +410,10 @@ def color_map(): return color_code -def color_lexer( color, style, text ): - lexer = get_lexer_by_name(color.lower()) +def color_lexer( name, style, text ): + lexer = get_lexer_by_name(name.lower()) # Python => 256 colors, python => 8 colors - m = mode(color) + m = mode(name) if m == 256: try: formatter = Terminal256Formatter(style=style) @@ -418,7 +428,7 @@ def color_lexer( color, style, text ): if not debug: return highlight(text, lexer, formatter)[:-1] else: - return "<"+color+">"+ highlight(text, lexer, formatter)[:-1] + "" + return "<"+name+">"+ highlight(text, lexer, formatter)[:-1] + "" def colorin(text, color="red", style="normal"): @@ -481,7 +491,7 @@ def colorin(text, color="red", style="normal"): # Really useful only when using colout as a library # thus you can change the "colormap" variable to your favorite one before calling colorin elif color == "colormap": - color_code = color_map() + color_code = color_map(color) # 8 colors modes elif color in colors: @@ -512,7 +522,9 @@ def colorin(text, color="red", style="normal"): return start + style_code + endmarks[m] + color_code + "m" + text + stop else: return start + style_code + endmarks[m] + color_code + "m" \ - + "" \ + + "" \ + text + "" + stop @@ -964,23 +976,23 @@ if __name__ == "__main__": scale = tuple([float(i) for i in myscale.split(",")]) logging.debug("user-defined scale: %f,%f" % scale) - if default_colormap and default_colormap not in colormaps: - colormap = default_colormap.split(",") - logging.debug("used-defined default colormap: %s" % ",".join([str(i) for i in colormap]) ) - elif default_colormap and default_colormap in colormaps: - # Configure the default colormap to be in the same mode than the given color - if color[0].islower(): - cmap = default_colormap.lower() - else: - cmap = default_colormap[0].upper() + default_colormap[1:] - logging.debug("used-defined default colormap: %s" % cmap ) - colormap = colormaps[cmap] - logging.debug("used-defined default colormap: %s" % colormap ) + # Default color maps + if default_colormap not in colormaps: + cmap = default_colormap.split(",") + elif default_colormap in colormaps: + cmap = colormaps[default_colormap] + + colormaps[color] = cmap + logging.debug("used-defined default colormap: %s" % ",".join([str(i) for i in cmap]) ) + + + # explicit color map if as_colormap is True and color not in colormaps: - colormap = color.split(",") # replace the colormap by the given colors + colormaps["Default"] = color.split(",") # replace the colormap by the given colors + colormaps["default"] = color.split(",") # replace the colormap by the given colors color = "colormap" # use the keyword to switch to colormap instead of list of colors - logging.debug("used-defined colormap: %s" % ",".join(colormap) ) + logging.debug("used-defined colormap: %s" % ",".join(colormaps["Default"]) ) # if theme if as_theme: From c830a02fecce0e1b71959313bbdbb7142a2a534e Mon Sep 17 00:00:00 2001 From: nojhan Date: Thu, 24 Apr 2014 09:54:30 +0200 Subject: [PATCH 028/116] bugfix: return text if no color, more debug infos use global colormap_idx --- colout/colout.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 3eaba66..00c6b01 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -351,7 +351,7 @@ def color_scale( name, text ): # if out of scale, do not color if f < scale[0] or f > scale[1]: - return text + return None # normalize and scale over the nb of colors in cmap colormap = colormaps[name] @@ -448,7 +448,6 @@ def colorin(text, color="red", style="normal"): assert( type(color) is str ) - global colormap_idx global debug # Special characters. @@ -518,14 +517,20 @@ def colorin(text, color="red", style="normal"): else: raise UnknownColor(color) - if not debug: - return start + style_code + endmarks[m] + color_code + "m" + text + stop + if color_code is not None: + if not debug: + return start + style_code + endmarks[m] + color_code + "m" + text + stop + else: + return start + style_code + endmarks[m] + color_code + "m" \ + + "" \ + + text + "" + stop else: - return start + style_code + endmarks[m] + color_code + "m" \ - + "" \ - + text + "" + stop + if not debug: + return text + else: + return "" + text + "" def colorout(text, match, prev_end, color="red", style="normal", group=0): From d3efe7e8513785414a6c102f5b8079c8cdf9b2df Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 25 Apr 2014 10:56:17 +0200 Subject: [PATCH 029/116] Make default colormaps work. Overwrite default colormaps only if asked. Correctly interpret integers in mode(). Test registered colormaps after specials. Silently ignore duplicated external palettes. Add a set_special_colormaps function. Do not sue ANSI_min/max as limits for the whole ANSI range. Move global variables at the top of the file. --- README.md | 2 + colout/colout.py | 179 +++++++++++++++++++++++++++-------------------- 2 files changed, 104 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 80ac984..c49e5db 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,8 @@ Gentoo WARNING: be sure to specify a default colormap that is compatible with the special colormap's mode. For instance, if you indicate `scale`, you can use `-d red,green,blue`, but `-d 12,13,14` will fail. Also, if you specify `Scale`, you cannot use `-d red,green,blue`, but `-d Rainbow` will work. + Similarly, external palettes are converted from RGB to 256-ANSI and will thus not work if you use + them as default colormaps for a 8-colors mode special color. * `-r TYPE(S)`, `--resources TYPE(S)`: Print the names of available resources. Use a comma-separated list of resources names diff --git a/colout/colout.py b/colout/colout.py index 00c6b01..21a63ed 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -23,10 +23,77 @@ import functools signal.signal( signal.SIGPIPE, signal.SIG_DFL ) +############################################################################### +# Global variables +############################################################################### + +# Escaped end markers for given color modes +endmarks = {8: ";", 256: ";38;5;"} + +# Available styles +styles = { + "normal": 0, "bold": 1, "faint": 2, "italic": 3, "underline": 4, + "blink": 5, "rapid_blink": 6, + "reverse": 7, "conceal": 8 +} + +# Available color names in 8-colors mode +colors = { + "black": 0, "red": 1, "green": 2, "yellow": 3, "orange":3, "blue": 4, + "magenta": 5, "purple": 5, "cyan": 6, "white": 7, "none": -1 +} + +themes = {} + +# pre-defined colormaps +# 8-colors mode should start with a lower-case letter (and can contains either named or indexed colors) +# 256-colors mode should start with an upper-case letter (and should contains indexed colors) +colormaps = { + # Rainbows + "rainbow" : ["magenta", "blue", "cyan", "green", "yellow", "red"], + "Rainbow" : [92, 93, 57, 21, 27, 33, 39, 45, 51, 50, 49, 48, 47, 46, 82, 118, 154, 190, 226, 220, 214, 208, 202, 196], + + # from magenta to red, with white in the middle + "spectrum" : ["magenta", "blue", "cyan", "white", "green", "yellow", "red"], + "Spectrum" : [91, 92, 56, 57, 21, 27, 26, 32, 31, 37, 36, 35, 41, 40, 41, 77, 83, 84, 120, 121, 157, 194, 231, 254, 255, 231, 230, 229, 228, 227, 226, 220, 214, 208, 202, 196] +} # colormaps + +colormaps["scale"] = colormaps["spectrum"] +colormaps["Scale"] = colormaps["Spectrum"] +colormaps["hash"] = colormaps["rainbow"] +colormaps["Hash"] = colormaps["Rainbow"] +colormaps["default"] = colormaps["spectrum"] +colormaps["Default"] = colormaps["Spectrum"] + +colormap_idx = 0 + +scale = (0,100) + +class UnknownColor(Exception): + pass + +class DuplicatedPalette(Exception): + pass + +class DuplicatedTheme(Exception): + pass + + ############################################################################### # Ressource parsing helpers ############################################################################### + +def set_special_colormaps( cmap ): + """Change all the special colors to a single colormap (which must be a list of colors).""" + colormaps["scale"] = cmap + colormaps["Scale"] = cmap + colormaps["hash"] = cmap + colormaps["Hash"] = cmap + colormaps["default"] = cmap + colormaps["Default"] = cmap + + def parse_gimp_palette( filename ): """ Parse the given filename as a GIMP palette (.gpl) @@ -90,7 +157,13 @@ def uniq( lst ): def rgb_to_ansi( r, g, b ): """Convert a RGB color to its closest 256-colors ANSI index""" - # ansi_max is the higher possible RGB value for ANSI colors + + # Range limits for the *colored* section of ANSI, + # this does not include the *gray* section. + ansi_min = 16 + ansi_max = 234 + + # ansi_max is the higher possible RGB value for ANSI *colors* # limit RGB values to ansi_max red,green,blue = tuple([ansi_max if c>ansi_max else c for c in (r,g,b)]) @@ -121,65 +194,6 @@ def hex_to_rgb(h): return tuple( int(h[i:i+lh//3], 16) for i in range(0, lh, lh//3) ) -############################################################################### -# Global variables -############################################################################### - -# Escaped end markers for given color modes -endmarks = {8: ";", 256: ";38;5;"} - -ansi_min = 16 -ansi_max = 234 - -# Available styles -styles = { - "normal": 0, "bold": 1, "faint": 2, "italic": 3, "underline": 4, - "blink": 5, "rapid_blink": 6, - "reverse": 7, "conceal": 8 -} - -# Available color names in 8-colors mode -colors = { - "black": 0, "red": 1, "green": 2, "yellow": 3, "orange":3, "blue": 4, - "magenta": 5, "purple": 5, "cyan": 6, "white": 7, "none": -1 -} - -themes = {} - -# pre-defined colormaps -# 8-colors mode should start with a lower-case letter (and can contains either named or indexed colors) -# 256-colors mode should start with an upper-case letter (and should contains indexed colors) -colormaps = { - # Rainbows - "rainbow" : ["magenta", "blue", "cyan", "green", "yellow", "red"], - "Rainbow" : [92, 93, 57, 21, 27, 33, 39, 45, 51, 50, 49, 48, 47, 46, 82, 118, 154, 190, 226, 220, 214, 208, 202, 196], - - # from magenta to red, with white in the middle - "spectrum" : ["magenta", "blue", "cyan", "white", "green", "yellow", "red"], - "Spectrum" : [91, 92, 56, 57, 21, 27, 26, 32, 31, 37, 36, 35, 41, 40, 41, 77, 83, 84, 120, 121, 157, 194, 231, 254, 255, 231, 230, 229, 228, 227, 226, 220, 214, 208, 202, 196] -} # colormaps - -colormaps["scale"] = colormaps["spectrum"] -colormaps["Scale"] = colormaps["Spectrum"] -colormaps["hash"] = colormaps["rainbow"] -colormaps["Hash"] = colormaps["Rainbow"] -colormaps["default"] = colormaps["spectrum"] -colormaps["Default"] = colormaps["Spectrum"] - -colormap_idx = 0 - -scale = (0,100) - -class UnknownColor(Exception): - pass - -class DuplicatedPalette(Exception): - pass - -class DuplicatedTheme(Exception): - pass - - ############################################################################### # Load available extern resources ############################################################################### @@ -199,7 +213,7 @@ def load_themes( themes_dir): themes[name] = importlib.import_module(module) -def load_palettes( palettes_dir ): +def load_palettes( palettes_dir, ignore_duplicates = True ): global colormaps logging.debug("search for palettes in: %s" % palettes_dir) os.chdir( palettes_dir ) @@ -212,7 +226,10 @@ def load_palettes( palettes_dir ): logging.warning("error while parsing palette %s: %s" % ( p,e ) ) continue if name in colormaps: - raise DuplicatedPalette(name) + if ignore_duplicates: + logging.warning("ignore this duplicated palette name: %s" % name) + else: + raise DuplicatedPalette(name) # Convert the palette to ANSI ansi_palette = [ rgb_to_ansi(r,g,b) for r,g,b in palette ] # Compress it so that there isn't two consecutive identical colors @@ -265,7 +282,12 @@ def load_resources( themes_dir, palettes_dir ): ############################################################################### def mode( color ): - if color in colors: + if type(color) is int: + if 0 <= color and color <= 255 : + return 256 + else: + raise UnknownColor(color) + elif color in colors: return 8 elif color in colormaps.keys(): if color[0].islower(): @@ -279,7 +301,7 @@ def mode( color ): return 256 elif color[0] == "#": return 256 - elif color.isdigit() and (ansi_min < int(color) and int(color) < ansi_max) : + elif color.isdigit() and (0 <= int(color) and int(color) <= 255) : return 256 else: raise UnknownColor(color) @@ -402,7 +424,7 @@ def color_map(name): color_code = str(30 + colors[color]) else: color_nb = int(color) - assert( ansi_min <= color_nb <= ansi_max ) + assert( 0 <= color_nb <= 255 ) color_code = str(color_nb) colormap_idx = next_in_map(color) @@ -477,9 +499,6 @@ def colorin(text, color="red", style="normal"): elif color.lower() == "random": color_code = color_random( color ) - elif color in colormaps.keys(): - color_code = color_in_colormaps( color ) - elif color.lower() == "scale": # "scale" or "Scale" color_code = color_scale( color, text ) @@ -492,6 +511,12 @@ def colorin(text, color="red", style="normal"): elif color == "colormap": color_code = color_map(color) + # Registered colormaps should be tested after special colors, + # because special tags are also registered as colormaps, + # but do not have the same simple behavior. + elif color in colormaps.keys(): + color_code = color_in_colormaps( color ) + # 8 colors modes elif color in colors: color_code = str(30 + colors[color]) @@ -818,7 +843,7 @@ def __args_parse__(argv, usage=""): parser.add_argument("-P", "--palettes-dir", metavar="DIR", action="append", help="Search for additional palettes (*.gpl files) in the given directory") - parser.add_argument("-d", "--default", metavar="COLORMAP", default="spectrum", + parser.add_argument("-d", "--default", metavar="COLORMAP", default=None, help="When using special colormaps (`scale` or `hash`), use this COLORMAP. \ This can be either one of the available colormaps or a comma-separated list of colors. \ WARNING: be sure to specify a default colormap that is compatible with the special colormap's mode.") @@ -982,22 +1007,22 @@ if __name__ == "__main__": logging.debug("user-defined scale: %f,%f" % scale) # Default color maps - if default_colormap not in colormaps: - cmap = default_colormap.split(",") + if default_colormap: + if default_colormap not in colormaps: + cmap = default_colormap.split(",") - elif default_colormap in colormaps: - cmap = colormaps[default_colormap] - - colormaps[color] = cmap - logging.debug("used-defined default colormap: %s" % ",".join([str(i) for i in cmap]) ) + elif default_colormap in colormaps: + cmap = colormaps[default_colormap] + set_special_colormaps( cmap ) + logging.debug("user-defined special colormap: %s" % ",".join([str(i) for i in cmap]) ) # explicit color map if as_colormap is True and color not in colormaps: colormaps["Default"] = color.split(",") # replace the colormap by the given colors colormaps["default"] = color.split(",") # replace the colormap by the given colors color = "colormap" # use the keyword to switch to colormap instead of list of colors - logging.debug("used-defined colormap: %s" % ",".join(colormaps["Default"]) ) + logging.debug("used-defined default colormap: %s" % ",".join(colormaps["Default"]) ) # if theme if as_theme: From e499f40f7d70825231c6f772cfeb13a283487251 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 25 Apr 2014 13:50:51 +0200 Subject: [PATCH 030/116] Bring global context variables to the themes. Encapsulate global variables in the `context` dictionary. Pass the context through the called themes, that can thus change the configuration. --- colout/colout.py | 168 ++++++++++++++++++++++------------------ colout/colout_cmake.py | 8 +- colout/colout_g++.py | 4 +- colout/colout_javac.py | 4 +- colout/colout_json.py | 4 +- colout/colout_latex.py | 4 +- colout/colout_perm.py | 4 +- colout/colout_python.py | 4 +- 8 files changed, 109 insertions(+), 91 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 21a63ed..3b83169 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -24,31 +24,30 @@ signal.signal( signal.SIGPIPE, signal.SIG_DFL ) ############################################################################### -# Global variables +# Global variable(s) ############################################################################### -# Escaped end markers for given color modes -endmarks = {8: ";", 256: ";38;5;"} +context = {} # Available styles -styles = { +context["styles"] = { "normal": 0, "bold": 1, "faint": 2, "italic": 3, "underline": 4, "blink": 5, "rapid_blink": 6, "reverse": 7, "conceal": 8 } # Available color names in 8-colors mode -colors = { +context["colors"] = { "black": 0, "red": 1, "green": 2, "yellow": 3, "orange":3, "blue": 4, "magenta": 5, "purple": 5, "cyan": 6, "white": 7, "none": -1 } -themes = {} +context["themes"] = {} # pre-defined colormaps # 8-colors mode should start with a lower-case letter (and can contains either named or indexed colors) # 256-colors mode should start with an upper-case letter (and should contains indexed colors) -colormaps = { +context["colormaps"] = { # Rainbows "rainbow" : ["magenta", "blue", "cyan", "green", "yellow", "red"], "Rainbow" : [92, 93, 57, 21, 27, 33, 39, 45, 51, 50, 49, 48, 47, 46, 82, 118, 154, 190, 226, 220, 214, 208, 202, 196], @@ -58,16 +57,18 @@ colormaps = { "Spectrum" : [91, 92, 56, 57, 21, 27, 26, 32, 31, 37, 36, 35, 41, 40, 41, 77, 83, 84, 120, 121, 157, 194, 231, 254, 255, 231, 230, 229, 228, 227, 226, 220, 214, 208, 202, 196] } # colormaps -colormaps["scale"] = colormaps["spectrum"] -colormaps["Scale"] = colormaps["Spectrum"] -colormaps["hash"] = colormaps["rainbow"] -colormaps["Hash"] = colormaps["Rainbow"] -colormaps["default"] = colormaps["spectrum"] -colormaps["Default"] = colormaps["Spectrum"] +context["colormaps"]["scale"] = context["colormaps"]["spectrum"] +context["colormaps"]["Scale"] = context["colormaps"]["Spectrum"] +context["colormaps"]["hash"] = context["colormaps"]["rainbow"] +context["colormaps"]["Hash"] = context["colormaps"]["Rainbow"] +context["colormaps"]["default"] = context["colormaps"]["spectrum"] +context["colormaps"]["Default"] = context["colormaps"]["Spectrum"] -colormap_idx = 0 +context["colormap_idx"] = 0 -scale = (0,100) +context["scale"] = (0,100) + +context["lexers"] = [] class UnknownColor(Exception): pass @@ -86,12 +87,14 @@ class DuplicatedTheme(Exception): def set_special_colormaps( cmap ): """Change all the special colors to a single colormap (which must be a list of colors).""" - colormaps["scale"] = cmap - colormaps["Scale"] = cmap - colormaps["hash"] = cmap - colormaps["Hash"] = cmap - colormaps["default"] = cmap - colormaps["Default"] = cmap + global context + context["colormaps"]["scale"] = cmap + context["colormaps"]["Scale"] = cmap + context["colormaps"]["hash"] = cmap + context["colormaps"]["Hash"] = cmap + context["colormaps"]["default"] = cmap + context["colormaps"]["Default"] = cmap + logging.debug("user-defined special colormap: %s" % ",".join([str(i) for i in cmap]) ) def parse_gimp_palette( filename ): @@ -199,7 +202,7 @@ def hex_to_rgb(h): ############################################################################### def load_themes( themes_dir): - global themes + global context logging.debug("search for themes in: %s" % themes_dir) os.chdir( themes_dir ) @@ -207,14 +210,14 @@ def load_themes( themes_dir): for f in glob.iglob("colout_*.py"): module = ".".join(f.split(".")[:-1]) # remove extension name = "_".join(module.split("_")[1:]) # remove the prefix - if name in themes: + if name in context["themes"]: raise DuplicatedTheme(name) logging.debug("load theme %s" % name) - themes[name] = importlib.import_module(module) + context["themes"][name] = importlib.import_module(module) def load_palettes( palettes_dir, ignore_duplicates = True ): - global colormaps + global context logging.debug("search for palettes in: %s" % palettes_dir) os.chdir( palettes_dir ) @@ -225,7 +228,7 @@ def load_palettes( palettes_dir, ignore_duplicates = True ): except Exception as e: logging.warning("error while parsing palette %s: %s" % ( p,e ) ) continue - if name in colormaps: + if name in context["colormaps"]: if ignore_duplicates: logging.warning("ignore this duplicated palette name: %s" % name) else: @@ -235,11 +238,11 @@ def load_palettes( palettes_dir, ignore_duplicates = True ): # Compress it so that there isn't two consecutive identical colors compressed = uniq(ansi_palette) logging.debug("load %i ANSI colors in palette %s: %s" % (len(compressed), name, compressed)) - colormaps[name] = compressed + context["colormaps"][name] = compressed def load_lexers(): - global lexers + global context # load available pygments lexers lexers = [] try: @@ -270,6 +273,8 @@ def load_lexers(): logging.debug("loaded lexer %s" % lexer[1][0]) lexers.sort() + context["lexers"] = lexers + def load_resources( themes_dir, palettes_dir ): load_themes( themes_dir ) @@ -282,19 +287,20 @@ def load_resources( themes_dir, palettes_dir ): ############################################################################### def mode( color ): + global context if type(color) is int: if 0 <= color and color <= 255 : return 256 else: raise UnknownColor(color) - elif color in colors: + elif color in context["colors"]: return 8 - elif color in colormaps.keys(): + elif color in context["colormaps"].keys(): if color[0].islower(): return 8 elif color[0].isupper(): return 256 - elif color.lower() in ("scale","hash","random") or color.lower() in lexers: + elif color.lower() in ("scale","hash","random") or color.lower() in context["lexers"]: if color[0].islower(): return 8 elif color[0].isupper(): @@ -308,15 +314,15 @@ def mode( color ): def next_in_map( color ): - global colormap_idx + global context # loop over indices in colormap - return (colormap_idx+1) % len(colormaps[color]) + return (context["colormap_idx"]+1) % len(context["colormaps"][color]) def color_random( color ): m = mode(color) if m == 8: - color_code = random.choice(list(colors.values())) + color_code = random.choice(list(context["colors"].values())) color_code = str(30 + color_code) elif m == 256: @@ -327,20 +333,20 @@ def color_random( color ): def color_in_colormaps( color ): - global colormap_idx + global context m = mode(color) if m == 8: - c = colormaps[color][colormap_idx] + c = context["colormaps"][color][context["colormap_idx"]] if c.isdigit(): color_code = str(30 + c) else: - color_code = str(30 + colors[c]) + color_code = str(30 + context["colors"][c]) else: - color_nb = colormaps[color][colormap_idx] + color_nb = context["colormaps"][color][context["colormap_idx"]] color_code = str( color_nb ) - colormap_idx = next_in_map(color) + context["colormap_idx"] = next_in_map(color) return color_code @@ -372,19 +378,19 @@ def color_scale( name, text ): f = eval(nb) # if out of scale, do not color - if f < scale[0] or f > scale[1]: + if f < context["scale"][0] or f > context["scale"][1]: return None # normalize and scale over the nb of colors in cmap - colormap = colormaps[name] - i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(colormap)-1) ) ) + colormap = context["colormaps"][name] + i = int( math.ceil( (f - context["scale"][0]) / (context["scale"][1]-context["scale"][0]) * (len(colormap)-1) ) ) color = colormap[i] # infer mode from the color in the colormap m = mode(color) if m == 8: - color_code = str(30 + colors[color]) + color_code = str(30 + context["colors"][color]) else: color_code = str(color) @@ -399,15 +405,15 @@ def color_hash( name, text ): f = float(functools.reduce(lambda x, y: x+ord(y), hash, 0) % 101) # normalize and scale over the nb of colors in cmap - colormap = colormaps[name] - i = int( math.ceil( (f - scale[0]) / (scale[1]-scale[0]) * (len(colormap)-1) ) ) + colormap = context["colormaps"][name] + i = int( math.ceil( (f - context["scale"][0]) / (context["scale"][1]-context["scale"][0]) * (len(colormap)-1) ) ) color = colormap[i] # infer mode from the color in the colormap m = mode(color) if m == 8: - color_code = str(30 + colors[color]) + color_code = str(30 + context["colors"][color]) else: color_code = str(color) @@ -415,19 +421,19 @@ def color_hash( name, text ): def color_map(name): - global colormap_idx + global context # current color - color = colormaps[name][colormap_idx] + color = context["colormaps"][name][context["colormap_idx"]] m = mode(color) if m == 8: - color_code = str(30 + colors[color]) + color_code = str(30 + context["colors"][color]) else: color_nb = int(color) assert( 0 <= color_nb <= 255 ) color_code = str(color_nb) - colormap_idx = next_in_map(color) + context["colormap_idx"] = next_in_map(color) return color_code @@ -476,15 +482,18 @@ def colorin(text, color="red", style="normal"): start = "\033[" stop = "\033[0m" + # Escaped end markers for given color modes + endmarks = {8: ";", 256: ";38;5;"} + color_code = "" style_code = "" # Convert the style code if style == "random" or style == "Random": - style = random.choice(list(styles.keys())) + style = random.choice(list(context["styles"].keys())) else: - if style in styles: - style_code = str(styles[style]) + if style in context["styles"]: + style_code = str(context["styles"][style]) color = color.strip() m = mode(color) @@ -514,12 +523,12 @@ def colorin(text, color="red", style="normal"): # Registered colormaps should be tested after special colors, # because special tags are also registered as colormaps, # but do not have the same simple behavior. - elif color in colormaps.keys(): + elif color in context["colormaps"].keys(): color_code = color_in_colormaps( color ) # 8 colors modes - elif color in colors: - color_code = str(30 + colors[color]) + elif color in context["colors"]: + color_code = str(30 + context["colors"][color]) # hexadecimal color elif color[0] == "#": @@ -594,7 +603,7 @@ def colorup(text, pattern, color="red", style="normal", on_groups=False): >>> colorup("Faites Chier la Vache", "([A-Z])(\S+)\s", "blue", "bold,italic") '\x1b[1;34mF\x1b[0m\x1b[3;34maites\x1b[0m \x1b[1;34mC\x1b[0m\x1b[3;34mhier\x1b[0m la Vache' """ - global colormap_idx + global context if not debug: regex = re.compile(pattern) @@ -628,7 +637,7 @@ def colorup(text, pattern, color="red", style="normal", on_groups=False): # If we want to iterate colormaps on groups instead of patterns if on_groups: # Reset the counter at the beginning of each match - colormap_idx = 0 + context["colormap_idx"] = 0 # For each group index. # Note that match.groups returns a tuple (thus being indexed in [0,n[), @@ -748,8 +757,8 @@ def __args_dirty__(argv, usage=""): or argv[1] == "-h": print(usage+"\n") print("Usage:", argv[0], " [] [] []") - print("\tAvailable colors:", " ".join(colors)) - print("\tAvailable styles:", " ".join(styles)) + print("\tAvailable colors:", " ".join(context["colors"])) + print("\tAvailable styles:", " ".join(context["styles"])) print("Example:", argv[0], "'^(def)\s+(\w*).*$' blue,magenta italic,bold < colout.py") sys.exit(1) @@ -969,23 +978,23 @@ if __name__ == "__main__": # print("Available resources:") for res in asked: if "style" in res or "all" in res: - print("STYLES: %s" % join_sort(styles) ) + print("STYLES: %s" % join_sort(context["styles"]) ) if "color" in res or "all" in res: - print("COLORS: %s" % join_sort(colors) ) + print("COLORS: %s" % join_sort(context["colors"]) ) if "special" in res or "all" in res: print("SPECIAL: %s" % join_sort(["random", "Random", "scale", "Scale", "hash", "Hash", "colormap"]) ) if "theme" in res or "all" in res: if len(themes) > 0: - print("THEMES: %s" % join_sort(themes.keys()) ) + print("THEMES: %s" % join_sort(context["themes"].keys()) ) else: print("NO THEME") if "colormap" in res or "all" in res: - if len(colormaps) > 0: - print("COLORMAPS: %s" % join_sort(colormaps) ) + if len(context["colormaps"]) > 0: + print("COLORMAPS: %s" % join_sort(context["colormaps"]) ) else: print("NO COLORMAPS") @@ -1003,32 +1012,32 @@ if __name__ == "__main__": try: if myscale: - scale = tuple([float(i) for i in myscale.split(",")]) - logging.debug("user-defined scale: %f,%f" % scale) + context["scale"] = tuple([float(i) for i in myscale.split(",")]) + logging.debug("user-defined scale: %f,%f" % context["scale"]) # Default color maps if default_colormap: - if default_colormap not in colormaps: + if default_colormap not in context["colormaps"]: cmap = default_colormap.split(",") - elif default_colormap in colormaps: - cmap = colormaps[default_colormap] + elif default_colormap in context["colormaps"]: + cmap = context["colormaps"][default_colormap] set_special_colormaps( cmap ) - logging.debug("user-defined special colormap: %s" % ",".join([str(i) for i in cmap]) ) # explicit color map - if as_colormap is True and color not in colormaps: - colormaps["Default"] = color.split(",") # replace the colormap by the given colors - colormaps["default"] = color.split(",") # replace the colormap by the given colors + if as_colormap is True and color not in context["colormaps"]: + context["colormaps"]["Default"] = color.split(",") # replace the colormap by the given colors + context["colormaps"]["default"] = color.split(",") # replace the colormap by the given colors color = "colormap" # use the keyword to switch to colormap instead of list of colors - logging.debug("used-defined default colormap: %s" % ",".join(colormaps["Default"]) ) + logging.debug("used-defined default colormap: %s" % ",".join(context["colormaps"]["Default"]) ) # if theme if as_theme: logging.debug( "asked for theme: %s" % pattern ) - assert(pattern in themes.keys()) - write_all( as_all, sys.stdin, sys.stdout, colortheme, themes[pattern].theme() ) + assert(pattern in context["themes"].keys()) + context,theme = context["themes"][pattern].theme(context) + write_all( as_all, sys.stdin, sys.stdout, colortheme, theme ) # if pygments elif as_source: @@ -1055,6 +1064,11 @@ if __name__ == "__main__": write_all( as_all, sys.stdin, sys.stdout, colorup, pattern, color, style, on_groups ) except UnknownColor as e: + if debug: + import traceback + for var in context: + print(var,context[var]) + print(traceback.format_exc()) logging.error("unknown color: %s" % e ) sys.exit( error_codes["UnknownColor"] ) diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index d2efefa..cca396f 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -1,5 +1,5 @@ -def theme(): +def theme(context): # CMake theme: # actions performing in cyan performing="cyan" @@ -8,7 +8,11 @@ def theme(): # actions taking an unknown time untimed="blue" - return [ + # A palette that goes: purple, orange, white + percs = [45, 39, 33, 27, 21, 57, 63, 62, 98, 97, 133, 132, 138, 173, 172, 208, 214, 220, 226, 228, 229, 230, 231, 255] + context["colormaps"]["Scale"] = percs + + return context,[ # Configure... [ "^--.*works", performed ], [ "^--.*done", performed ], diff --git a/colout/colout_g++.py b/colout/colout_g++.py index 17f9952..848569f 100644 --- a/colout/colout_g++.py +++ b/colout/colout_g++.py @@ -3,7 +3,7 @@ def default_gettext( msg ): return msg -def theme(): +def theme(context): import os import gettext import locale @@ -33,7 +33,7 @@ def theme(): qo = "['`]" qc = "'" - return [ + return context,[ # Command line [ "[/\s]([cg]\+\+-*[0-9]*\.*[0-9]*)", "white", "bold" ], [ "\s(\-D)(\s*[^\s]+\s)", "none,green", "normal,bold" ], diff --git a/colout/colout_javac.py b/colout/colout_javac.py index c8fbfb4..0acaba0 100644 --- a/colout/colout_javac.py +++ b/colout/colout_javac.py @@ -1,8 +1,8 @@ #encoding: utf-8 -def theme(): +def theme(context): style="monokai" - return [ + return context,[ [ "^(.*\.java):([0-9]+):\s*(warning:.*)$", "white,yellow,magenta", "normal,normal,bold" ], [ "^(.*\.java):([0-9]+):(.*)$", "white,yellow,red", "normal,normal,bold" ], [ "^(symbol|location)\s*:\s*(.*)$", "blue,Java", "bold,"+style ], diff --git a/colout/colout_json.py b/colout/colout_json.py index 5eaefeb..62ddee4 100644 --- a/colout/colout_json.py +++ b/colout/colout_json.py @@ -1,8 +1,8 @@ -def theme(): +def theme(context): # This theme expect a formatted JSON input, with items spread across lines. # See tools like "python -m json.tool" or "json_xs" - return [ + return context,[ [ '[\[\]{}],*\s*\n' ], [ '" (:) ', "yellow" ], [ '[\]}"](,)', "yellow" ], diff --git a/colout/colout_latex.py b/colout/colout_latex.py index dbd96b5..cc6210e 100644 --- a/colout/colout_latex.py +++ b/colout/colout_latex.py @@ -1,6 +1,6 @@ -def theme(): - return [ +def theme(context): + return context,[ # LaTeX ["This is .*TeX.*$", "white", "bold"], ["(LaTeX Warning): (.*) `(.*)' on page [0-9] (.*) on input line [0-9]+.$", diff --git a/colout/colout_perm.py b/colout/colout_perm.py index 3d2ed6a..c03cf96 100644 --- a/colout/colout_perm.py +++ b/colout/colout_perm.py @@ -1,8 +1,8 @@ -def theme(): +def theme(context): p="([rwxs-])" reg="^([d-])"+p*9+"\s.*$" colors="blue"+",green"*3+",yellow"*3+",red"*3 styles="normal"+ ",normal,italic,bold"*3 - return [ [reg, colors, styles] ] + return context,[ [reg, colors, styles] ] diff --git a/colout/colout_python.py b/colout/colout_python.py index cdbbb3e..3623d04 100644 --- a/colout/colout_python.py +++ b/colout/colout_python.py @@ -1,6 +1,6 @@ -def theme(): - return [ +def theme(context): + return context,[ # traceback header ["^Traceback .*$", "blue" ], # File, line, in From 9d4fde40ba5980f13cddc16d2a54d386c06580d7 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 25 Apr 2014 14:02:36 +0200 Subject: [PATCH 031/116] Special `random` color set can be changed as a colormap Add random among the colormaps, if this colormap is changed, it will pick random colors in it. --- colout/colout.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 3b83169..f73533c 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -52,9 +52,13 @@ context["colormaps"] = { "rainbow" : ["magenta", "blue", "cyan", "green", "yellow", "red"], "Rainbow" : [92, 93, 57, 21, 27, 33, 39, 45, 51, 50, 49, 48, 47, 46, 82, 118, 154, 190, 226, 220, 214, 208, 202, 196], - # from magenta to red, with white in the middle + # From magenta to red, with white in the middle "spectrum" : ["magenta", "blue", "cyan", "white", "green", "yellow", "red"], - "Spectrum" : [91, 92, 56, 57, 21, 27, 26, 32, 31, 37, 36, 35, 41, 40, 41, 77, 83, 84, 120, 121, 157, 194, 231, 254, 255, 231, 230, 229, 228, 227, 226, 220, 214, 208, 202, 196] + "Spectrum" : [91, 92, 56, 57, 21, 27, 26, 32, 31, 37, 36, 35, 41, 40, 41, 77, 83, 84, 120, 121, 157, 194, 231, 254, 255, 231, 230, 229, 228, 227, 226, 220, 214, 208, 202, 196], + + # All the colors are available for the default `random` special + "random" : context["colors"], + "Random" : list(range(256)) } # colormaps context["colormaps"]["scale"] = context["colormaps"]["spectrum"] @@ -94,6 +98,8 @@ def set_special_colormaps( cmap ): context["colormaps"]["Hash"] = cmap context["colormaps"]["default"] = cmap context["colormaps"]["Default"] = cmap + context["colormaps"]["random"] = cmap + context["colormaps"]["Random"] = cmap logging.debug("user-defined special colormap: %s" % ",".join([str(i) for i in cmap]) ) @@ -320,13 +326,14 @@ def next_in_map( color ): def color_random( color ): + global context m = mode(color) if m == 8: - color_code = random.choice(list(context["colors"].values())) + color_code = random.choice(context["colormaps"]["random"]) color_code = str(30 + color_code) elif m == 256: - color_nb = random.randint(0, 255) + color_nb = random.choice(context["colormaps"]["Random"]) color_code = str(color_nb) return color_code From 56f9f0d7e6f810b7edbcb8ed934004f289696aa4 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 25 Apr 2014 14:28:15 +0200 Subject: [PATCH 032/116] bugfix: random in 8-colors mode with user-defined default colormap --- README.md | 22 +++++++++++----------- colout/colout.py | 5 +++-- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index c49e5db..f13ae26 100644 --- a/README.md +++ b/README.md @@ -22,18 +22,19 @@ groups. Available colors are: blue, black, yellow, cyan, green, magenta, white, red, rainbow, random, Random, Spectrum, spectrum, scale, Scale, hash, Hash, none, an -RGB hexadecimal triplet or any number between 0 and 255. +RGB hexadecimal triplet (`#11aaff`, for example) or any number between 0 and 255. Available styles are: normal, bold, faint, italic, underline, blink, rapid\_blink, reverse, conceal or random (some styles may have no effect, depending on your terminal). -`rainbow` will cycle over a 6 colors rainbow at each matching pattern. -`Rainbow` will do the same over 24 colors (this requires a terminal that supports -the 256 color escape sequences). +`rainbow` will cycle over a the default colormap at each matching pattern. +`Rainbow` will do the same over the default colormap for the 256-colors mode +(this requires a terminal that supports the 256 color escape sequences). -`Random` will color each matching pattern with a random color among the 255 -available in the ANSI table. `random` will do the same in 8 colors mode. +`Random` will color each matching pattern with a random color among the default colormap +(the 255 available in the ANSI table, by default). +`random` will do the same in 8 colors mode. `spectrum` and `Spectrum` are like rainbows, but with more colors (8 and 36 colors). @@ -133,12 +134,11 @@ Gentoo Search for additional palettes (\*.gpl files) in this directory. * `-d COLORMAP`, `--default COLORMAP`: - When using special colormaps (`scale` or `hash`), use this COLORMAP instead of the `spectrum` one. + When using special colormaps (`random`, `scale` or `hash`), use this COLORMAP instead of the default one. This can be either one of the available colormaps or a comma-separated list of colors. - WARNING: be sure to specify a default colormap that is compatible with the special colormap's mode. - For instance, if you indicate `scale`, you can use `-d red,green,blue`, but `-d 12,13,14` will fail. - Also, if you specify `Scale`, you cannot use `-d red,green,blue`, but `-d Rainbow` will work. - Similarly, external palettes are converted from RGB to 256-ANSI and will thus not work if you use + WARNING: be sure to specify a default colormap that is compatible with the special colormap's mode, + or else the colors may not appear the same. + Also, external palettes are converted from RGB to 256-ANSI and will thus not work if you use them as default colormaps for a 8-colors mode special color. * `-r TYPE(S)`, `--resources TYPE(S)`: diff --git a/colout/colout.py b/colout/colout.py index f73533c..3d3ebc0 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -329,7 +329,8 @@ def color_random( color ): global context m = mode(color) if m == 8: - color_code = random.choice(context["colormaps"]["random"]) + color_name = random.choice(context["colormaps"]["random"]) + color_code = context["colors"][color_name] color_code = str(30 + color_code) elif m == 256: @@ -860,7 +861,7 @@ def __args_parse__(argv, usage=""): help="Search for additional palettes (*.gpl files) in the given directory") parser.add_argument("-d", "--default", metavar="COLORMAP", default=None, - help="When using special colormaps (`scale` or `hash`), use this COLORMAP. \ + help="When using special colormaps (`random`, `scale` or `hash`), use this COLORMAP. \ This can be either one of the available colormaps or a comma-separated list of colors. \ WARNING: be sure to specify a default colormap that is compatible with the special colormap's mode.") From 39674665d83b8d183b2038692643f58526e67b57 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 25 Apr 2014 14:37:12 +0200 Subject: [PATCH 033/116] bugfix: use the full `scale` range Was using scale[1:] colors instead of scale[:] --- colout/colout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/colout/colout.py b/colout/colout.py index 3d3ebc0..293ed2c 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -391,7 +391,7 @@ def color_scale( name, text ): # normalize and scale over the nb of colors in cmap colormap = context["colormaps"][name] - i = int( math.ceil( (f - context["scale"][0]) / (context["scale"][1]-context["scale"][0]) * (len(colormap)-1) ) ) + i = int( math.ceil( (f - context["scale"][0]) / (context["scale"][1]-context["scale"][0]) * len(colormap) ) ) - 1 color = colormap[i] # infer mode from the color in the colormap From d0ef6abdc6010e0cc99833126d696842eaa6380b Mon Sep 17 00:00:00 2001 From: Philippe Daouadi Date: Fri, 25 Apr 2014 21:39:58 +0200 Subject: [PATCH 034/116] bugfix: start scale at right color --- colout/colout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/colout/colout.py b/colout/colout.py index 293ed2c..3d3ebc0 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -391,7 +391,7 @@ def color_scale( name, text ): # normalize and scale over the nb of colors in cmap colormap = context["colormaps"][name] - i = int( math.ceil( (f - context["scale"][0]) / (context["scale"][1]-context["scale"][0]) * len(colormap) ) ) - 1 + i = int( math.ceil( (f - context["scale"][0]) / (context["scale"][1]-context["scale"][0]) * (len(colormap)-1) ) ) color = colormap[i] # infer mode from the color in the colormap From 1f9125af88ad9d13a7de6f972032dd810da300d6 Mon Sep 17 00:00:00 2001 From: Philippe Daouadi Date: Fri, 25 Apr 2014 21:42:08 +0200 Subject: [PATCH 035/116] bugfix: crash when using fractions --- colout/colout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/colout/colout.py b/colout/colout.py index 3d3ebc0..17ef20f 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -377,7 +377,7 @@ def color_scale( name, text ): import babel.numbers as bn try: f = float(bn.parse_decimal(nb)) - except NumberFormatError: + except bn.NumberFormatError: f = eval(nb) # Note: in python2, `eval(2/3)` would produce `0`, in python3 `0.666` except ImportError: try: From d437e463648d194763ae0e90440e8a37cc0dfbdf Mon Sep 17 00:00:00 2001 From: Philippe Daouadi Date: Fri, 25 Apr 2014 21:46:49 +0200 Subject: [PATCH 036/116] Make cmake colouring work with fractions --- colout/colout.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 17ef20f..ede0d37 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -372,26 +372,33 @@ def color_scale( name, text ): # if not, use python itself, # if thoses fails, try to `eval` the string # (this allow strings like "1/2+0.9*2") + f = None try: # babel is a specialized module import babel.numbers as bn try: f = float(bn.parse_decimal(nb)) except bn.NumberFormatError: - f = eval(nb) # Note: in python2, `eval(2/3)` would produce `0`, in python3 `0.666` + pass except ImportError: try: f = float(nb) except ValueError: - f = eval(nb) + pass + if f is not None: + # normalize with scale if it's a number + f = (f - context["scale"][0]) / (context["scale"][1]-context["scale"][0]) + else: + # interpret as float between 0 and 1 otherwise + f = eval(nb) # if out of scale, do not color - if f < context["scale"][0] or f > context["scale"][1]: + if f < 0 or f > 1: return None # normalize and scale over the nb of colors in cmap colormap = context["colormaps"][name] - i = int( math.ceil( (f - context["scale"][0]) / (context["scale"][1]-context["scale"][0]) * (len(colormap)-1) ) ) + i = int( math.ceil( f * (len(colormap)-1) ) ) color = colormap[i] # infer mode from the color in the colormap From 200f1cd1f3f245716f14babe0c8ac34a544e92b2 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 2 May 2014 19:08:57 +0200 Subject: [PATCH 037/116] bugfix: test lexers in context --- colout/colout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/colout/colout.py b/colout/colout.py index 293ed2c..41346c6 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -551,7 +551,7 @@ def colorin(text, color="red", style="normal"): color_code = str(color_nb) # programming language - elif color.lower() in lexers: + elif color.lower() in context["lexers"]: # bypass color encoding and return text colored by the lexer return color_lexer(color,style,text) From 9fd0df9963624dd3fc883ac80be6fdf13a4cada2 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 2 May 2014 19:30:26 +0200 Subject: [PATCH 038/116] Separated Ninja theme with correct handling of scale Add a flag for user defined colormaps in the context. Do not overload the colormap if the user changed it. Inherit the Ninja theme from the cmake one. Explanations about themes in the README. --- README.md | 19 +++++++++++++++++++ colout/colout.py | 3 +++ colout/colout_cmake.py | 15 ++++++--------- colout/colout_ninja.py | 19 +++++++++++++++++++ 4 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 colout/colout_ninja.py diff --git a/README.md b/README.md index f13ae26..065af82 100644 --- a/README.md +++ b/README.md @@ -266,3 +266,22 @@ cmake and g++ themes: You then can use the `cm` alias as a prefix to your build command, for example: `cm make test` + +### Themes + +You can easily add your own theme to colout. +A theme is basically a module with a function named `theme` that take the configuration context as an argument and +return back the (modified) context and a list of triplets. +Each triplet figures the same arguments than those of the command line interface. + + def theme(context): + return context,[ [regexp, colors, styles] ] + +With the context dictionary at hand, you have access to the internal configuration of colout, you can thus change colormaps for +special keywords, the scale, even the available colors, styles or themes. + +See the cmake theme for how to modify an existing colormap if (and only if) the user didn't ask for an +alternative one. +See the ninja theme for how to extend an existing theme with more regexps and a different configuration. +See the gcc theme for an example of how to use the localization of existing softwares to build translated regexp. + diff --git a/colout/colout.py b/colout/colout.py index 41346c6..94b06ba 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -68,6 +68,8 @@ context["colormaps"]["Hash"] = context["colormaps"]["Rainbow"] context["colormaps"]["default"] = context["colormaps"]["spectrum"] context["colormaps"]["Default"] = context["colormaps"]["Spectrum"] +context["user_defined_colormaps"] = False + context["colormap_idx"] = 0 context["scale"] = (0,100) @@ -100,6 +102,7 @@ def set_special_colormaps( cmap ): context["colormaps"]["Default"] = cmap context["colormaps"]["random"] = cmap context["colormaps"]["Random"] = cmap + context["user_defined_colormaps"] = True logging.debug("user-defined special colormap: %s" % ",".join([str(i) for i in cmap]) ) diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index cca396f..68ff06e 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -8,9 +8,11 @@ def theme(context): # actions taking an unknown time untimed="blue" - # A palette that goes: purple, orange, white - percs = [45, 39, 33, 27, 21, 57, 63, 62, 98, 97, 133, 132, 138, 173, 172, 208, 214, 220, 226, 228, 229, 230, 231, 255] - context["colormaps"]["Scale"] = percs + # If the user do not ask for his own colormap + if not context["user_defined_colormaps"]: + # A palette that goes: purple, orange, white + percs = [45, 39, 33, 27, 21, 57, 63, 62, 98, 97, 133, 132, 138, 173, 172, 208, 214, 220, 226, 228, 229, 230, 231, 255] + context["colormaps"]["Scale"] = percs return context,[ # Configure... @@ -31,9 +33,6 @@ def theme(context): # Link (make) [ "^(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", untimed, "normal,normal,bold" ], - # Link (ninja) - [ "^\[[0-9/]+\]\s?(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", - untimed, "normal,normal,bold" ], # [percent] Built [ "^\[\s*[0-9/]+%?\]\s(Built target)(\s.*)$", performed, "normal,bold" ], @@ -47,7 +46,5 @@ def theme(context): [ "make\[[0-9]+\].*", "yellow"], [ "(make: \*\*\* \[.+\] )(.* [0-9]+)", "red", "normal,bold"], # progress percentage (make) - [ "^(\[\s*[0-9]+%\])","Scale" ], - # progress percentage (ninja) - [ "^(\[[0-9]+/[0-9]+\])","Scale" ] + [ "^(\[\s*[0-9]+%\])","Scale" ] ] diff --git a/colout/colout_ninja.py b/colout/colout_ninja.py new file mode 100644 index 0000000..1d416c9 --- /dev/null +++ b/colout/colout_ninja.py @@ -0,0 +1,19 @@ + +import colout_cmake + +def theme(context): + # Ninja theme + + # Inherit from the CMake theme + context,th = colout_cmake.theme(context) + + # Because Ninja note progress as a fraction, we do not want the scale of a percentage + context["scale"] = (0,1) + + # Link (ninja) + th.append( [ "^\[[0-9/]+\]\s?(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", + "blue", "normal,normal,bold" ] ) + # progress percentage (ninja) + th.append( [ "^(\[[0-9]+/[0-9]+\])","Scale" ] ) + + return context,th From 4cdf3e609df037d313e74c333197d8ea53edc6cb Mon Sep 17 00:00:00 2001 From: nojhan Date: Sat, 21 Jun 2014 11:30:32 +0200 Subject: [PATCH 039/116] bugfix: debug variable corret declaration --- colout/colout.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/colout/colout.py b/colout/colout.py index 94b06ba..5973fc9 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -28,6 +28,7 @@ signal.signal( signal.SIGPIPE, signal.SIG_DFL ) ############################################################################### context = {} +debug = False # Available styles context["styles"] = { @@ -615,6 +616,7 @@ def colorup(text, pattern, color="red", style="normal", on_groups=False): '\x1b[1;34mF\x1b[0m\x1b[3;34maites\x1b[0m \x1b[1;34mC\x1b[0m\x1b[3;34mhier\x1b[0m la Vache' """ global context + global debug if not debug: regex = re.compile(pattern) @@ -906,7 +908,6 @@ def write_all( as_all, stream_in, stream_out, function, *args ): if __name__ == "__main__": - global debug error_codes = {"UnknownColor":1, "DuplicatedPalette":2} usage = "A regular expression based formatter that color up an arbitrary text stream." From 5c626318599874f2549001fa8a12c98b079d8fab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Sad=C5=82ocha?= Date: Sat, 28 Jun 2014 13:51:49 +0200 Subject: [PATCH 040/116] Fix typos Changes occurrences of 'Ouput' to 'Output' --- colout/colout.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 8ac771b..248b9b7 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 #encoding: utf-8 -# Color Up Arbitrary Command Ouput +# Color Up Arbitrary Command Output # Licensed under the GPL version 3 # 2012 (c) nojhan diff --git a/setup.py b/setup.py index 2ad8b72..6af0562 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ requires = ['argparse', 'pygments', 'babel'] setup( name='colout', version='0.1', - description='Color Up Arbitrary Command Ouput.', + description='Color Up Arbitrary Command Output.', long_description=open('README.md').read(), author='nojhan', author_email='nojhan@nojhan.net', From ddaab0b1dbe13bda6447fce50f6a15ba4b2bbc7e Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 16 Sep 2014 10:28:47 +0200 Subject: [PATCH 041/116] add a valgrind theme --- colout/colout_valgrind.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 colout/colout_valgrind.py diff --git a/colout/colout_valgrind.py b/colout/colout_valgrind.py new file mode 100644 index 0000000..fc614d2 --- /dev/null +++ b/colout/colout_valgrind.py @@ -0,0 +1,24 @@ +#encoding: utf-8 + +def theme(context): + + return context, [ + # section title + ["^(==[0-9]+==\s{1}\S+.*)$","red",""], + # section explanation + ["^==[0-9]+==\s{2}(\S+.*)$","orange",""], + # locations adresses + ["^==[0-9]+==\s{4}([atby]{2}) (0x)([^:]*): (\S+) ", + "blue,blue,blue,none", "normal"], + # locations: library + ["\(in (.*)\)", "cyan", "normal"], + # locations: file + ["\(([^\.]*\.[^:]+):([0-9]+)\)", "white,yellow", "bold,normal"], + # leak summary + ["^==[0-9]+==\s{4}(definitely lost): .* (in) .*","red","bold"], + ["^==[0-9]+==\s{4}(indirectly lost): .* (in) .*","orange","bold"], + ["^==[0-9]+==\s{6}(possibly lost): .* (in) .*","yellow","bold"], + ["^==[0-9]+==\s{4}(still reachable): .* (in) .*","green","bold"], + ["^==[0-9]+==\s{9}(suppressed): .* (in) .*","cyan","bold"], + ] + From 92237172131f10015a3b200ac2220a2778471740 Mon Sep 17 00:00:00 2001 From: nojhan Date: Sun, 28 Sep 2014 23:02:44 +0200 Subject: [PATCH 042/116] more thoughts about arithmetics in the readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 065af82..ea7d616 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,8 @@ Gentoo * `-l min,max`, `--scale min,max`: When using the 'scale' colormap, parse matches as decimal numbers (taking your locale into account) - and apply the rainbow colormap linearly between the given min,max (0,100, by default). + or as arithmetic expression (like "1+2/0.9\*3") and apply the rainbow colormap linearly + between the given min,max (0,100, by default). * `-a`, `--all`: Color the whole input at once instead of line per line From f7ae2118e71bde417179862de16c8c93c6fb4213 Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 8 Oct 2014 11:10:35 +0200 Subject: [PATCH 043/116] bugfix printing ressources Use the context --- colout/colout.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 94b06ba..0b7052e 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -998,7 +998,7 @@ if __name__ == "__main__": print("SPECIAL: %s" % join_sort(["random", "Random", "scale", "Scale", "hash", "Hash", "colormap"]) ) if "theme" in res or "all" in res: - if len(themes) > 0: + if len(context["themes"]) > 0: print("THEMES: %s" % join_sort(context["themes"].keys()) ) else: print("NO THEME") @@ -1010,8 +1010,8 @@ if __name__ == "__main__": print("NO COLORMAPS") if "lexer" in res or "all" in res: - if len(lexers) > 0: - print("SYNTAX COLORING: %s" % join_sort(lexers) ) + if len(context["lexers"]) > 0: + print("SYNTAX COLORING: %s" % join_sort(context["lexers"]) ) else: print("NO SYNTAX COLORING (check that python3-pygments is installed)") From d47272663db4d8736bfa8836a36b68ab1af6bd90 Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 8 Oct 2014 11:11:00 +0200 Subject: [PATCH 044/116] enhunce the valgrind theme less red sections highlight null adresses --- colout/colout_valgrind.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/colout/colout_valgrind.py b/colout/colout_valgrind.py index fc614d2..425a7e8 100644 --- a/colout/colout_valgrind.py +++ b/colout/colout_valgrind.py @@ -4,11 +4,18 @@ def theme(context): return context, [ # section title + ["^(==[0-9]+==\s{1})(Memcheck|Copyright|Using)(.*)$","blue",""], + ["^(==[0-9]+==\s{1}Command: )(\S*)(.*)$","green,white","normal,bold,normal"], + ["^(==[0-9]+==\s{1})(HEAP SUMMARY:)(.*)$","green",""], + ["^(==[0-9]+==\s{1})(All heap blocks were freed)(.*)$","green",""], + ["^(==[0-9]+==\s{1})(For counts of detected and suppressed errors, rerun with: -v)(.*)$","blue",""], ["^(==[0-9]+==\s{1}\S+.*)$","red",""], # section explanation ["^==[0-9]+==\s{2}(\S+.*)$","orange",""], # locations adresses - ["^==[0-9]+==\s{4}([atby]{2}) (0x)([^:]*): (\S+) ", + ["^==[0-9]+==\s{4}([atby]{2}) (0x0): (\?{3})", + "blue,yellow,red", "normal,normal,bold"], + ["^==[0-9]+==\s{4}([atby]{2}) (0x)([^:]*:) (\S+)", "blue,blue,blue,none", "normal"], # locations: library ["\(in (.*)\)", "cyan", "normal"], From 963d6addf17cb4a4653aa6a96703768abf01a1ec Mon Sep 17 00:00:00 2001 From: nojhan Date: Thu, 16 Oct 2014 19:04:50 +0200 Subject: [PATCH 045/116] bugfix lexers --- colout/colout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/colout/colout.py b/colout/colout.py index 0b7052e..19dcf96 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -1053,7 +1053,7 @@ if __name__ == "__main__": # if pygments elif as_source: logging.debug("asked for lexer: %s" % pattern.lower()) - assert(pattern.lower() in lexers) + assert(pattern.lower() in context["lexers"]) lexer = get_lexer_by_name(pattern.lower()) # Python => 256 colors, python => 8 colors ask_256 = pattern[0].isupper() From 67f79205204d215bcc5f58cc117404831d2512f3 Mon Sep 17 00:00:00 2001 From: nojhan Date: Thu, 16 Oct 2014 19:04:59 +0200 Subject: [PATCH 046/116] better valgrind theme --- colout/colout_valgrind.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/colout/colout_valgrind.py b/colout/colout_valgrind.py index 425a7e8..fe95982 100644 --- a/colout/colout_valgrind.py +++ b/colout/colout_valgrind.py @@ -5,10 +5,12 @@ def theme(context): return context, [ # section title ["^(==[0-9]+==\s{1})(Memcheck|Copyright|Using)(.*)$","blue",""], + ["^(==[0-9]+==\s{1})(Warning)(.*)$","magenta",""], ["^(==[0-9]+==\s{1}Command: )(\S*)(.*)$","green,white","normal,bold,normal"], ["^(==[0-9]+==\s{1})(HEAP SUMMARY:)(.*)$","green",""], ["^(==[0-9]+==\s{1})(All heap blocks were freed)(.*)$","green",""], - ["^(==[0-9]+==\s{1})(For counts of detected and suppressed errors, rerun with: -v)(.*)$","blue",""], + ["^(==[0-9]+==\s{1})(.*[rR]erun.*)$","blue",""], + ["^(==[0-9]+==\s{1})(Use --.*)$","blue",""], ["^(==[0-9]+==\s{1}\S+.*)$","red",""], # section explanation ["^==[0-9]+==\s{2}(\S+.*)$","orange",""], From b193ce4885dcd312f2a8a49deaec38992d469000 Mon Sep 17 00:00:00 2001 From: nojhan Date: Thu, 16 Oct 2014 20:07:41 +0200 Subject: [PATCH 047/116] An example config for coloring GDB sessions Use a config hack to plug colout on GDB output. --- colout/example.gdbinit | 86 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 colout/example.gdbinit diff --git a/colout/example.gdbinit b/colout/example.gdbinit new file mode 100644 index 0000000..0abde94 --- /dev/null +++ b/colout/example.gdbinit @@ -0,0 +1,86 @@ + +# Don't wrap line or the coloring regexp won't work. +set width 0 + +# Create a named pipe to get outputs from gdb +shell test -e /tmp/coloutPipe && rm /tmp/coloutPipe +shell mkfifo /tmp/coloutPipe + +# A yellow prompt +set prompt \033[0;33mgdb>>>\033[0m + +define logging_on + # Instead of printing on stdout only, log everything... + set logging redirect on + # ... in our named pipe. + set logging on /tmp/coloutPipe +end + +define logging_off + set logging off + set logging redirect off + # Because both gdb and our commands are writing on the same pipe at the same + # time, it is more than probable that gdb will end before our (higher level) + # commands. The gdb prompt will thus render before the result of the command, + # which is highly akward. To prevent this, we need to wait before displaying + # the prompt again. The more your commands are complex, the higher you will + # need to set this. + shell sleep 0.4s +end + + +define hook-break + # Don't forget to run the command in the background + shell cat /tmp/coloutPipe | colout "(Breakpoint) ([0-9]+) at (0x\S+): file (.+/)([^/]+), line ([0-9]+)." blue,red,cyan,none,white,yellow normal,bold,normal,normal,bold,normal & + # You should start to consume the pipe before actually redirecting the command output into it. + logging_on +end +define hookpost-break + logging_off +end + + +define hook-continue + shell cat /tmp/coloutPipe | colout "^Program received signal.*$" | colout "^(Breakpoint) ([0-9]+),*\s+(0x\S+ )*(in )*(\S+) (\(.*\)) at (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" red,red,blue,none,green,cpp,none,white,white,yellow normal,bold,normal,normal,bold,normal,normal,bold,bold,bold | colout "^[0-9]+\s+(.*)$" Cpp & + logging_on +end +define hookpost-continue + logging_off +end + + +# Full syntax highlighting for the `list` command. +define hook-list + shell cat /tmp/coloutPipe | colout --all --source Cpp & + logging_on +end +# Don't forget the hookpost- or next coloring commands will fail. +define hookpost-list + logging_off +end + + +define hook-backtrace + # match the [path]file[.ext]: (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)) + shell cat /tmp/coloutPipe | colout "^(#)([0-9]+)\s+(0x\S+ )*(in )*(\S+) (\(.*\)) at (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" red,red,blue,none,green,cpp,none,white,white,yellow normal,bold,normal,normal,bold,normal,normal,bold,bold,bold & + logging_on +end +define hookpost-backtrace + logging_off +end + + +define info hook-breakpoints + shell cat /tmp/coloutPipe | colout "^([0-9]+)" red bold | colout "\sy\s" green | colout "\sn\s" red | colout "breakpoint" green normal | colout "watchpoint" orange normal | colout "\s0x\S+\s" blue normal | colout "(.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)$" none,white,white,yellow normal,bold & + logging_on +end +define info hookpost-breakpoints + logging_off +end + + +# Don't forget to clean the adhoc pipe. +define hook-quit + shell rm -f /tmp/coloutPipe +end + From f80d3e7642be124bbd709ad1a30b5bc762b9c931 Mon Sep 17 00:00:00 2001 From: DainDwarf Date: Fri, 21 Nov 2014 14:32:47 +0100 Subject: [PATCH 048/116] Update README.md The text "COLOR" does not appear on github -> I propose using *COLOR* instead of --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ea7d616..3cc48a6 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ colout(1) -- Color Up Arbitrary Command Output ## DESCRIPTION `colout` read lines of text stream on the standard input and output characters -matching a given regular expression *PATTERN* in given and *STYLE*. +matching a given regular expression *PATTERN* in given *COLOR* and *STYLE*. If groups are specified in the regular expression pattern, only them are taken into account, else the whole matching pattern is colored. From a39bc4022b0a8628858f3e7d8b14dfca2e027185 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 19 Dec 2014 11:07:15 +0100 Subject: [PATCH 049/116] add gdb hooks: run and line, better continue --- colout/example.gdbinit | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/colout/example.gdbinit b/colout/example.gdbinit index 0abde94..e4c3116 100644 --- a/colout/example.gdbinit +++ b/colout/example.gdbinit @@ -40,8 +40,17 @@ define hookpost-break end +define hook-run + shell cat /tmp/coloutPipe | colout "^(Breakpoint) ([0-9]+),*\s+(0x\S+ )*(in )*(\S+) (\(.*\)) at (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" red,red,blue,none,green,cpp,none,white,white,yellow normal,bold,normal,normal,bold,normal,normal,bold,bold,bold | colout "^(Starting program): (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" green,none,white,white,yellow normal,normal,bold,bold,bold | colout "^[0-9]+\s+(.*)$" Cpp & + logging_on +end +define hookpost-run + logging_off +end + + define hook-continue - shell cat /tmp/coloutPipe | colout "^Program received signal.*$" | colout "^(Breakpoint) ([0-9]+),*\s+(0x\S+ )*(in )*(\S+) (\(.*\)) at (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" red,red,blue,none,green,cpp,none,white,white,yellow normal,bold,normal,normal,bold,normal,normal,bold,bold,bold | colout "^[0-9]+\s+(.*)$" Cpp & + shell cat /tmp/coloutPipe | colout "^(Program received signal )(.*)(,.*)$" yellow,red,yellow bold | colout "^(Breakpoint) ([0-9]+),*\s+(0x\S+ )*(in )*(\S+) (\(.*\)) at (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" red,red,blue,none,green,cpp,none,white,white,yellow normal,bold,normal,normal,bold,normal,normal,bold,bold,bold | colout "^[0-9]+\s+(.*)$" Cpp & logging_on end define hookpost-continue @@ -79,6 +88,15 @@ define info hookpost-breakpoints end +define info hook-line + shell cat /tmp/coloutPipe | colout "^Line ([0-9]+) of \"(.*/)?(?:$|(.+?)(?:(\.[^.]*)|))\"" yellow,none,white,white bold | colout "(0x\S+) <(\S+)\+([0-9]+)>" blue,green,blue normal & + logging_on +end +define info hookpost-line + logging_off +end + + # Don't forget to clean the adhoc pipe. define hook-quit shell rm -f /tmp/coloutPipe From 17420be917de5054676448e92f5f19dea3aebce5 Mon Sep 17 00:00:00 2001 From: Scott Lawrence Date: Thu, 2 Apr 2015 10:34:51 -0400 Subject: [PATCH 050/116] fix for Issue #75: add the --themes-dir to the module import path --- colout/colout.py | 1 + 1 file changed, 1 insertion(+) diff --git a/colout/colout.py b/colout/colout.py index 2d232ba..c68c948 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -215,6 +215,7 @@ def load_themes( themes_dir): global context logging.debug("search for themes in: %s" % themes_dir) os.chdir( themes_dir ) + sys.path.append( themes_dir ) # load available themes for f in glob.iglob("colout_*.py"): From 7338d36f37867ccba285f6c7ff2abef54a15b07e Mon Sep 17 00:00:00 2001 From: nojhan Date: Sun, 29 May 2016 17:32:05 +0200 Subject: [PATCH 051/116] More colors for cmake building log Hash the subdirs and do not color extension. --- colout/colout_cmake.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index 68ff06e..24b544f 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -33,12 +33,15 @@ def theme(context): # Link (make) [ "^(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", untimed, "normal,normal,bold" ], + # [percent] Creating something + [ "^\[\s*[0-9/]+%?\]\s(.*Creating.*)$", + performing, "normal" ], # [percent] Built [ "^\[\s*[0-9/]+%?\]\s(Built target)(\s.*)$", performed, "normal,bold" ], # [percent] Building - [ "^\[\s*[0-9/]+%?\]\s(Building \w* object)(\s+.*/)([-\w]+.c.*)(.o)$", - performing, "normal,normal,bold,normal"], + [ "^\[\s*[0-9/]+%?\]\s(Building \w* object)\s+(.*)(\.dir)(.*/)([-\w]+).c.*.o$", + performing+","+performing+","+performing+",Hash,"+performing, "normal,normal,normal,normal,bold"], # [percent] Generating [ "^\[\s*[0-9/]+%?\]\s(Generating)(\s+.*)$", performing, "normal,bold"], From 912802597394169c9ea9b969e154a1c85fffed91 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 3 Jun 2016 10:25:09 +0200 Subject: [PATCH 052/116] More themes --- colout/colout_clang.py | 1 + colout/colout_configure.py | 13 +++++++++++++ colout/colout_ctest.py | 17 +++++++++++++++++ colout/colout_g++.py | 3 ++- colout/colout_latex.py | 5 ++++- 5 files changed, 37 insertions(+), 2 deletions(-) create mode 120000 colout/colout_clang.py create mode 100644 colout/colout_configure.py create mode 100644 colout/colout_ctest.py diff --git a/colout/colout_clang.py b/colout/colout_clang.py new file mode 120000 index 0000000..2df53b5 --- /dev/null +++ b/colout/colout_clang.py @@ -0,0 +1 @@ +colout_g++.py \ No newline at end of file diff --git a/colout/colout_configure.py b/colout/colout_configure.py new file mode 100644 index 0000000..4d50e96 --- /dev/null +++ b/colout/colout_configure.py @@ -0,0 +1,13 @@ +#encoding: utf-8 + +def theme(context): + + return context, [ + ["^(checking .*)(yes|found|ok)$","green", "normal,bold"], + ["^(checking .*)(no|none)$", "yellow", "normal,bold"], + ["^(configure:) (error:)(.*)", "red","normal,bold"], + ["^(configure:)(.*)", "magenta","normal,bold"], + ["^(checking .*)", "blue",""], + ["^(config.status:) (creating )(.*)", "cyan,blue","normal,normal,bold"], + ["^(config.status:) (executing )(.*)", "cyan,green","normal,normal,bold"], + ] diff --git a/colout/colout_ctest.py b/colout/colout_ctest.py new file mode 100644 index 0000000..d23d2bc --- /dev/null +++ b/colout/colout_ctest.py @@ -0,0 +1,17 @@ + +def theme(context): + # CTest theme: + passed="green" + notpassed="red" + + # If the user do not ask for his own colormap + # if not context["user_defined_colormaps"]: + # # A palette that goes: purple, orange, white + # percs = [45, 39, 33, 27, 21, 57, 63, 62, 98, 97, 133, 132, 138, 173, 172, 208, 214, 220, 226, 228, 229, 230, 231, 255] + # context["colormaps"]["Scale"] = percs + + return context,[ + # Passed + [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+\s+(Passed)", passed], + [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(\*{3}.*)\s+.*", notpassed] + ] diff --git a/colout/colout_g++.py b/colout/colout_g++.py index 848569f..cb9764f 100644 --- a/colout/colout_g++.py +++ b/colout/colout_g++.py @@ -76,7 +76,8 @@ def theme(context): [ qo+"(.*?)"+qc, "Cpp", "monokai" ], # source code after a "note: candidate are/is:" - [ _("note: ")+"((?!.*(candidate|"+qo+"|"+qc+")).*)$", "Cpp", "monokai" ], + [ _("note: ")+"((?!.*("+qo+"|"+qc+")).*)$", "Cpp", "monokai" ], + # [ _("note: ")+"(candidate:)(.*)$", "green,Cpp", "normal,monokai" ], # after the code part, to avoid matching ANSI escape chars [ _("note: "), "green", "normal" ] ] diff --git a/colout/colout_latex.py b/colout/colout_latex.py index cc6210e..c19287f 100644 --- a/colout/colout_latex.py +++ b/colout/colout_latex.py @@ -6,13 +6,16 @@ def theme(context): ["(LaTeX Warning): (.*) `(.*)' on page [0-9] (.*) on input line [0-9]+.$", "magenta,magenta,white,magenta", "normal,bold,normal" ], ["(LaTeX Warning): (.*)", "magenta", "normal,bold" ], + ["(LaTeX Error): (.*)", "red", "normal,bold" ], + ["^(.*\.tex):([0-9]+): (.*)", "white,yellow,red", "normal,normal,bold" ], # ["on (page [0-9]+)", "yellow", "normal" ], ["on input (line [0-9]+)", "yellow", "normal" ], ["^! .*$", "red", "bold"], ["(.*erfull) ([^\s]+).* in [^\s]+ at (lines [0-9]+--[0-9]+)", "magenta,magenta,yellow", "normal"], ["\\[^\s]+\s", "white", "bold"], - ["^l\.([0-9]+) ", "yellow"], + ["^l\.([0-9]+) (.*)", "yellow,tex"], + ["^\s+(.*)", "tex"], ["(Output written on) (.*) \(([0-9]+ pages), [0-9]+ bytes\).", "blue,white,blue", "normal,bold,normal"], ["WARNING.*", "magenta", "normal"], From f03ed7a647803fe1e635cc267fd0e5354c5cad32 Mon Sep 17 00:00:00 2001 From: nojhan Date: Thu, 18 Aug 2016 20:54:50 +0200 Subject: [PATCH 053/116] Add remark about shell buffering --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 3cc48a6..fe270e8 100644 --- a/README.md +++ b/README.md @@ -286,3 +286,10 @@ alternative one. See the ninja theme for how to extend an existing theme with more regexps and a different configuration. See the gcc theme for an example of how to use the localization of existing softwares to build translated regexp. + +### Buffering + +Note that when you use colout within real time streams (like `tail -f X | qrep Y | colout Y`) of commands, +you may observe that the lines are printed by large chunks and not one by one, in real time. +This is not due to colout but to the buffering behavior of your shell. +To fix that, use `stdbuf`, for example: `tail -f X | stdbuf -o0 grep Y | colout Y`. From fb9de000ed01a7b84fee24b702ea0802ba70ffe5 Mon Sep 17 00:00:00 2001 From: nojhan Date: Thu, 18 Aug 2016 21:11:33 +0200 Subject: [PATCH 054/116] Add a message for a common error fix #73 --- colout/colout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/colout/colout.py b/colout/colout.py index c68c948..7d436db 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -1089,6 +1089,6 @@ if __name__ == "__main__": for var in context: print(var,context[var]) print(traceback.format_exc()) - logging.error("unknown color: %s" % e ) + logging.error("unknown color: %s (maybe you forgot to install python3-pygments?)" % e ) sys.exit( error_codes["UnknownColor"] ) From 01d1ab6b20bb375b0af38ffbe7d5eb33686bbab5 Mon Sep 17 00:00:00 2001 From: nojhan Date: Thu, 18 Aug 2016 21:18:58 +0200 Subject: [PATCH 055/116] Remove the dirty arg management, only keep argparse fix #70 --- colout/colout.py | 76 ++++-------------------------------------------- 1 file changed, 5 insertions(+), 71 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 7d436db..a5744d9 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -17,6 +17,7 @@ import signal import string import hashlib import functools +import argparse # set the SIGPIPE handler to kill the program instead of # ending in a write error when a broken pipe occurs @@ -755,64 +756,7 @@ def colorgen(stream, pattern, color="red", style="normal", on_groups=False): # Command line tools # ###################### -def __args_dirty__(argv, usage=""): - """ - Roughly extract options from the command line arguments. - To be used only when argparse is not available. - - Returns a tuple of (pattern,color,style,on_stderr). - - >>> colout.__args_dirty__(["colout","pattern"],"usage") - ('pattern', 'red', 'normal', False) - >>> colout.__args_dirty__(["colout","pattern","colors","styles"],"usage") - ('pattern', 'colors', 'styles', False) - >>> colout.__args_dirty__(["colout","pattern","colors","styles","True"],"usage") - ('pattern', 'colors', 'styles', True) - """ - - # Use a dirty argument picker - # Check for bad usage or an help flag - if len(argv) < 2 \ - or len(argv) > 10 \ - or argv[1] == "--help" \ - or argv[1] == "-h": - print(usage+"\n") - print("Usage:", argv[0], " [] [] []") - print("\tAvailable colors:", " ".join(context["colors"])) - print("\tAvailable styles:", " ".join(context["styles"])) - print("Example:", argv[0], "'^(def)\s+(\w*).*$' blue,magenta italic,bold < colout.py") - sys.exit(1) - - assert(len(argv) >= 2) - # Get mandatory arguments - pattern = argv[1] - - # default values for optional args - color = "red" - style = "normal" - on_stderr = False - - if len(argv) >= 3: - color = argv[2] - if len(argv) >= 4: - style = argv[3] - if len(argv) == 5: - on_groups = bool(argv[4]) - if len(argv) == 6: - as_colormap = bool(argv[5]) - if len(argv) == 7: - as_theme = bool(argv[6]) - if len(argv) == 8: - as_source = bool(argv[7]) - if len(argv) == 9: - as_all = bool(argv[8]) - if len(argv) == 10: - scale = bool(argv[9]) - - return pattern, color, style, on_groups, as_colormap, as_theme, as_source, as_all, scale - - -def __args_parse__(argv, usage=""): +def _args_parse(argv, usage=""): """ Parse command line arguments with the argparse library. Returns a tuple of (pattern,color,style,on_stderr). @@ -923,19 +867,9 @@ if __name__ == "__main__": ##################### # Arguments parsing # ##################### - try: - import argparse - - # if argparse is not installed - except ImportError: - pattern, color, style, on_groups, as_colormap, as_theme, as_source, as_all, myscale \ - = __args_dirty__(sys.argv, usage) - - # if argparse is available - else: - pattern, color, style, on_groups, as_colormap, as_theme, as_source, as_all, myscale, \ - debug, resources, palettes_dirs, themes_dirs, default_colormap \ - = __args_parse__(sys.argv, usage) + pattern, color, style, on_groups, as_colormap, as_theme, as_source, as_all, myscale, \ + debug, resources, palettes_dirs, themes_dirs, default_colormap \ + = _args_parse(sys.argv, usage) if debug: lvl = logging.DEBUG From 5e1c64e61efb574c6c23e6e6b60054f898986b2a Mon Sep 17 00:00:00 2001 From: Nurono Date: Wed, 23 Nov 2016 12:48:09 +0300 Subject: [PATCH 056/116] fix UnicodeEncodeError --- colout/colout.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/colout/colout.py b/colout/colout.py index a5744d9..b80e065 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -698,6 +698,8 @@ def write(colored, stream = sys.stdout): """ Write "colored" on sys.stdout, then flush. """ + if isinstance(colored, unicode): + colored = colored.encode('utf-8') try: stream.write(colored) stream.flush() From eb8935f15689989ea1bca337f210b357cc75de85 Mon Sep 17 00:00:00 2001 From: jonathan poelen Date: Wed, 22 Feb 2017 23:38:06 +0100 Subject: [PATCH 057/116] better perm theme --- colout/colout_perm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/colout/colout_perm.py b/colout/colout_perm.py index c03cf96..ffcb2a5 100644 --- a/colout/colout_perm.py +++ b/colout/colout_perm.py @@ -1,7 +1,7 @@ def theme(context): - p="([rwxs-])" - reg="^([d-])"+p*9+"\s.*$" + p="([-rwxsStT])" + reg="^([-dpcCDlMmpPs?])"+p*9+"\s.*$" colors="blue"+",green"*3+",yellow"*3+",red"*3 styles="normal"+ ",normal,italic,bold"*3 return context,[ [reg, colors, styles] ] From 36faadae394a3c80e3875372138265d66dc5e35f Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 17 May 2017 11:13:01 +0200 Subject: [PATCH 058/116] better themes for cmake, ctest and configure --- colout/colout_cmake.py | 3 ++- colout/colout_configure.py | 5 ++++- colout/colout_ctest.py | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index 24b544f..252fc2f 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -31,7 +31,8 @@ def theme(context): [ "^(Scanning dependencies of target)(.*)$", performing, "normal,bold" ], # Link (make) - [ "^(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", + # [ "^(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", + [ "^(Linking .* )(library|executable) (.*)$", untimed, "normal,normal,bold" ], # [percent] Creating something [ "^\[\s*[0-9/]+%?\]\s(.*Creating.*)$", diff --git a/colout/colout_configure.py b/colout/colout_configure.py index 4d50e96..2f5e2b7 100644 --- a/colout/colout_configure.py +++ b/colout/colout_configure.py @@ -8,6 +8,9 @@ def theme(context): ["^(configure:) (error:)(.*)", "red","normal,bold"], ["^(configure:)(.*)", "magenta","normal,bold"], ["^(checking .*)", "blue",""], - ["^(config.status:) (creating )(.*)", "cyan,blue","normal,normal,bold"], + ["^(config.status:) (creating|linking)(.*)", "cyan,blue","normal,normal,bold"], ["^(config.status:) (executing )(.*)", "cyan,green","normal,normal,bold"], + ["^(config.status:) (.*)(is unchanged)", "cyan,green","normal,normal,bold"], + ["^\s*(Build.*)(yes)$","green", "normal,bold"], + ["^\s*(Build.*)(no)$","yellow", "normal,bold"], ] diff --git a/colout/colout_ctest.py b/colout/colout_ctest.py index d23d2bc..ba7e56e 100644 --- a/colout/colout_ctest.py +++ b/colout/colout_ctest.py @@ -12,6 +12,6 @@ def theme(context): return context,[ # Passed - [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+\s+(Passed)", passed], - [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(\*{3}.*)\s+.*", notpassed] + [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+\s+(Passed)", "blue,"+passed], + [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(\*{3}.*)\s+.*", "blue,"+notpassed] ] From b7e71fc32f788cf2a6455d33334649350347f6e6 Mon Sep 17 00:00:00 2001 From: Mantas Date: Fri, 23 Jun 2017 11:50:53 +0300 Subject: [PATCH 059/116] Fixes #88: failed to install with pip Also this fix includes package version issue, fixed in #87. In order to generate python package with all the files in it, use this command: python setup.py sdist --- MANIFEST.in | 2 ++ setup.py | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..04f196a --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include README.md +include LICENSE diff --git a/setup.py b/setup.py index 6af0562..3c4d90a 100644 --- a/setup.py +++ b/setup.py @@ -3,8 +3,6 @@ import os import sys -import colout - try: from setuptools import setup except ImportError: @@ -20,14 +18,14 @@ requires = ['argparse', 'pygments', 'babel'] setup( name='colout', - version='0.1', + version='0.5', description='Color Up Arbitrary Command Output.', long_description=open('README.md').read(), author='nojhan', author_email='nojhan@nojhan.net', url='http://nojhan.github.com/colout/', packages=packages, - package_data={'': ['LICENSE']}, + package_data={'': ['LICENSE', 'README.md']}, package_dir={'colout': 'colout'}, scripts=['bin/colout'], include_package_data=True, From 4a66a2976103f8c14fad36c20142ab6ae943d59d Mon Sep 17 00:00:00 2001 From: Mantas Date: Fri, 23 Jun 2017 12:57:05 +0300 Subject: [PATCH 060/116] Do not include whole licence text into licence field In setup.py, licence field should be short licence abbreviation, not a full licence text. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3c4d90a..bd67df0 100644 --- a/setup.py +++ b/setup.py @@ -30,6 +30,6 @@ setup( scripts=['bin/colout'], include_package_data=True, install_requires=requires, - license=open('LICENSE').read(), + license='GPLv3', zip_safe=False, ) From a47020e5d7150839b02d350063d25a1e3e6c3eec Mon Sep 17 00:00:00 2001 From: Jason Green Date: Thu, 19 Oct 2017 21:48:52 -0400 Subject: [PATCH 061/116] added the ability also specify background color in 8 color mode --- colout/colout.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index a5744d9..641abf5 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -44,6 +44,18 @@ context["colors"] = { "magenta": 5, "purple": 5, "cyan": 6, "white": 7, "none": -1 } + +context["backgrounds"] = { + "black": 0, + "red": 1, + "green": 2, + "yellow": 3, + "blue": 4, + "magenta": 5, + "cyan": 6, + "white": 7 + } + context["themes"] = {} # pre-defined colormaps @@ -508,6 +520,7 @@ def colorin(text, color="red", style="normal"): color_code = "" style_code = "" + background_code = "" # Convert the style code if style == "random" or style == "Random": @@ -515,8 +528,11 @@ def colorin(text, color="red", style="normal"): else: if style in context["styles"]: style_code = str(context["styles"][style]) + + color_background = color.strip().split("_") + color = color_background[0] + background = color_background[1] if len(color_background) == 2 else None - color = color.strip() m = mode(color) if color == "none": @@ -572,9 +588,17 @@ def colorin(text, color="red", style="normal"): else: raise UnknownColor(color) + if background in context["backgrounds"] and m == 8: + background_code = endmarks[m] + str(40 + context["backgrounds"][background]) + elif background == None: + pass + else: + raise UnknownColor(background) + + if color_code is not None: if not debug: - return start + style_code + endmarks[m] + color_code + "m" + text + stop + return start + style_code + endmarks[m] + color_code + background_code + "m" + text + stop else: return start + style_code + endmarks[m] + color_code + "m" \ + " Date: Fri, 20 Oct 2017 21:30:43 -0400 Subject: [PATCH 063/116] fixed color --- colout/colout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/colout/colout.py b/colout/colout.py index d492747..73e43ea 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -347,7 +347,7 @@ def color_random( color ): global context m = mode(color) if m == 8: - color_name = random.choice(context["colormaps"]["random"]) + color_name = random.choice(list(context["colormaps"]["random"])) color_code = context["colors"][color_name] color_code = str(30 + color_code) From 34c04c49db99bc5041b1f5107b43f97d8ec91795 Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 26 Feb 2018 16:28:42 +0100 Subject: [PATCH 064/116] Use six to handle both Py2 and Py3 on unicode --- colout/colout.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index b80e065..3028f39 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -18,6 +18,7 @@ import string import hashlib import functools import argparse +import six # set the SIGPIPE handler to kill the program instead of # ending in a write error when a broken pipe occurs @@ -698,8 +699,9 @@ def write(colored, stream = sys.stdout): """ Write "colored" on sys.stdout, then flush. """ - if isinstance(colored, unicode): - colored = colored.encode('utf-8') + if six.PY2: # If Python 2.x: force unicode + if isinstance(colored, unicode): + colored = colored.encode('utf-8') try: stream.write(colored) stream.flush() From d06b1b449a93483561052415dcb2d418ae811d9f Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 26 Feb 2018 17:50:14 +0100 Subject: [PATCH 065/116] Allow background without foreground ("none.blue") Use a configurable fore/background separator. Declare fore- and background colors only once. Pretty print context in debug mode. --- colout/colout.py | 83 ++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index cd7d68b..422ad6a 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -18,6 +18,8 @@ import string import hashlib import functools import argparse +import pprint +import copy # set the SIGPIPE handler to kill the program instead of # ending in a write error when a broken pipe occurs @@ -38,23 +40,21 @@ context["styles"] = { "reverse": 7, "conceal": 8 } -# Available color names in 8-colors mode -context["colors"] = { - "black": 0, "red": 1, "green": 2, "yellow": 3, "orange":3, "blue": 4, - "magenta": 5, "purple": 5, "cyan": 6, "white": 7, "none": -1 -} +# Available color names in 8-colors mode. +eight_colors = ["black","red","green","yellow","blue","magenta","cyan","white"] +# Given in that order, the ASCII code is the index. +eight_color_codes = {n:i for i,n in enumerate(eight_colors)} +# One can add synonyms. +eight_color_codes["orange"] = eight_color_codes["yellow"] +eight_color_codes["purple"] = eight_color_codes["magenta"] +# Foreground colors has a special "none" item. +# Note: use copy to avoid having the same reference over fore/background. +context["colors"] = copy.copy(eight_color_codes) +context["colors"]["none"] = -1 -context["backgrounds"] = { - "black": 0, - "red": 1, - "green": 2, - "yellow": 3, - "blue": 4, - "magenta": 5, - "cyan": 6, - "white": 7 - } +# Background has the same colors than foreground, but without the none code. +context["backgrounds"] = copy.copy(eight_color_codes) context["themes"] = {} @@ -90,6 +90,10 @@ context["scale"] = (0,100) context["lexers"] = [] +# Character use as a delimiter +# between foreground and background. +context["groundmark"]="." + class UnknownColor(Exception): pass @@ -492,10 +496,14 @@ def color_lexer( name, style, text ): return "<"+name+">"+ highlight(text, lexer, formatter)[:-1] + "" -def colorin(text, color="red", style="normal"): +def colorin(text, color="red", style="normal", groundmark=context["groundmark"]): """ Return the given text, surrounded by the given color ASCII markers. + The given color may be either a single name, encoding the foreground color, + or a pair of names, delimited by the given groundmark, + encoding foreground and background, e.g. "red.blue". + If the given color is a name that exists in available colors, a 8-colors mode is assumed, else, a 256-colors mode. @@ -521,25 +529,25 @@ def colorin(text, color="red", style="normal"): color_code = "" style_code = "" background_code = "" - list_style_code = [] - + style_codes = [] + # Convert the style code if style == "random" or style == "Random": style = random.choice(list(context["styles"].keys())) else: - styles = style.split(".") + styles = style.split(groundmark) for astyle in styles: if astyle in context["styles"]: - list_style_code.append(str(context["styles"][astyle])) - style_code = ";".join(list_style_code) - - color_background = color.strip().split(".") - color = color_background[0] - background = color_background[1] if len(color_background) == 2 else None + style_codes.append(str(context["styles"][astyle])) + style_code = ";".join(style_codes) + + color_pair = color.strip().split(groundmark) + color = color_pair[0] + background = color_pair[1] if len(color_pair) == 2 else "none" m = mode(color) - if color == "none": + if color == "none" and background == "none": # if no color, style cannot be applied if not debug: return text @@ -594,20 +602,24 @@ def colorin(text, color="red", style="normal"): if background in context["backgrounds"] and m == 8: background_code = endmarks[m] + str(40 + context["backgrounds"][background]) - elif background == None: + elif background == "none": pass else: raise UnknownColor(background) - if color_code is not None: if not debug: return start + style_code + endmarks[m] + color_code + background_code + "m" + text + stop else: - return start + style_code + endmarks[m] + color_code + "m" \ - + "" \ + return start + style_code + endmarks[m] + color_code + background_code + "m" \ + + "" \ + text + "" + stop else: if not debug: @@ -726,8 +738,6 @@ def write(colored, stream = sys.stdout): """ Write "colored" on sys.stdout, then flush. """ - if isinstance(colored, unicode): - colored = colored.encode('utf-8') try: stream.write(colored) stream.flush() @@ -912,6 +922,11 @@ if __name__ == "__main__": ################## # Load resources # ################## + + if debug: + setting = pprint.pformat(context, depth=2) + logging.debug(setting) + try: # Search for available resources files (themes, palettes) # in the same dir as the colout.py script From 881a2c7cbd53637aa51d941697ac0a0e09ee8c44 Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 27 Feb 2018 09:09:33 +0100 Subject: [PATCH 066/116] Add separator characters as options Separator for lists of colors ("," -> sep_list). Separator for fore/background color pairs ("." -> sep_back). --- colout/colout.py | 58 +++++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 1b6b07c..26698b5 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -93,7 +93,8 @@ context["lexers"] = [] # Character use as a delimiter # between foreground and background. -context["groundmark"]="." +context["sep_back"]="." +context["sep_list"]="," class UnknownColor(Exception): pass @@ -110,7 +111,7 @@ class DuplicatedTheme(Exception): ############################################################################### -def set_special_colormaps( cmap ): +def set_special_colormaps( cmap, sep_list = context["sep_list"] ): """Change all the special colors to a single colormap (which must be a list of colors).""" global context context["colormaps"]["scale"] = cmap @@ -122,7 +123,7 @@ def set_special_colormaps( cmap ): context["colormaps"]["random"] = cmap context["colormaps"]["Random"] = cmap context["user_defined_colormaps"] = True - logging.debug("user-defined special colormap: %s" % ",".join([str(i) for i in cmap]) ) + logging.debug("user-defined special colormap: %s" % sep_list.join([str(i) for i in cmap]) ) def parse_gimp_palette( filename ): @@ -497,12 +498,12 @@ def color_lexer( name, style, text ): return "<"+name+">"+ highlight(text, lexer, formatter)[:-1] + "" -def colorin(text, color="red", style="normal", groundmark=context["groundmark"]): +def colorin(text, color="red", style="normal", sep_back=context["sep_back"]): """ Return the given text, surrounded by the given color ASCII markers. The given color may be either a single name, encoding the foreground color, - or a pair of names, delimited by the given groundmark, + or a pair of names, delimited by the given sep_back, encoding foreground and background, e.g. "red.blue". If the given color is a name that exists in available colors, @@ -536,13 +537,13 @@ def colorin(text, color="red", style="normal", groundmark=context["groundmark"]) if style == "random" or style == "Random": style = random.choice(list(context["styles"].keys())) else: - styles = style.split(groundmark) + styles = style.split(sep_back) for astyle in styles: if astyle in context["styles"]: style_codes.append(str(context["styles"][astyle])) style_code = ";".join(style_codes) - color_pair = color.strip().split(groundmark) + color_pair = color.strip().split(sep_back) color = color_pair[0] background = color_pair[1] if len(color_pair) == 2 else "none" @@ -642,7 +643,7 @@ def colorout(text, match, prev_end, color="red", style="normal", group=0): return colored_text, end -def colorup(text, pattern, color="red", style="normal", on_groups=False): +def colorup(text, pattern, color="red", style="normal", on_groups=False, sep_list=context["sep_list"]): """ Color up every characters that match the given regexp patterns. If groups are specified, only color up them and not the whole pattern. @@ -690,11 +691,11 @@ def colorup(text, pattern, color="red", style="normal", on_groups=False): # Build a list of colors that match the number of grouped, # if there is not enough colors, duplicate the last one. - colors_l = color.split(",") + colors_l = color.split(sep_list) group_colors = colors_l + [colors_l[-1]] * (nb_groups - len(colors_l)) # Same for styles - styles_l = style.split(",") + styles_l = style.split(sep_list) group_styles = styles_l + [styles_l[-1]] * (nb_groups - len(styles_l)) # If we want to iterate colormaps on groups instead of patterns @@ -777,7 +778,7 @@ def map_write( stream_in, stream_out, function, *args ): write( function(item, *args), stream_out ) -def colorgen(stream, pattern, color="red", style="normal", on_groups=False): +def colorgen(stream, pattern, color="red", style="normal", on_groups=False, sep_list=context["sep_list"]): """ A generator that colors the items given in an iterable input. @@ -793,7 +794,7 @@ def colorgen(stream, pattern, color="red", style="normal", on_groups=False): break if not item: break - yield colorup(item, pattern, color, style, on_groups) + yield colorup(item, pattern, color, style, on_groups, sep_list) ###################### @@ -864,7 +865,8 @@ def _args_parse(argv, usage=""): parser.add_argument("-d", "--default", metavar="COLORMAP", default=None, help="When using special colormaps (`random`, `scale` or `hash`), use this COLORMAP. \ This can be either one of the available colormaps or a comma-separated list of colors. \ - WARNING: be sure to specify a default colormap that is compatible with the special colormap's mode.") + WARNING: be sure to specify a default colormap that is compatible with the special colormap's mode \ + (8 or 256 colors).") # This normally should be an option with an argument, but this would end in an error, # as no regexp is supposed to be passed after calling this option, @@ -881,6 +883,13 @@ def _args_parse(argv, usage=""): if it is lower case, use the 8 colors mode. \ Interpret COLOR as a Pygments style." + pygments_warn) + parser.add_argument("-m", "--sep-list", metavar="CHAR", default=",", + help="Use this character as a separator for list of colors (instead of comma).") + + parser.add_argument("-b", "--sep-back", metavar="CHAR", default=".", + help="Use this character as a separator for foreground/background pairs (instead of period).") + + parser.add_argument("--debug", action="store_true", help="Debug mode: print what's going on internally, useful if you want to check what features are available.") @@ -888,7 +897,7 @@ def _args_parse(argv, usage=""): return args.pattern[0], args.color, args.style, args.groups, \ args.colormap, args.theme, args.source, args.all, args.scale, args.debug, args.resources, args.palettes_dir, \ - args.themes_dir, args.default + args.themes_dir, args.default, args.sep_list, args.sep_back def write_all( as_all, stream_in, stream_out, function, *args ): @@ -912,7 +921,7 @@ if __name__ == "__main__": # Arguments parsing # ##################### pattern, color, style, on_groups, as_colormap, as_theme, as_source, as_all, myscale, \ - debug, resources, palettes_dirs, themes_dirs, default_colormap \ + debug, resources, palettes_dirs, themes_dirs, default_colormap, sep_list, sep_back \ = _args_parse(sys.argv, usage) if debug: @@ -931,6 +940,9 @@ if __name__ == "__main__": setting = pprint.pformat(context, depth=2) logging.debug(setting) + context["sep_list"] = sep_list + context["sep_back"] = sep_back + try: # Search for available resources files (themes, palettes) # in the same dir as the colout.py script @@ -965,7 +977,7 @@ if __name__ == "__main__": sys.exit( error_codes["DuplicatedPalette"] ) if resources: - asked=[r.lower() for r in pattern.split(",")] + asked=[r.lower() for r in pattern.split(context["sep_list"])] def join_sort( l ): """ @@ -1015,25 +1027,25 @@ if __name__ == "__main__": try: if myscale: - context["scale"] = tuple([float(i) for i in myscale.split(",")]) + context["scale"] = tuple([float(i) for i in myscale.split(context["sep_list"])]) logging.debug("user-defined scale: %f,%f" % context["scale"]) # Default color maps if default_colormap: if default_colormap not in context["colormaps"]: - cmap = default_colormap.split(",") + cmap = default_colormap.split(context["sep_list"]) elif default_colormap in context["colormaps"]: cmap = context["colormaps"][default_colormap] - set_special_colormaps( cmap ) + set_special_colormaps( cmap, context["sep_list"] ) # explicit color map if as_colormap is True and color not in context["colormaps"]: - context["colormaps"]["Default"] = color.split(",") # replace the colormap by the given colors - context["colormaps"]["default"] = color.split(",") # replace the colormap by the given colors + context["colormaps"]["Default"] = color.split(context["sep_list"]) # replace the colormap by the given colors + context["colormaps"]["default"] = color.split(context["sep_list"]) # replace the colormap by the given colors color = "colormap" # use the keyword to switch to colormap instead of list of colors - logging.debug("used-defined default colormap: %s" % ",".join(context["colormaps"]["Default"]) ) + logging.debug("used-defined default colormap: %s" % context["sep_list"].join(context["colormaps"]["Default"]) ) # if theme if as_theme: @@ -1064,7 +1076,7 @@ if __name__ == "__main__": # if color else: - write_all( as_all, sys.stdin, sys.stdout, colorup, pattern, color, style, on_groups ) + write_all( as_all, sys.stdin, sys.stdout, colorup, pattern, color, style, on_groups, context["sep_list"] ) except UnknownColor as e: if debug: From 8b0607e035eed84040c160545cfcfe776776a324 Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 27 Feb 2018 15:51:41 +0100 Subject: [PATCH 067/116] fix #92: handling of --colormap Use "default" instead of "colormap". Use the first color in the user-defined map to check mode. Add check of mixed modes. --- colout/colout.py | 71 +++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 26698b5..8e44cd4 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -5,22 +5,22 @@ # Licensed under the GPL version 3 # 2012 (c) nojhan -import sys -import re -import random import os +import re +import six +import sys +import copy import glob import math -import importlib -import logging +import pprint +import random import signal import string import hashlib -import functools +import logging import argparse -import six -import pprint -import copy +import importlib +import functools # set the SIGPIPE handler to kill the program instead of # ending in a write error when a broken pipe occurs @@ -105,11 +105,25 @@ class DuplicatedPalette(Exception): class DuplicatedTheme(Exception): pass +class MixedModes(Exception): + pass + ############################################################################### # Ressource parsing helpers ############################################################################### +def make_colormap( colors, sep_list = context["sep_list"] ): + cmap = colors.split(sep_list) + + # Check unicity of mode. + modes = [mode(c) for c in cmap] + if len(uniq(modes)) > 1: + # Format a list of color:mode, for error display. + raise MixedModes(", ".join(["%s:%s" % cm for cm in zip(cmap,modes)])) + + return cmap + def set_special_colormaps( cmap, sep_list = context["sep_list"] ): """Change all the special colors to a single colormap (which must be a list of colors).""" @@ -343,10 +357,10 @@ def mode( color ): raise UnknownColor(color) -def next_in_map( color ): +def next_in_map( name ): global context # loop over indices in colormap - return (context["colormap_idx"]+1) % len(context["colormaps"][color]) + return (context["colormap_idx"]+1) % len(context["colormaps"][name]) def color_random( color ): @@ -462,7 +476,7 @@ def color_hash( name, text ): def color_map(name): global context # current color - color = context["colormaps"][name][context["colormap_idx"]] + color = context["colormaps"][name][ context["colormap_idx"] ] m = mode(color) if m == 8: @@ -472,7 +486,7 @@ def color_map(name): assert( 0 <= color_nb <= 255 ) color_code = str(color_nb) - context["colormap_idx"] = next_in_map(color) + context["colormap_idx"] = next_in_map(name) return color_code @@ -547,8 +561,6 @@ def colorin(text, color="red", style="normal", sep_back=context["sep_back"]): color = color_pair[0] background = color_pair[1] if len(color_pair) == 2 else "none" - m = mode(color) - if color == "none" and background == "none": # if no color, style cannot be applied if not debug: @@ -569,7 +581,11 @@ def colorin(text, color="red", style="normal", sep_back=context["sep_back"]): # Really useful only when using colout as a library # thus you can change the "colormap" variable to your favorite one before calling colorin elif color == "colormap": - color_code = color_map(color) + # "default" should have been set to the user-defined colormap. + color_code = color_map("default") + # Use the first of the user-defined colormap to detect the mode, + # thus set `color`, to be used by `mode` below. + color = context["colormaps"]["default"][0] # Registered colormaps should be tested after special colors, # because special tags are also registered as colormaps, @@ -602,6 +618,8 @@ def colorin(text, color="red", style="normal", sep_back=context["sep_back"]): else: raise UnknownColor(color) + m = mode(color) + if background in context["backgrounds"] and m == 8: background_code = endmarks[m] + str(40 + context["backgrounds"][background]) elif background == "none": @@ -883,10 +901,10 @@ def _args_parse(argv, usage=""): if it is lower case, use the 8 colors mode. \ Interpret COLOR as a Pygments style." + pygments_warn) - parser.add_argument("-m", "--sep-list", metavar="CHAR", default=",", + parser.add_argument("-m", "--sep-list", metavar="CHAR", default=",", type=str, nargs=1, help="Use this character as a separator for list of colors (instead of comma).") - parser.add_argument("-b", "--sep-back", metavar="CHAR", default=".", + parser.add_argument("-b", "--sep-back", metavar="CHAR", default=".", type=str, nargs=1, help="Use this character as a separator for foreground/background pairs (instead of period).") @@ -913,7 +931,7 @@ def write_all( as_all, stream_in, stream_out, function, *args ): if __name__ == "__main__": - error_codes = {"UnknownColor":1, "DuplicatedPalette":2} + error_codes = {"UnknownColor":1, "DuplicatedPalette":2, "MixedModes":3} usage = "A regular expression based formatter that color up an arbitrary text stream." @@ -1033,7 +1051,7 @@ if __name__ == "__main__": # Default color maps if default_colormap: if default_colormap not in context["colormaps"]: - cmap = default_colormap.split(context["sep_list"]) + cmap = make_colormap(default_colormap,context["sep_list"]) elif default_colormap in context["colormaps"]: cmap = context["colormaps"][default_colormap] @@ -1042,8 +1060,8 @@ if __name__ == "__main__": # explicit color map if as_colormap is True and color not in context["colormaps"]: - context["colormaps"]["Default"] = color.split(context["sep_list"]) # replace the colormap by the given colors - context["colormaps"]["default"] = color.split(context["sep_list"]) # replace the colormap by the given colors + context["colormaps"]["Default"] = make_colormap(color,context["sep_list"]) # replace the colormap by the given colors + context["colormaps"]["default"] = make_colormap(color,context["sep_list"]) # replace the colormap by the given colors color = "colormap" # use the keyword to switch to colormap instead of list of colors logging.debug("used-defined default colormap: %s" % context["sep_list"].join(context["colormaps"]["Default"]) ) @@ -1081,9 +1099,12 @@ if __name__ == "__main__": except UnknownColor as e: if debug: import traceback - for var in context: - print(var,context[var]) print(traceback.format_exc()) - logging.error("unknown color: %s (maybe you forgot to install python3-pygments?)" % e ) + logging.error("Unknown color: %s (maybe you forgot to install python3-pygments?)" % e ) sys.exit( error_codes["UnknownColor"] ) + except MixedModes as e: + logging.error("You cannot mix up color modes when defining your own colormap." \ + + " Check the following 'color:mode' pairs: %s." % e ) + sys.exit( error_codes["MixedModes"] ) + From b285d51db2adba95b587c866b5606dca843f0ad8 Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 27 Feb 2018 15:57:59 +0100 Subject: [PATCH 068/116] less verbose lexers debuging --- colout/colout.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 8e44cd4..0b58399 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -313,9 +313,8 @@ def load_lexers(): except IndexError: logging.warning("cannot load lexer: %s" % lexer[1][0]) pass - else: - logging.debug("loaded lexer %s" % lexer[1][0]) lexers.sort() + logging.debug("loaded %i lexers: %s" % (len(lexers), ", ".join(lexers))) context["lexers"] = lexers From feb87f25326f1d12a627842b85bcb1c19e02851a Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 27 Feb 2018 16:09:26 +0100 Subject: [PATCH 069/116] fix separator option --- colout/colout.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 0b58399..54f231c 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -134,8 +134,8 @@ def set_special_colormaps( cmap, sep_list = context["sep_list"] ): context["colormaps"]["Hash"] = cmap context["colormaps"]["default"] = cmap context["colormaps"]["Default"] = cmap - context["colormaps"]["random"] = cmap - context["colormaps"]["Random"] = cmap + context["colormaps"]["random"] = cmap + context["colormaps"]["Random"] = cmap context["user_defined_colormaps"] = True logging.debug("user-defined special colormap: %s" % sep_list.join([str(i) for i in cmap]) ) @@ -900,10 +900,10 @@ def _args_parse(argv, usage=""): if it is lower case, use the 8 colors mode. \ Interpret COLOR as a Pygments style." + pygments_warn) - parser.add_argument("-m", "--sep-list", metavar="CHAR", default=",", type=str, nargs=1, + parser.add_argument("-m", "--sep-list", metavar="CHAR", default=",", type=str, help="Use this character as a separator for list of colors (instead of comma).") - parser.add_argument("-b", "--sep-back", metavar="CHAR", default=".", type=str, nargs=1, + parser.add_argument("-b", "--sep-back", metavar="CHAR", default=".", type=str, help="Use this character as a separator for foreground/background pairs (instead of period).") @@ -958,7 +958,9 @@ if __name__ == "__main__": logging.debug(setting) context["sep_list"] = sep_list + logging.debug("Color list separator: %s" % context["sep_list"]) context["sep_back"] = sep_back + logging.debug("Color pair separator: %s" % context["sep_back"]) try: # Search for available resources files (themes, palettes) From 4b758a5f9e92fc70d4c646657f05a0ab9f22b053 Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 27 Feb 2018 16:29:19 +0100 Subject: [PATCH 070/116] Simpler color_map returns Rename some variables/options. Do not log debug context. --- colout/colout.py | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 54f231c..69cd78a 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -93,7 +93,7 @@ context["lexers"] = [] # Character use as a delimiter # between foreground and background. -context["sep_back"]="." +context["sep_pair"]="." context["sep_list"]="," class UnknownColor(Exception): @@ -487,7 +487,7 @@ def color_map(name): context["colormap_idx"] = next_in_map(name) - return color_code + return color,color_code def color_lexer( name, style, text ): @@ -511,12 +511,12 @@ def color_lexer( name, style, text ): return "<"+name+">"+ highlight(text, lexer, formatter)[:-1] + "" -def colorin(text, color="red", style="normal", sep_back=context["sep_back"]): +def colorin(text, color="red", style="normal", sep_pair=context["sep_pair"]): """ Return the given text, surrounded by the given color ASCII markers. The given color may be either a single name, encoding the foreground color, - or a pair of names, delimited by the given sep_back, + or a pair of names, delimited by the given sep_pair, encoding foreground and background, e.g. "red.blue". If the given color is a name that exists in available colors, @@ -550,13 +550,13 @@ def colorin(text, color="red", style="normal", sep_back=context["sep_back"]): if style == "random" or style == "Random": style = random.choice(list(context["styles"].keys())) else: - styles = style.split(sep_back) + styles = style.split(sep_pair) for astyle in styles: if astyle in context["styles"]: style_codes.append(str(context["styles"][astyle])) style_code = ";".join(style_codes) - color_pair = color.strip().split(sep_back) + color_pair = color.strip().split(sep_pair) color = color_pair[0] background = color_pair[1] if len(color_pair) == 2 else "none" @@ -577,14 +577,10 @@ def colorin(text, color="red", style="normal", sep_back=context["sep_back"]): elif color.lower() == "hash": color_code = color_hash( color, text ) - # Really useful only when using colout as a library - # thus you can change the "colormap" variable to your favorite one before calling colorin + # The user can change the "colormap" variable to its favorite one before calling colorin. elif color == "colormap": # "default" should have been set to the user-defined colormap. - color_code = color_map("default") - # Use the first of the user-defined colormap to detect the mode, - # thus set `color`, to be used by `mode` below. - color = context["colormaps"]["default"][0] + color,color_code = color_map("default") # Registered colormaps should be tested after special colors, # because special tags are also registered as colormaps, @@ -622,7 +618,7 @@ def colorin(text, color="red", style="normal", sep_back=context["sep_back"]): if background in context["backgrounds"] and m == 8: background_code = endmarks[m] + str(40 + context["backgrounds"][background]) elif background == "none": - pass + background_code = "" else: raise UnknownColor(background) @@ -900,13 +896,12 @@ def _args_parse(argv, usage=""): if it is lower case, use the 8 colors mode. \ Interpret COLOR as a Pygments style." + pygments_warn) - parser.add_argument("-m", "--sep-list", metavar="CHAR", default=",", type=str, - help="Use this character as a separator for list of colors (instead of comma).") + parser.add_argument("-e", "--sep-list", metavar="CHAR", default=",", type=str, + help="Use this character as a separator for list of colors/resources/numbers (instead of comma).") - parser.add_argument("-b", "--sep-back", metavar="CHAR", default=".", type=str, + parser.add_argument("-E", "--sep-pair", metavar="CHAR", default=".", type=str, help="Use this character as a separator for foreground/background pairs (instead of period).") - parser.add_argument("--debug", action="store_true", help="Debug mode: print what's going on internally, useful if you want to check what features are available.") @@ -914,7 +909,7 @@ def _args_parse(argv, usage=""): return args.pattern[0], args.color, args.style, args.groups, \ args.colormap, args.theme, args.source, args.all, args.scale, args.debug, args.resources, args.palettes_dir, \ - args.themes_dir, args.default, args.sep_list, args.sep_back + args.themes_dir, args.default, args.sep_list, args.sep_pair def write_all( as_all, stream_in, stream_out, function, *args ): @@ -938,7 +933,7 @@ if __name__ == "__main__": # Arguments parsing # ##################### pattern, color, style, on_groups, as_colormap, as_theme, as_source, as_all, myscale, \ - debug, resources, palettes_dirs, themes_dirs, default_colormap, sep_list, sep_back \ + debug, resources, palettes_dirs, themes_dirs, default_colormap, sep_list, sep_pair \ = _args_parse(sys.argv, usage) if debug: @@ -953,14 +948,10 @@ if __name__ == "__main__": # Load resources # ################## - if debug: - setting = pprint.pformat(context, depth=2) - logging.debug(setting) - context["sep_list"] = sep_list - logging.debug("Color list separator: %s" % context["sep_list"]) - context["sep_back"] = sep_back - logging.debug("Color pair separator: %s" % context["sep_back"]) + logging.debug("Color list separator: '%s'" % context["sep_list"]) + context["sep_pair"] = sep_pair + logging.debug("Color pair separator: '%s'" % context["sep_pair"]) try: # Search for available resources files (themes, palettes) @@ -995,6 +986,10 @@ if __name__ == "__main__": logging.error( "duplicated palette file name: %s" % e ) sys.exit( error_codes["DuplicatedPalette"] ) + # if debug: + # setting = pprint.pformat(context, depth=2) + # logging.debug(setting) + if resources: asked=[r.lower() for r in pattern.split(context["sep_list"])] From 1bebce1c633755eb538273925c74e087fefc7b0e Mon Sep 17 00:00:00 2001 From: nojhan Date: Sun, 4 Mar 2018 20:39:33 +0100 Subject: [PATCH 071/116] version 0.6 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index bd67df0..daa8d35 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ requires = ['argparse', 'pygments', 'babel'] setup( name='colout', - version='0.5', + version='0.6', description='Color Up Arbitrary Command Output.', long_description=open('README.md').read(), author='nojhan', From abaa109c0d0333c74931fba349a47df19ab3fedd Mon Sep 17 00:00:00 2001 From: nojhan Date: Sun, 4 Mar 2018 20:55:56 +0100 Subject: [PATCH 072/116] Add color/style pairs to the readme --- README.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fe270e8..0f670da 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ colout(1) -- Color Up Arbitrary Command Output `colout` [-h] [-r RESOURCE] -`colout` [-g] [-c] [-l min,max] [-a] [-t] [-T DIR] [-P DIR] [-d COLORMAP] [-s] [--debug] PATTERN [COLOR(S) [STYLE(S)]] +`colout` [-g] [-c] [-l min,max] [-a] [-t] [-T DIR] [-P DIR] [-d COLORMAP] [-s] [-e CHAR] [-E CHAR] [--debug] PATTERN [COLOR(S) [STYLE(S)]] ## DESCRIPTION @@ -28,6 +28,8 @@ Available styles are: normal, bold, faint, italic, underline, blink, rapid\_blink, reverse, conceal or random (some styles may have no effect, depending on your terminal). +In some case, you can indicate a foreground and a background color, by indicating boths colors separated by a period(for example: `red.blue`). You can also use this system to combine two styles (for example, for a bold style that also blinks: `bold.blink`). + `rainbow` will cycle over a the default colormap at each matching pattern. `Rainbow` will do the same over the default colormap for the 256-colors mode (this requires a terminal that supports the 256 color escape sequences). @@ -152,6 +154,12 @@ Gentoo is upper case, use the 256 color mode, if it is lower case, use the 8 colors mode. In 256 color mode, interpret COLOR as a Pygments style (e.g. "default"). +* `-e CHAR`, `--sep-list CHAR`: + Use this character as a separator for list of colors/resources/numbers (instead of comma). + +* `-E CHAR`, `--sep-pair CHAR`: + Use this character as a separator for foreground/background pairs (instead of period). + * `--debug`: Debug mode: print what's going on internally, if you want to check what features are available. @@ -183,6 +191,7 @@ with each matching colors. Using a default colormap that is incompatible with the special colormap's mode will end badly. +Color pairs ("foreground.background") work in 8-colors mode for simple coloring, but may fail with `--colormap`. ## EXAMPLES @@ -289,7 +298,8 @@ See the gcc theme for an example of how to use the localization of existing soft ### Buffering -Note that when you use colout within real time streams (like `tail -f X | qrep Y | colout Y`) of commands, +Note that when you use colout within real time streams (like `tail -f X | grep Y | colout Z`) of commands, you may observe that the lines are printed by large chunks and not one by one, in real time. This is not due to colout but to the buffering behavior of your shell. -To fix that, use `stdbuf`, for example: `tail -f X | stdbuf -o0 grep Y | colout Y`. +To fix that, use `stdbuf`, for example: `tail -f X | stdbuf -o0 grep Y | colout Z`. + From a20cfa32c7c88fffaaaecac5336cfae788e9060d Mon Sep 17 00:00:00 2001 From: Philippe Daouadi Date: Thu, 12 Jul 2018 11:10:05 +0200 Subject: [PATCH 073/116] fix g++ coloration --- colout/colout_g++.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/colout/colout_g++.py b/colout/colout_g++.py index cb9764f..c4abe03 100644 --- a/colout/colout_g++.py +++ b/colout/colout_g++.py @@ -36,15 +36,16 @@ def theme(context): return context,[ # Command line [ "[/\s]([cg]\+\+-*[0-9]*\.*[0-9]*)", "white", "bold" ], - [ "\s(\-D)(\s*[^\s]+\s)", "none,green", "normal,bold" ], - [ "\s-g\s", "green", "normal" ], - [ "\s-O[0-4]*\s", "green", "normal" ], + [ "\s(\-D)(\s*[^\s]+)", "none,green", "normal,bold" ], + [ "\s(-g)", "green", "normal" ], + [ "\s-O[0-4]", "green", "normal" ], [ "\s-[Wf][^\s]*", "magenta", "normal" ], + [ "\s-pedantic", "magenta", "normal" ], [ "\s(-I)(/*[^\s]+/)([^/\s]+)", "none,blue", "normal,normal,bold" ], [ "\s(-L)(/*[^\s]+/)([^/\s]+)", "none,cyan", "normal,normal,bold" ], [ "\s(-l)([^/\s]+)", "none,cyan", "normal,bold" ], [ "\s-[oc]", "red", "bold" ], - [ "\s(-+std)=*([^s]+)", "red", "normal,bold" ], + [ "\s(-+std(?:lib)?)=?([^\s]+)", "red", "normal,bold" ], # Important messages [ _("error: "), "red", "bold" ], From d0ad9850ad8cb247f9dabf3a12a6e633651506f7 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Wed, 1 Aug 2018 23:41:54 +0100 Subject: [PATCH 074/116] Remove use of six (not listed in dependencies) --- colout/colout.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 3028f39..bd7a973 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -18,7 +18,6 @@ import string import hashlib import functools import argparse -import six # set the SIGPIPE handler to kill the program instead of # ending in a write error when a broken pipe occurs @@ -29,6 +28,8 @@ signal.signal( signal.SIGPIPE, signal.SIG_DFL ) # Global variable(s) ############################################################################### +PY2 = sys.version_info.major == 2 + context = {} debug = False @@ -699,7 +700,7 @@ def write(colored, stream = sys.stdout): """ Write "colored" on sys.stdout, then flush. """ - if six.PY2: # If Python 2.x: force unicode + if PY2: # If Python 2.x: force unicode if isinstance(colored, unicode): colored = colored.encode('utf-8') try: From 9d90694375a53049226fcb1b8ce56898a0608543 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Thu, 2 Aug 2018 12:55:03 +0100 Subject: [PATCH 075/116] Only require argparse for python < 2.7 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6af0562..787dd37 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ if sys.argv[-1] == 'publish': packages = ['colout'] -requires = ['argparse', 'pygments', 'babel'] +requires = ['argparse; python_version < "2.7"', 'pygments', 'babel'] setup( name='colout', From 78dc13c40eba26d50e805c7aabdc467650caf3b6 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 3 Aug 2018 16:00:15 +0200 Subject: [PATCH 076/116] Add authors and a gdbinit example --- README.md | 88 +++++++++++++++++++++++++++++++- example.gdbinit | 132 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+), 2 deletions(-) create mode 100644 example.gdbinit diff --git a/README.md b/README.md index 0f670da..187f828 100644 --- a/README.md +++ b/README.md @@ -178,7 +178,6 @@ special characters that would be recognize by your shell. Recommended packages: -* `argparse` for a usable arguments parsing * `pygments` for the source code syntax coloring * `babel` for a locale-aware number parsing @@ -189,7 +188,7 @@ Don't use nested groups or colout will duplicate the corresponding input text with each matching colors. Using a default colormap that is incompatible with the special colormap's mode -will end badly. +(i.e. number of colors) will end badly. Color pairs ("foreground.background") work in 8-colors mode for simple coloring, but may fail with `--colormap`. @@ -277,6 +276,66 @@ You then can use the `cm` alias as a prefix to your build command, for example: `cm make test` +### GDB integration + +You can use `colout` within the GNU debuger (`gbd`) to color its output. +For example, the following script `.gdbinit` configuration will color +the output of the backtrace command: + +```gdb +set confirm off + +# Don't wrap line or the coloring regexp won't work. +set width 0 + +# Create a named pipe to get outputs from gdb +shell test -e /tmp/coloutPipe && rm /tmp/coloutPipe +shell mkfifo /tmp/coloutPipe + +define logging_on + # Instead of printing on stdout only, log everything... + set logging redirect on + # ... in our named pipe. + set logging on /tmp/coloutPipe +end + +define logging_off + set logging off + set logging redirect off + # Because both gdb and our commands are writing on the same pipe at the same + # time, it is more than probable that gdb will end before our (higher level) + # commands. The gdb prompt will thus render before the result of the command, + # which is highly akward. To prevent this, we need to wait before displaying + # the prompt again. The more your commands are complex, the higher you will + # need to set this. + shell sleep 0.4s +end + +define hook-backtrace + # Note: match path = [path]file[.ext] = (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)) + # This line color highlights: + # – lines that link to source code, + # – function call in green, + # – arguments names in yellow, values in magenta, + # — the parent directory in bold red (assuming that the debug session would be in a "project/build/" directory). + shell cat /tmp/coloutPipe | colout "^(#)([0-9]+)\s+(0x\S+ )*(in )*(.*) (\(.*\)) (at) (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" red,red,blue,red,green,magenta,red,none,white,white,yellow normal,bold,normal,normal,normal,normal,normal,bold,bold,bold | colout "([\w\s]*?)(=)([^,]*?)([,\)])" yellow,blue,magenta,blue normal | colout "/($(basename $(dirname $(pwd))))/" red bold & + logging_on +end +define hookpost-backtrace + logging_off +end + +# Don't forget to clean the adhoc pipe. +define hook-quit + set confirm off + shell rm -f /tmp/coloutPipe +end +``` + +Take a look at the `example.gdbinit` file distributed with colout for more gdb commands. + + + ### Themes You can easily add your own theme to colout. @@ -303,3 +362,28 @@ you may observe that the lines are printed by large chunks and not one by one, i This is not due to colout but to the buffering behavior of your shell. To fix that, use `stdbuf`, for example: `tail -f X | stdbuf -o0 grep Y | colout Z`. +## Authors + +* nojhan : original idea, main developer, maintener. +* Adrian Sadłocha +* Alex Burka +* Brian Foley +* Charles Lewis +* DainDwarf +* Dimitri Merejkowsky +* Dong Wei Ming +* Fabien MARTY +* Jason Green +* John Anderson +* Jonathan Poelen +* Louis-Kenzo Furuya Cahier +* Mantas +* Martin Ueding +* Nicolas Pouillard +* Nurono +* Oliver Bristow +* orzrd <61966225@qq.com> +* Philippe Daouadi +* Piotr Staroszczyk +* Scott Lawrence +* Xu Di diff --git a/example.gdbinit b/example.gdbinit new file mode 100644 index 0000000..b40a960 --- /dev/null +++ b/example.gdbinit @@ -0,0 +1,132 @@ + +set confirm off + +# Reversed yellow >>>, underlined green frame name, yellow »»» +set extended-prompt \[\e[7;33m\]>>>\[\e[0m\]\[\] \[\e[4;32m\]\f\[\e[0m\]\[\]\[\e[0;33m\] \n»»» \[\e[0m\] + + +# Don't wrap line or the coloring regexp won't work. +set width 0 + +# Create a named pipe to get outputs from gdb +shell test -e /tmp/coloutPipe && rm /tmp/coloutPipe +shell mkfifo /tmp/coloutPipe + +define logging_on + # Instead of printing on stdout only, log everything... + set logging redirect on + # ... in our named pipe. + set logging on /tmp/coloutPipe +end + +define logging_off + set logging off + set logging redirect off + # Because both gdb and our commands are writing on the same pipe at the same + # time, it is more than probable that gdb will end before our (higher level) + # commands. The gdb prompt will thus render before the result of the command, + # which is highly akward. To prevent this, we need to wait before displaying + # the prompt again. The more your commands are complex, the higher you will + # need to set this. + shell sleep 0.4s +end + + +define hook-break + # Don't forget to run the command in the background + shell cat /tmp/coloutPipe | colout "(Breakpoint) ([0-9]+) at (0x\S+): file (.+/)([^/]+), line ([0-9]+)." blue,red,cyan,none,white,yellow normal,bold,normal,normal,bold,normal & + # You should start to consume the pipe before actually redirecting the command output into it. + logging_on +end +define hookpost-break + logging_off +end + + +define hook-run + shell cat /tmp/coloutPipe | colout "^(Program received signal )(.+), (.+).$" yellow,red,yellow normal,bold | colout "^(Breakpoint) ([0-9]+),*\s+(0x\S+ )*(in )*(\S+) (\(.*\)) at (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" red,red,blue,none,green,cpp,none,white,white,yellow normal,bold,normal,normal,bold,normal,normal,bold,bold,bold | colout "^(Starting program): (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" green,none,white,white,yellow normal,normal,bold,bold,bold | colout "^[0-9]+\s+(.*)$" Cpp & + logging_on +end +define hookpost-run + logging_off +end + + +define hook-continue + shell cat /tmp/coloutPipe | colout "^(Program received signal )(.*)(,.*)$" yellow,red,yellow bold | colout "^(Breakpoint) ([0-9]+),*\s+(0x\S+ )*(in )*(\S+) (\(.*\)) at (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" red,red,blue,none,green,cpp,none,white,white,yellow normal,bold,normal,normal,bold,normal,normal,bold,bold,bold | colout "^[0-9]+\s+(.*)$" Cpp & + logging_on +end +define hookpost-continue + logging_off +end + + +# Full syntax highlighting for the `list` command. +define hook-list + #shell cat /tmp/coloutPipe | colout --all --source cpp & + shell cat /tmp/coloutPipe | colout "^([0-9]+)\s*(.*)$" red,Cpp & + logging_on +end +# Don't forget the hookpost- or next coloring commands will fail. +define hookpost-list + logging_off +end + + +define hook-backtrace + # Note: match path = [path]file[.ext] = (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)) + # This line color highlights: + # – lines that link to source code, + # – function call in green, + # – arguments names in yellow, values in magenta, + # — the parent directory in bold red (assuming that the debug session would be in a "project/build/" directory). + shell cat /tmp/coloutPipe | colout "^(#)([0-9]+)\s+(0x\S+ )*(in )*(.*) (\(.*\)) (at) (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" red,red,blue,red,green,magenta,red,none,white,white,yellow normal,bold,normal,normal,normal,normal,normal,bold,bold,bold | colout "([\w\s]*?)(=)([^,]*?)([,\)])" yellow,blue,magenta,blue normal | colout "/($(basename $(dirname $(pwd))))/" red bold & + logging_on +end +define hookpost-backtrace + logging_off +end + + +define info hook-breakpoints + shell cat /tmp/coloutPipe | colout "^([0-9]+)" red bold | colout "\sy\s" green | colout "\sn\s" red | colout "breakpoint" green normal | colout "watchpoint" orange normal | colout "\s0x\S+\s" blue normal | colout "(.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)$" none,white,white,yellow normal,bold & + logging_on +end +define info hookpost-breakpoints + logging_off +end + + +define info hook-line + shell cat /tmp/coloutPipe | colout "^Line ([0-9]+) of \"(.*/)?(?:$|(.+?)(?:(\.[^.]*)|))\"" yellow,none,white,white bold | colout "(0x\S+) <(\S+)\+([0-9]+)>" blue,green,blue normal & + logging_on +end +define info hookpost-line + logging_off +end + + +define hook-frame + #shell cat /tmp/coloutPipe | colout "^(#)([0-9]+)\s+(0x\S+ )*(in )*(.*) (at) (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" red,red,blue,red,green,red,magenta,none,white,white,yellow normal,bold,normal,normal,bold,normal,normal,bold,bold,bold | colout "^([0-9]+)\s+(.*)$" yellow,Cpp & + shell cat /tmp/coloutPipe | colout "^(#)([0-9]+)\s+(0x\S+ )*(in )*(.*) (\(.*\)) (at) (.*/)?(?:$|(.+?)(?:(\.[^.]*)|)):([0-9]+)" red,red,blue,red,green,magenta,red,none,white,white,yellow normal,bold,normal,normal,normal,normal,normal,bold,bold,bold | colout "([\w\s]*?)(=)([^,]*?)([,\)])" yellow,blue,magenta,blue normal & + logging_on +end +define hookpost-frame + logging_off +end + +# Don't forget to clean the adhoc pipe. +define hook-quit + set confirm off + shell rm -f /tmp/coloutPipe +end + +define hook-display + shell cat /tmp/coloutPipe | colout "^([0-9]+)(:) (.+?) (=) " red,blue,white,blue normal,normal,bold,normal | colout "(@)(0x\S+)(:)" red,blue,red normal & + logging_on +end +define hookpost-display + logging_off +end + + From 80a55281c5f71fe0ffb3de419e02cea63013fbaa Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 17:11:25 +0100 Subject: [PATCH 077/116] Remove six --- colout/colout.py | 1 - 1 file changed, 1 deletion(-) diff --git a/colout/colout.py b/colout/colout.py index 40335fd..656adc7 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -7,7 +7,6 @@ import os import re -import six import sys import copy import glob From ae33bac9d7f5cf35c9fe34bf4c855ef9eb1204bd Mon Sep 17 00:00:00 2001 From: Csaba Kertesz Date: Tue, 7 Aug 2018 09:04:16 +0300 Subject: [PATCH 078/116] Update the PPA information --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 187f828..7688266 100644 --- a/README.md +++ b/README.md @@ -97,9 +97,9 @@ or sudo easy_install colout -Ubuntu 13.04's ppa +Ubuntu PPA for 16.04 (Xenial)/18.04 (Bionic) - sudo add-apt-repository ppa:ciici123/colout + sudo add-apt-repository ppa:csaba-kertesz/random sudo apt-get update sudo apt-get/aptitude install colout From b62b57512d4b344728cb53ebc0ecf0d2c1cf81bb Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 14 Aug 2018 14:31:55 +0200 Subject: [PATCH 079/116] (almost) silently handle (weird) errors from pygments --- colout/colout.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 656adc7..29ca071 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -306,14 +306,17 @@ def load_lexers(): from pygments.lexers import get_all_lexers except ImportError: logging.warning("the pygments module has not been found, syntax coloring is not available") - pass else: - for lexer in get_all_lexers(): - try: - lexers.append(lexer[1][0]) - except IndexError: - logging.warning("cannot load lexer: %s" % lexer[1][0]) - pass + try: + for lexer in get_all_lexers(): + try: + lexers.append(lexer[1][0]) + except IndexError: + logging.warning("cannot load lexer: %s" % lexer[1][0]) + pass + except: + logging.warning("error while executing the pygment module, syntax coloring is not available") + lexers.sort() logging.debug("loaded %i lexers: %s" % (len(lexers), ", ".join(lexers))) From a261a2dfa8e644f60d214eb87904a8e3394f637f Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 17:30:49 +0100 Subject: [PATCH 080/116] Use version from SCM --- .gitignore | 1 + setup.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9839280..56a1c24 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ build/ dist/ colout.egg-info/ +.eggs/ diff --git a/setup.py b/setup.py index a79d0cf..a693306 100644 --- a/setup.py +++ b/setup.py @@ -16,9 +16,11 @@ packages = ['colout'] requires = ['argparse; python_version < "2.7"', 'pygments', 'babel'] +setup_requires = ['setuptools_scm'] + setup( name='colout', - version='0.6', + use_scm_version=True, description='Color Up Arbitrary Command Output.', long_description=open('README.md').read(), author='nojhan', @@ -28,6 +30,7 @@ setup( package_data={'': ['LICENSE', 'README.md']}, package_dir={'colout': 'colout'}, scripts=['bin/colout'], + setup_requires=setup_requires, include_package_data=True, install_requires=requires, license='GPLv3', From cfcd61fd2f470e6a220a9c5e97992df068c737ca Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 17:52:58 +0100 Subject: [PATCH 081/116] Add Travis smoke test --- .travis.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0ddc514 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +language: python +python: + - "2.6" + - "2.7" + - "3.2" + - "3.3" + - "3.4" + - "3.5" + - "3.6" + - "3.7-dev" + - "pypy" + - "pypy3" +install: + - pip install . +script: colout --help From 7d848d09e8b5152c804e325b70099274dc88787f Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 18:26:17 +0100 Subject: [PATCH 082/116] Add package classifiers --- setup.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/setup.py b/setup.py index a693306..a96f95c 100644 --- a/setup.py +++ b/setup.py @@ -18,9 +18,22 @@ requires = ['argparse; python_version < "2.7"', 'pygments', 'babel'] setup_requires = ['setuptools_scm'] +classifiers = """ +Environment :: Console +License :: OSI Approved :: GNU General Public License v3 (GPLv3) +Programming Language :: Python :: 2 +Programming Language :: Python :: 2.7 +Programming Language :: Python :: 3 +Programming Language :: Python :: 3.4 +Programming Language :: Python :: 3.5 +Programming Language :: Python :: 3.6 +Programming Language :: Python :: 3.7 +""".strip().split('\n') + setup( name='colout', use_scm_version=True, + classifiers=classifiers, description='Color Up Arbitrary Command Output.', long_description=open('README.md').read(), author='nojhan', From b0d41ab172bb4e13ad79cca5a43ac3e7107e92d7 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 18:39:23 +0100 Subject: [PATCH 083/116] Remove argparse requirement as code not 2.6 compatible --- .travis.yml | 1 - setup.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0ddc514..7d737cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: python python: - - "2.6" - "2.7" - "3.2" - "3.3" diff --git a/setup.py b/setup.py index a96f95c..f9fcbac 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ if sys.argv[-1] == 'publish': packages = ['colout'] -requires = ['argparse; python_version < "2.7"', 'pygments', 'babel'] +requires = ['pygments', 'babel'] setup_requires = ['setuptools_scm'] From e49b42db45a810c41524f9508d3a7bba0525832c Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 18:43:50 +0100 Subject: [PATCH 084/116] Add 3.3 classifier --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index f9fcbac..fdd69d2 100644 --- a/setup.py +++ b/setup.py @@ -24,6 +24,7 @@ License :: OSI Approved :: GNU General Public License v3 (GPLv3) Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 +Programming Language :: Python :: 3.3 Programming Language :: Python :: 3.4 Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 From 513552d5be29888f87dac2d0bf58d65465a877f4 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 18:44:11 +0100 Subject: [PATCH 085/116] Remove 3.2 smoke test as incompatible syntax --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7d737cb..4362143 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: python python: - "2.7" - - "3.2" - "3.3" - "3.4" - "3.5" From 7e3502d66757aa577b042e0e51d42307bec9bf38 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 18:50:39 +0100 Subject: [PATCH 086/116] Add another smoke test --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4362143..bd53a0b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,4 +10,6 @@ python: - "pypy3" install: - pip install . -script: colout --help +script: + - colout --help + - echo heyoo | colout hey yellow From a7a5f6adb8ca3e587d5c3b812e75f68a5a6d3e42 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 19:13:43 +0100 Subject: [PATCH 087/116] Publish universal wheel --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index fdd69d2..890b887 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ except ImportError: from distutils.core import setup if sys.argv[-1] == 'publish': - os.system('python3 setup.py sdist upload') + os.system('python setup.py bdist_wheel --universal upload') sys.exit() packages = ['colout'] From f9ec8cba39c7f52deaf40b3b8d036c6f2aeddf6e Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 20:18:21 +0100 Subject: [PATCH 088/116] Replace shell script with console scripts --- bin/colout | 11 ----------- colout/colout.py | 7 +++++-- setup.py | 4 +++- 3 files changed, 8 insertions(+), 14 deletions(-) delete mode 100644 bin/colout diff --git a/bin/colout b/bin/colout deleted file mode 100644 index 7702d17..0000000 --- a/bin/colout +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# Copyright (c) 2013 Martin Ueding - -# Small launcher script for the main module. - -# Licence: GPL 3 - -set -e -set -u - -python3 -m colout.colout "$@" diff --git a/colout/colout.py b/colout/colout.py index 29ca071..052d77e 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -927,8 +927,8 @@ def write_all( as_all, stream_in, stream_out, function, *args ): map_write( stream_in, stream_out, function, *args ) -if __name__ == "__main__": - +def main(): + global context error_codes = {"UnknownColor":1, "DuplicatedPalette":2, "MixedModes":3} usage = "A regular expression based formatter that color up an arbitrary text stream." @@ -1108,3 +1108,6 @@ if __name__ == "__main__": + " Check the following 'color:mode' pairs: %s." % e ) sys.exit( error_codes["MixedModes"] ) + +if __name__ == "__main__": + main() diff --git a/setup.py b/setup.py index 890b887..d844893 100644 --- a/setup.py +++ b/setup.py @@ -36,6 +36,9 @@ setup( use_scm_version=True, classifiers=classifiers, description='Color Up Arbitrary Command Output.', + entry_points={ + 'console_scripts': ['colout=colout.colout:main'], + }, long_description=open('README.md').read(), author='nojhan', author_email='nojhan@nojhan.net', @@ -43,7 +46,6 @@ setup( packages=packages, package_data={'': ['LICENSE', 'README.md']}, package_dir={'colout': 'colout'}, - scripts=['bin/colout'], setup_requires=setup_requires, include_package_data=True, install_requires=requires, From 177a37dd3768e286c36f36e4222c9ef1282ee74b Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 20:49:01 +0100 Subject: [PATCH 089/116] Update documentation --- README.md | 59 ++++++++++++++++++++----------------------------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 7688266..5fb788e 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ colout(1) -- Color Up Arbitrary Command Output ============================================== -## SYNOPSIS +## Synopsis `colout` [-h] [-r RESOURCE] `colout` [-g] [-c] [-l min,max] [-a] [-t] [-T DIR] [-P DIR] [-d COLORMAP] [-s] [-e CHAR] [-E CHAR] [--debug] PATTERN [COLOR(S) [STYLE(S)]] -## DESCRIPTION +## Description `colout` read lines of text stream on the standard input and output characters matching a given regular expression *PATTERN* in given *COLOR* and *STYLE*. @@ -77,37 +77,28 @@ use the `-r` switch (see below). `colout` is released under the GNU Public License v3. -## INSTALLATION +## Installation - sudo python3 setup.py install +The reccomended method is using [pipsi](https://github.com/mitsuhiko/pipsi) +``` +pipsi install colout +``` -and then soft link `/usr/local/bin/colout` to your colout.py under your installation -directory, which is usually something like +Another method is to use pip to install the package for the local user: - /usr/local/lib/python3/dist-packages/colout-0.1-py3.egg/colout/colout.py +``` +pip install --user colout +``` +There is also a PPA for Ubuntu 16.04 (Xenial)/18.04 (Bionic) -## OTHER INSTALLATION METHOD +``` +sudo add-apt-repository ppa:csaba-kertesz/random +sudo apt-get update +sudo apt-get/aptitude install colout +``` -Pypi (the Python Package Index) - - sudo pip install colout - -or - - sudo easy_install colout - -Ubuntu PPA for 16.04 (Xenial)/18.04 (Bionic) - - sudo add-apt-repository ppa:csaba-kertesz/random - sudo apt-get update - sudo apt-get/aptitude install colout - -Gentoo - - sudo emerge colout - -## OPTIONS +## Options * `-h`, `--help`: Show a help message and exit @@ -164,7 +155,7 @@ Gentoo Debug mode: print what's going on internally, if you want to check what features are available. -## REGULAR EXPRESSIONS +## Regular expressions A regular expression (or _regex_) is a pattern that describes a set of strings that matches it. @@ -174,15 +165,7 @@ that matches it. special characters that would be recognize by your shell. -## DEPENDENCIES - -Recommended packages: - -* `pygments` for the source code syntax coloring -* `babel` for a locale-aware number parsing - - -## LIMITATIONS +## Limitations Don't use nested groups or colout will duplicate the corresponding input text with each matching colors. @@ -192,7 +175,7 @@ Using a default colormap that is incompatible with the special colormap's mode Color pairs ("foreground.background") work in 8-colors mode for simple coloring, but may fail with `--colormap`. -## EXAMPLES +## Examples ### Simple From b77d79e596c54083c3ad7d25e77291b30d891f3e Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 21:38:23 +0100 Subject: [PATCH 090/116] Mark python version support --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index d844893..0be5ef3 100644 --- a/setup.py +++ b/setup.py @@ -46,6 +46,7 @@ setup( packages=packages, package_data={'': ['LICENSE', 'README.md']}, package_dir={'colout': 'colout'}, + python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*', setup_requires=setup_requires, include_package_data=True, install_requires=requires, From 741665553596ed71dcb0763c4e034ed46c8cba5f Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 21:40:00 +0100 Subject: [PATCH 091/116] Remove references to pygments as optional --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5fb788e..cce451b 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,8 @@ Before interpreting the matched string as a number, colout will remove any character not supposed to be used to write down numbers. This permits to apply this special color on a large group, while interpreting only its numerical part. -If the python3-pygments library is installed, you can use the name of a -syntax-coloring "lexer" as a color (for example: "Cpp", "ruby", "xml+django", etc.). +You can use the name of a syntax-coloring ["lexer"](http://pygments.org/docs/lexers/) +as a color (for example: "Cpp", "ruby", "xml+django", etc.). If GIMP palettes files (\*.gpl) are available, you can also use their names as a colormap (see the `-P` switch below). @@ -68,8 +68,7 @@ When not specified, a *COLOR* defaults to _red_ and a *STYLE* defaults to _bold_ `colout` comes with some predefined themes to rapidly color well-known outputs (see the `-t` switch below). -If the python3-pygments library is available, `colout` can be used as an interface -to it (see also the `-s` switch below). +`colout` can be used as an interface to pygments (see also the `--source` switch below). To have a list of all colors, styles, special colormaps, themes, palettes and lexers, use the `-r` switch (see below). From 3644dc06191844ed1687aefd176d1ddb1c04742e Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 21:54:44 +0100 Subject: [PATCH 092/116] Fix error_codes scope + more informative lexer error --- colout/colout.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 052d77e..63ef9ac 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -42,6 +42,8 @@ context["styles"] = { "reverse": 7, "conceal": 8 } +error_codes = {"UnknownColor": 1, "DuplicatedPalette": 2, "MixedModes": 3, "UnknownLexer": 4} + # Available color names in 8-colors mode. eight_colors = ["black","red","green","yellow","blue","magenta","cyan","white"] # Given in that order, the ASCII code is the index. @@ -929,8 +931,6 @@ def write_all( as_all, stream_in, stream_out, function, *args ): def main(): global context - error_codes = {"UnknownColor":1, "DuplicatedPalette":2, "MixedModes":3} - usage = "A regular expression based formatter that color up an arbitrary text stream." ##################### @@ -1075,7 +1075,12 @@ def main(): # if pygments elif as_source: logging.debug("asked for lexer: %s" % pattern.lower()) - assert(pattern.lower() in context["lexers"]) + if pattern.lower() not in context["lexers"]: + logging.error("Lexer %r is not one of %s" % ( + pattern, + ", ".join(repr(lexer) for lexer in context["lexers"]), + )) + sys.exit(error_codes["UnknownLexer"]) lexer = get_lexer_by_name(pattern.lower()) # Python => 256 colors, python => 8 colors ask_256 = pattern[0].isupper() From 161777d679add5d92e82140e1a0a78f49a8b92a8 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 22:02:05 +0100 Subject: [PATCH 093/116] Remove references to pygments+babel being optional --- colout/colout.py | 80 ++++++++++++++++-------------------------------- 1 file changed, 27 insertions(+), 53 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 63ef9ac..6b5d619 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -20,6 +20,7 @@ import logging import argparse import importlib import functools +import babel.numbers as bn # set the SIGPIPE handler to kill the program instead of # ending in a write error when a broken pipe occurs @@ -292,35 +293,31 @@ def load_lexers(): global context # load available pygments lexers lexers = [] + global get_lexer_by_name + from pygments.lexers import get_lexer_by_name + + global highlight + from pygments import highlight + + global Terminal256Formatter + from pygments.formatters import Terminal256Formatter + + global TerminalFormatter + from pygments.formatters import TerminalFormatter + + from pygments.lexers import get_all_lexers try: - global get_lexer_by_name - from pygments.lexers import get_lexer_by_name + for lexer in get_all_lexers(): + try: + lexers.append(lexer[1][0]) + except IndexError: + logging.warning("cannot load lexer: %s" % lexer[1][0]) + pass + except: + logging.warning("error while executing the pygment module, syntax coloring is not available") - global highlight - from pygments import highlight - - global Terminal256Formatter - from pygments.formatters import Terminal256Formatter - - global TerminalFormatter - from pygments.formatters import TerminalFormatter - - from pygments.lexers import get_all_lexers - except ImportError: - logging.warning("the pygments module has not been found, syntax coloring is not available") - else: - try: - for lexer in get_all_lexers(): - try: - lexers.append(lexer[1][0]) - except IndexError: - logging.warning("cannot load lexer: %s" % lexer[1][0]) - pass - except: - logging.warning("error while executing the pygment module, syntax coloring is not available") - - lexers.sort() - logging.debug("loaded %i lexers: %s" % (len(lexers), ", ".join(lexers))) + lexers.sort() + logging.debug("loaded %i lexers: %s" % (len(lexers), ", ".join(lexers))) context["lexers"] = lexers @@ -411,23 +408,11 @@ def color_scale( name, text ): nb = "".join([i for i in filter(allowed.__contains__, text)]) # interpret as decimal - # First, try with the babel module, if available - # if not, use python itself, - # if thoses fails, try to `eval` the string - # (this allow strings like "1/2+0.9*2") f = None try: - # babel is a specialized module - import babel.numbers as bn - try: - f = float(bn.parse_decimal(nb)) - except bn.NumberFormatError: - pass - except ImportError: - try: - f = float(nb) - except ValueError: - pass + f = float(bn.parse_decimal(nb)) + except bn.NumberFormatError: + pass if f is not None: # normalize with scale if it's a number f = (f - context["scale"][0]) / (context["scale"][1]-context["scale"][0]) @@ -832,11 +817,6 @@ def _args_parse(argv, usage=""): help="A regular expression") pygments_warn=" You can use a language name to activate syntax coloring (see `-r all` for a list)." - try: - import pygments - except ImportError: - pygments_warn=" (WARNING: python3-pygments is not available, \ - install it if you want to be able to use syntax coloring)" parser.add_argument("color", metavar="COLOR", type=str, nargs='?', default="red", @@ -856,12 +836,6 @@ def _args_parse(argv, usage=""): (cycle the colors at each match)") babel_warn=" (numbers will be parsed according to your locale)" - try: - # babel is a specialized module - import babel.numbers - except ImportError: - babel_warn=" (WARNING: python3-babel is not available, install it \ - if you want to be able to parse numbers according to your locale)" parser.add_argument("-l", "--scale", metavar="SCALE", help="When using the 'scale' colormap, parse matches as decimal numbers \ From b8e259add3d596036a6365343c7d680a5b0b8040 Mon Sep 17 00:00:00 2001 From: Oliver Bristow Date: Sat, 4 Aug 2018 22:08:23 +0100 Subject: [PATCH 094/116] Make missing lexer error less verbose --- colout/colout.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 6b5d619..3cfaa61 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -1050,10 +1050,7 @@ def main(): elif as_source: logging.debug("asked for lexer: %s" % pattern.lower()) if pattern.lower() not in context["lexers"]: - logging.error("Lexer %r is not one of %s" % ( - pattern, - ", ".join(repr(lexer) for lexer in context["lexers"]), - )) + logging.error("Lexer %r is not available. Run with \"--resources all\" to see the options.") sys.exit(error_codes["UnknownLexer"]) lexer = get_lexer_by_name(pattern.lower()) # Python => 256 colors, python => 8 colors From 6256b3058204d61ca43bb0e3833e4e95441b63cc Mon Sep 17 00:00:00 2001 From: Jeff Quast Date: Sun, 7 Oct 2018 23:40:47 -0700 Subject: [PATCH 095/116] this might help.. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should prevent the following error, ``` $ pip --version pip 18.1 from /Users/jq/.pyenv/versions/3.6.5/envs/jupyter/lib/python3.6/site-packages/pip (python 3.6) $ pip install colout Collecting colout Downloading https://files.pythonhosted.org/packages/3d/ba/3ef31c0df3ace69271cc8b1af6b529f24de66ff42c0d99a8d18aa980a307/colout-0.5.tar.gz (47kB) 100% |████████████████████████████████| 51kB 970kB/s Complete output from command python setup.py egg_info: Traceback (most recent call last): File "", line 1, in File "/private/var/folders/0x/y8s2qlk558596kyqdhv3nwv40000gn/T/pip-install-gixoekff/colout/setup.py", line 25, in long_description=open('README.md').read(), FileNotFoundError: [Errno 2] No such file or directory: 'README.md' ---------------------------------------- Command "python setup.py egg_info" failed with error code 1 in /private/var/folders/0x/y8s2qlk558596kyqdhv3nwv40000gn/T/pip-install-gixoekff/colout/ ``` --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a79d0cf..33e99b4 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ setup( name='colout', version='0.6', description='Color Up Arbitrary Command Output.', - long_description=open('README.md').read(), + long_description=open(os.path.join(os.path.dirname(__file__), 'README.md')).read(), author='nojhan', author_email='nojhan@nojhan.net', url='http://nojhan.github.com/colout/', From dab5555503b07fe3e1f730a2bdebd97f4b535c8c Mon Sep 17 00:00:00 2001 From: linkmauve Date: Thu, 19 Dec 2019 00:51:29 +0100 Subject: [PATCH 096/116] Update colout.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Python 2 will retire in thirteen days (see https://pythonclock.org/), there is no reason to keep obsolete checks in the code any longer. --- colout/colout.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 29ca071..b346d0e 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -30,8 +30,6 @@ signal.signal( signal.SIGPIPE, signal.SIG_DFL ) # Global variable(s) ############################################################################### -PY2 = sys.version_info.major == 2 - context = {} debug = False @@ -757,9 +755,6 @@ def write(colored, stream = sys.stdout): """ Write "colored" on sys.stdout, then flush. """ - if PY2: # If Python 2.x: force unicode - if isinstance(colored, unicode): - colored = colored.encode('utf-8') try: stream.write(colored) stream.flush() From 88b177015224e16d398f46dae9e69ef0db159d10 Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 27 May 2020 17:40:09 +0200 Subject: [PATCH 097/116] get back Dependencies section in README --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index cce451b..ed30681 100644 --- a/README.md +++ b/README.md @@ -164,6 +164,14 @@ that matches it. special characters that would be recognize by your shell. +## Dependencies + +Necessary Python modules: + +* `pygments` for the source code syntax coloring +* `babel` for a locale-aware number parsing + + ## Limitations Don't use nested groups or colout will duplicate the corresponding input text From 01aedcc64255a4919489a098c1beb4d91c64c594 Mon Sep 17 00:00:00 2001 From: Stavros Ntentos <133706+stdedos@users.noreply.github.com> Date: Wed, 27 May 2020 22:45:06 +0300 Subject: [PATCH 098/116] Prepare for new `colout` version Because there is a weird `v0.11` tag, we pick the next version `v0.12.0`, instead of the "real" next version aka `v0.7.0` This project is considered to use Semantic Versioning (https://semver.org/) (https://semver.org/spec/v2.0.0.html as of now) Python versioning updates: * Unify that package is offered for >=Python3.5 2.7 support was dropped in dab5555503b07fe3e1f730a2bdebd97f4b535c8c, and <3.5 versions do not exist in https://devguide.python.org/#status-of-python-branches as of committing time * Add some classifiers (YMMV, my first pip package) * Add some bare-bones `tox` configuration (YMMV, my first tox interaction) * Add packages required for packaging/deployment in `requirements-build.txt` * `README.md` is not required to be packaged anymore - it is read at install time * Fix Content-Type for PyPI * Update `README.md`: * Reorder installation options (`pip` > `pipsi` > `ppa`) * Hard wrap at 100 chars for "meaningful" offences. * Add myself as maintainer * Remove escapes that don't make sense in CommonMark (GFM, as project is hosted in Github) * Fix typos * Add a more complete `.gitignore` file --- .gitignore | 161 ++++++++++++++++++++++++++++++++++++++++- .travis.yml | 7 +- MANIFEST.in | 1 - README.md | 90 +++++++++++++---------- requirements-build.txt | 3 + setup.py | 16 ++-- tox.ini | 15 ++++ 7 files changed, 239 insertions(+), 54 deletions(-) create mode 100644 requirements-build.txt create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore index 56a1c24..c2a9c3f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,162 @@ -*.pyc +## Python gitignore +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python build/ +develop-eggs/ dist/ -colout.egg-info/ +downloads/ +eggs/ .eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +## Jetbrains +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# Editor-based Rest Client +.idea/httpRequests + +# SonarLint +.idea/sonarlint + +# CMake +cmake-build-*/ + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties diff --git a/.travis.yml b/.travis.yml index bd53a0b..b7997b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,9 @@ language: python python: - - "2.7" - - "3.3" - - "3.4" - "3.5" - "3.6" - - "3.7-dev" - - "pypy" + - "3.7" + - "3.8" - "pypy3" install: - pip install . diff --git a/MANIFEST.in b/MANIFEST.in index 04f196a..1aba38f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1 @@ -include README.md include LICENSE diff --git a/README.md b/README.md index ed30681..2e0f115 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ colout(1) -- Color Up Arbitrary Command Output ## Synopsis -`colout` [-h] [-r RESOURCE] +`colout [-h] [-r RESOURCE]` -`colout` [-g] [-c] [-l min,max] [-a] [-t] [-T DIR] [-P DIR] [-d COLORMAP] [-s] [-e CHAR] [-E CHAR] [--debug] PATTERN [COLOR(S) [STYLE(S)]] +`colout [-g] [-c] [-l min,max] [-a] [-t] [-T DIR] [-P DIR] [-d COLORMAP] [-s] [-e CHAR] [-E CHAR] [--debug] PATTERN [COLOR(S) [STYLE(S)]]` ## Description @@ -25,10 +25,12 @@ rainbow, random, Random, Spectrum, spectrum, scale, Scale, hash, Hash, none, an RGB hexadecimal triplet (`#11aaff`, for example) or any number between 0 and 255. Available styles are: normal, bold, faint, italic, underline, blink, -rapid\_blink, reverse, conceal or random (some styles may have no effect, depending +rapid_blink, reverse, conceal or random (some styles may have no effect, depending on your terminal). -In some case, you can indicate a foreground and a background color, by indicating boths colors separated by a period(for example: `red.blue`). You can also use this system to combine two styles (for example, for a bold style that also blinks: `bold.blink`). +In some case, you can indicate a foreground and a background color, by indicating both colors +separated by a period (for example: `red.blue`). You can also use this system to combine two styles +(for example, for a bold style that also blinks: `bold.blink`). `rainbow` will cycle over a the default colormap at each matching pattern. `Rainbow` will do the same over the default colormap for the 256-colors mode @@ -57,7 +59,7 @@ this special color on a large group, while interpreting only its numerical part. You can use the name of a syntax-coloring ["lexer"](http://pygments.org/docs/lexers/) as a color (for example: "Cpp", "ruby", "xml+django", etc.). -If GIMP palettes files (\*.gpl) are available, you can also use their names as a +If GIMP palettes files (*.gpl) are available, you can also use their names as a colormap (see the `-P` switch below). Note that the RGB colors (either the hex triplets or the palettes's colors) will @@ -78,23 +80,24 @@ use the `-r` switch (see below). ## Installation -The reccomended method is using [pipsi](https://github.com/mitsuhiko/pipsi) -``` -pipsi install colout +The recomended method is using pip to install the package for the local user: + +```console +$ pip install --user colout ``` -Another method is to use pip to install the package for the local user: - -``` -pip install --user colout +Another method is using [pipsi](https://github.com/mitsuhiko/pipsi) +(_pipsi is no longer maintained, _) +```console +$ pipsi install colout ``` -There is also a PPA for Ubuntu 16.04 (Xenial)/18.04 (Bionic) +There is also a PPA for Ubuntu 16.04 (Xenial)/18.04 (Bionic) (@`0.6.1-3~dist7`, not actively maintained) -``` -sudo add-apt-repository ppa:csaba-kertesz/random -sudo apt-get update -sudo apt-get/aptitude install colout +```console +$ sudo add-apt-repository ppa:csaba-kertesz/random +$ sudo apt-get update +$ sudo apt-get/aptitude install colout ``` ## Options @@ -109,8 +112,8 @@ sudo apt-get/aptitude install colout Use the given list of comma-separated colors as a colormap (cycle the colors at each match). * `-l min,max`, `--scale min,max`: - When using the 'scale' colormap, parse matches as decimal numbers (taking your locale into account) - or as arithmetic expression (like "1+2/0.9\*3") and apply the rainbow colormap linearly + When using the 'scale' colormap, parse matches as decimal numbers (taking your locale into + account) or as arithmetic expression (like "1+2/0.9*3") and apply the rainbow colormap linearly between the given min,max (0,100, by default). * `-a`, `--all`: @@ -121,10 +124,10 @@ sudo apt-get/aptitude install colout Interpret PATTERN as a predefined theme (perm, cmake, g++, etc.). * `-T DIR`, `--themes-dir DIR`: - Search for additional themes (colout\_\*.py files) in this directory. + Search for additional themes (colout_*.py files) in this directory. * `-P DIR`, `--palettes-dir DIR`: - Search for additional palettes (\*.gpl files) in this directory. + Search for additional palettes (*.gpl files) in this directory. * `-d COLORMAP`, `--default COLORMAP`: When using special colormaps (`random`, `scale` or `hash`), use this COLORMAP instead of the default one. @@ -180,7 +183,7 @@ with each matching colors. Using a default colormap that is incompatible with the special colormap's mode (i.e. number of colors) will end badly. -Color pairs ("foreground.background") work in 8-colors mode for simple coloring, but may fail with `--colormap`. +Color pairs (`foreground.background`) work in 8-colors mode for simple coloring, but may fail with `--colormap`. ## Examples @@ -192,7 +195,7 @@ Color pairs ("foreground.background") work in 8-colors mode for simple coloring, * Color in bold violet home directories in _/etc/passwd_: `colout '/home/[a-z]+' 135 < /etc/passwd` -* Color in yellow user/groups id, in bold green name and in bold red home directories in _/etc/passwd_: +* Color in yellow user/groups id, in bold green name and in bold red home directories in `/etc/passwd`: `colout ':x:([0-9]+:[0-9]+):([^:]+).*(/home/[a-z]+)' yellow,green,red normal,bold < /etc/passwd` * Color in yellow file permissions with read rights for everyone: @@ -256,11 +259,13 @@ Color pairs ("foreground.background") work in 8-colors mode for simple coloring, The following bash function color the output of any command with the cmake and g++ themes: - function cm() - { - set -o pipefail - $@ 2>&1 | colout -t cmake | colout -t g++ - } +```bash +function cm() +{ + set -o pipefail + $@ 2>&1 | colout -t cmake | colout -t g++ +} +``` You then can use the `cm` alias as a prefix to your build command, for example: `cm make test` @@ -329,32 +334,36 @@ Take a look at the `example.gdbinit` file distributed with colout for more gdb c ### Themes You can easily add your own theme to colout. -A theme is basically a module with a function named `theme` that take the configuration context as an argument and -return back the (modified) context and a list of triplets. +A theme is basically a module with a function named `theme` that take the configuration context as +an argument and return back the (modified) context and a list of triplets. Each triplet figures the same arguments than those of the command line interface. - def theme(context): - return context,[ [regexp, colors, styles] ] +```python +def theme(context): + return context,[ [regexp, colors, styles] ] +``` -With the context dictionary at hand, you have access to the internal configuration of colout, you can thus change colormaps for -special keywords, the scale, even the available colors, styles or themes. +With the context dictionary at hand, you have access to the internal configuration of colout, you +can thus change colormaps for special keywords, the scale, even the available colors, styles or +themes. -See the cmake theme for how to modify an existing colormap if (and only if) the user didn't ask for an -alternative one. -See the ninja theme for how to extend an existing theme with more regexps and a different configuration. +See the cmake them for how to modify an existing colormap if (and only if) the user didn't ask for an alternative one. +See the ninja theme for how to extend an existing theme with more regexps and a different configuration. See the gcc theme for an example of how to use the localization of existing softwares to build translated regexp. ### Buffering -Note that when you use colout within real time streams (like `tail -f X | grep Y | colout Z`) of commands, -you may observe that the lines are printed by large chunks and not one by one, in real time. +Note that when you use colout within real time streams (like `tail -f X | grep Y | colout Z`) of +commands, you may observe that the lines are printed by large chunks and not one by one, in real +time. This is not due to colout but to the buffering behavior of your shell. + To fix that, use `stdbuf`, for example: `tail -f X | stdbuf -o0 grep Y | colout Z`. ## Authors -* nojhan : original idea, main developer, maintener. +* nojhan : original idea, main developer, maintainer. * Adrian Sadłocha * Alex Burka * Brian Foley @@ -377,3 +386,4 @@ To fix that, use `stdbuf`, for example: `tail -f X | stdbuf -o0 grep Y | colout * Piotr Staroszczyk * Scott Lawrence * Xu Di +* https://github.com/stdedos: maintainer. diff --git a/requirements-build.txt b/requirements-build.txt new file mode 100644 index 0000000..d50412d --- /dev/null +++ b/requirements-build.txt @@ -0,0 +1,3 @@ +tox +tox-wheel +twine diff --git a/setup.py b/setup.py index 9457291..887c0eb 100644 --- a/setup.py +++ b/setup.py @@ -20,15 +20,18 @@ setup_requires = ['setuptools_scm'] classifiers = """ Environment :: Console +Development Status :: 5 - Production/Stable License :: OSI Approved :: GNU General Public License v3 (GPLv3) -Programming Language :: Python :: 2 -Programming Language :: Python :: 2.7 -Programming Language :: Python :: 3 -Programming Language :: Python :: 3.3 -Programming Language :: Python :: 3.4 +Operating System :: POSIX +Operating System :: POSIX :: Linux +Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 +Programming Language :: Python :: 3.8 +Topic :: Utilities +Topic :: Text Processing +Topic :: Text Processing :: Filters """.strip().split('\n') setup( @@ -40,13 +43,14 @@ setup( 'console_scripts': ['colout=colout.colout:main'], }, long_description=open(os.path.join(os.path.dirname(__file__), 'README.md')).read(), + long_description_content_type='text/markdown;variant=CommonMark', author='nojhan', author_email='nojhan@nojhan.net', url='http://nojhan.github.com/colout/', packages=packages, package_data={'': ['LICENSE', 'README.md']}, package_dir={'colout': 'colout'}, - python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*', + python_requires='>=3.5', setup_requires=setup_requires, include_package_data=True, install_requires=requires, diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..ff4e1ca --- /dev/null +++ b/tox.ini @@ -0,0 +1,15 @@ +[tox] +envlist=py35,py36,py37,py38,cov + +[testenv] +wheel = true +deps= + pytest + pytest-cov + pytest-xdist +setenv= + py{35,36,37,38}: COVERAGE_FILE=.coverage.{envname} +commands= + py{35,36,37,38}: python -m pytest --cov=colout --cov-report=term-missing --no-cov-on-fail + cov: coverage combine + cov: coverage html --fail-under=85 From 707f499f4aefaa9d6eb37d35717fbc827b4bee52 Mon Sep 17 00:00:00 2001 From: nojhan Date: Thu, 4 Jun 2020 09:53:33 +0200 Subject: [PATCH 099/116] fix cmake theme Do not match the ":" in CMake Error --- colout/colout_cmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index 252fc2f..ae9027d 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -25,7 +25,7 @@ def theme(context): [ "^-- Configuring incomplete, errors occurred!", "red" ], [ "^--.*", performing ], # Errors - [ "CMake Error:", "red" ], + [ "CMake Error", "red" ], [ "CMake Warning", "yellow" ], # Scan [ "^(Scanning dependencies of target)(.*)$", From d9f1e69997f1fdc9ed6599c977fdc8a20815fde3 Mon Sep 17 00:00:00 2001 From: linkmauve Date: Sat, 1 Aug 2020 20:59:59 +0200 Subject: [PATCH 100/116] Stop advertising python2 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit python2 support got removed in dab5555503b07fe3e1f730a2bdebd97f4b535c8c, this shouldn’t be advertised anymore. --- setup.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 9457291..0b5e4c7 100644 --- a/setup.py +++ b/setup.py @@ -21,8 +21,6 @@ setup_requires = ['setuptools_scm'] classifiers = """ Environment :: Console License :: OSI Approved :: GNU General Public License v3 (GPLv3) -Programming Language :: Python :: 2 -Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.3 Programming Language :: Python :: 3.4 @@ -46,7 +44,7 @@ setup( packages=packages, package_data={'': ['LICENSE', 'README.md']}, package_dir={'colout': 'colout'}, - python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*', + python_requires='>=3.3', setup_requires=setup_requires, include_package_data=True, install_requires=requires, From a41eea11d25178a1802cad07d6ec25bf36ae1744 Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Thu, 12 May 2022 12:00:11 +0200 Subject: [PATCH 101/116] fix(syntax coloring): load all lexers, even those without aliases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some Pygments’ lexers are registered without any alias, just with their long name. This ensure that they are loaded, along with the others. --- colout/colout.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 39e8a0f..8c64d68 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -306,11 +306,21 @@ def load_lexers(): from pygments.lexers import get_all_lexers try: for lexer in get_all_lexers(): - try: - lexers.append(lexer[1][0]) - except IndexError: + l = None + # If the tuple has one-word aliases + # (which are usually a better option than the long names + # for a command line argument). + if lexer[1]: + l = lexer[1][0] # Take the first one. + else: + assert(lexer[0]) + l = lexer[0] # Take the long name, which should alway exists. + if not l: logging.warning("cannot load lexer: %s" % lexer[1][0]) - pass + pass # Forget about this lexer. + else: + assert(" " not in l) # Should be very rare, but probably a source of bugs. + lexers.append(l) except: logging.warning("error while executing the pygment module, syntax coloring is not available") From 86d26db9480ab9b56c4fe7c0434ae4142d7e9459 Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 31 Aug 2022 22:44:29 +0200 Subject: [PATCH 102/116] add a logo --- README.md | 6 +- colout_logo.svg | 612 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 616 insertions(+), 2 deletions(-) create mode 100644 colout_logo.svg diff --git a/README.md b/README.md index 2e0f115..6880d59 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ -colout(1) -- Color Up Arbitrary Command Output -============================================== +colout — Color Up Arbitrary Command Output +========================================== + +![Colout logo](https://raw.githubusercontent.com/nojhan/colout/master/colout_logo.svg") ## Synopsis diff --git a/colout_logo.svg b/colout_logo.svg new file mode 100644 index 0000000..8db7984 --- /dev/null +++ b/colout_logo.svg @@ -0,0 +1,612 @@ + + + + + colout logo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + colout logo + 2022-08-31 + + + nojhan + + + + + + From 6a490a483df69cbb04d3fb37b110be129fe26ed3 Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 31 Aug 2022 22:47:01 +0200 Subject: [PATCH 103/116] fix logo display --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6880d59..9d51e02 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,13 @@ colout — Color Up Arbitrary Command Output ========================================== -![Colout logo](https://raw.githubusercontent.com/nojhan/colout/master/colout_logo.svg") +

+Colout logo +

## Synopsis From 4ca64294852fd929e5f2b38e3cb9cc6dd02e6acf Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 20 Jan 2023 09:24:14 +0100 Subject: [PATCH 104/116] feat(cmake): improve cmake and ctest themes --- colout/colout_cmake.py | 3 ++- colout/colout_ctest.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index ae9027d..a9588ca 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -26,7 +26,8 @@ def theme(context): [ "^--.*", performing ], # Errors [ "CMake Error", "red" ], - [ "CMake Warning", "yellow" ], + [ "CMake Warning", "magenta" ], + [ "CMake Deprecation Warning", "magenta" ], # Scan [ "^(Scanning dependencies of target)(.*)$", performing, "normal,bold" ], diff --git a/colout/colout_ctest.py b/colout/colout_ctest.py index ba7e56e..ee6e36d 100644 --- a/colout/colout_ctest.py +++ b/colout/colout_ctest.py @@ -2,6 +2,7 @@ def theme(context): # CTest theme: passed="green" + notrun="yellow" notpassed="red" # If the user do not ask for his own colormap @@ -13,5 +14,6 @@ def theme(context): return context,[ # Passed [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+\s+(Passed)", "blue,"+passed], - [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(\*{3}.*)\s+.*", "blue,"+notpassed] + [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(\*{3}Not Run.*)\s+.*", "blue,"+notrun], + [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(.*\*{3}.*)\s+.*", "blue,"+notpassed], ] From 0839d955a9714fbb1519c159b202f2b28a702cea Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 20 Jan 2023 09:24:44 +0100 Subject: [PATCH 105/116] feat(latex): improve latex theme --- colout/colout_latex.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/colout/colout_latex.py b/colout/colout_latex.py index c19287f..7c57be5 100644 --- a/colout/colout_latex.py +++ b/colout/colout_latex.py @@ -19,7 +19,8 @@ def theme(context): ["(Output written on) (.*) \(([0-9]+ pages), [0-9]+ bytes\).", "blue,white,blue", "normal,bold,normal"], ["WARNING.*", "magenta", "normal"], - ["warning.*", "magenta", "normal"], + ["[wW]arning.*", "magenta", "normal"], + ["No pages of output", "red", "bold"], # BiBTeX ["^(I couldn't) (.*)", "red", "normal,bold"], From 6e623e897be64433843de28de472d268a476a982 Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 14 Feb 2023 09:07:10 +0100 Subject: [PATCH 106/116] feat(theme): add the SLURM theme Coloring all known states with a consistent scheme. --- colout/colout_slurm.py | 117 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 colout/colout_slurm.py diff --git a/colout/colout_slurm.py b/colout/colout_slurm.py new file mode 100644 index 0000000..9f5af8d --- /dev/null +++ b/colout/colout_slurm.py @@ -0,0 +1,117 @@ + +def theme(context): + # SLURM's states (from squeue manual). + + col_width = 9 + + COMPLETED =r"\bCOMPLETED" + PENDING =r"\bPENDING" + RUNNING =r"\bRUNNING" + CONFIGURING =r"\bCONFIGURING" + COMPLETING =r"\bCOMPLETING" + FAILED =r"\bFAILED" + DEADLINE =r"\bDEADLINE" + OUT_OF_MEMORY=r"\bOUT_OF_MEMORY" + TIMEOUT =r"\bTIMEOUT" + CANCELLED =r"\bCANCELLED" + BOOT_FAIL =r"\bBOOT_FAIL" + NODE_FAIL =r"\bNODE_FAIL" + PREEMPTED =r"\bPREEMPTED" + RESV_DEL_HOLD=r"\bRESV_DEL_HOLD" + REQUEUE_FED =r"\bREQUEUE_FED" + REQUEUE_HOLD =r"\bREQUEUE_HOLD" + REQUEUED =r"\bREQUEUED" + RESIZING =r"\bRESIZING" + REVOKED =r"\bREVOKED" + SIGNALING =r"\bSIGNALING" + SPECIAL_EXIT =r"\bSPECIAL_EXIT" + STAGE_OUT =r"\bSTAGE_OUT" + STOPPED =r"\bSTOPPED" + SUSPENDED =r"\bSUSPENDED" + + return context,[ + + ## No problem: greens + + #Job has terminated all processes on all nodes with an exit code of zero. + [r"\bCD\b", "22"], + [COMPLETED[0:col_width]+r"\w*\b", "22"], + #Job is awaiting resource allocation. + [r"\bPD\b", "28"], + [PENDING[0:col_width]+r"\w*\b", "28"], + #Job currently has an allocation. + [r"\bR\b", "34"], + [RUNNING[0:col_width]+r"\w*\b", "34"], + #Job has been allocated resources, but are waiting for them to become ready for use (e.g. booting). + [r"\bCF\b", "58"], + [CONFIGURING[0:col_width]+r"\w*\b", "58"], + #Job is in the process of completing. Some processes on some nodes may still be active. + [r"\bCG\b", "23"], + [COMPLETING[0:col_width]+r"\w*\b", "23"], + + ## Problem for the user: bold reds + + #Job terminated with non-zero exit code or other failure condition. + [r"\bF\b", "196"], + [FAILED[0:col_width]+r"\w*\b", "196", "bold"], + #Job terminated on deadline. + [r"\bDL\b", "160"], + [DEADLINE[0:col_width]+r"\w*\b", "160", "bold"], + #Job experienced out of memory error. + [r"\bOO\b", "197"], + [OUT_OF_MEMORY[0:col_width]+r"\w*\b", "197", "bold"], + #Job terminated upon reaching its time limit. + [r"\bTO\b", "161"], + [TIMEOUT[0:col_width]+r"\w*\b", "161", "bold"], + + ## Problem for the sysadmin: oranges + + #Job was explicitly cancelled by the user or system administrator. The job may or may not have been initiated. + [r"\bCA\b", "202"], + [CANCELLED[0:col_width]+r"\w*\b", "202", "bold"], + #Job terminated due to launch failure, typically due to a hardware failure (e.g. unable to boot the node or block and the job can not be requeued). + [r"\bBF\b", "166"], + [BOOT_FAIL[0:col_width]+r"\w*\b", "166"], + #Job terminated due to failure of one or more allocated nodes. + [r"\bNF\b", "208"], + [NODE_FAIL[0:col_width]+r"\w*\b", "208"], + + ## Non-blocking events: blues + + #Job terminated due to preemption. + [r"\bPR\b", "105"], + [PREEMPTED[0:col_width]+r"\w*\b", "105", "bold"], + #Job is being held after requested reservation was deleted. + [r"\bRD\b", "25"], + [RESV_DEL_HOLD[0:col_width]+r"\w*\b", "25"], + #Job is being requeued by a federation. + [r"\bRF\b", "26"], + [REQUEUE_FED[0:col_width]+r"\w*\b", "26"], + #Held job is being requeued. + [r"\bRH\b", "27"], + [REQUEUE_HOLD[0:col_width]+r"\w*\b", "27"], + #Completing job is being requeued. + [r"\bRQ\b", "31"], + [REQUEUED[0:col_width]+r"\w*\b", "31"], + #Job is about to change size. + [r"\bRS\b", "32"], + [RESIZING[0:col_width]+r"\w*\b", "32"], + #Sibling was removed from cluster due to other cluster starting the job. + [r"\bRV\b", "33"], + [REVOKED[0:col_width]+r"\w*\b", "33"], + #Job is being signaled. + [r"\bSI\b", "37"], + [SIGNALING[0:col_width]+r"\w*\b", "37"], + #The job was requeued in a special state. This state can be set by users, typically in EpilogSlurmctld, if the job has terminated with a particular exit value. + [r"\bSE\b", "38"], + [SPECIAL_EXIT[0:col_width]+r"\w*\b", "38"], + #Job is staging out files. + [r"\bSO\b", "39"], + [STAGE_OUT[0:col_width]+r"\w*\b", "39"], + #Job has an allocation, but execution has been stopped with SIGSTOP signal. CPUS have been retained by this job. + [r"\bST\b", "44"], + [STOPPED[0:col_width]+r"\w*\b", "44"], + #Job has an allocation, but execution has been suspended and CPUs have been released for other jobs. + [r"\bS\b", "45"], + [SUSPENDED[0:col_width]+r"\w*\b", "45"], + ] From 657a13eee19df8661ba9cd0c63895ee96640049b Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 14 Feb 2023 09:08:12 +0100 Subject: [PATCH 107/116] feat(theme): add the Django theme For coloring Django's logs. --- colout/colout_django.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 colout/colout_django.py diff --git a/colout/colout_django.py b/colout/colout_django.py new file mode 100644 index 0000000..e6ca473 --- /dev/null +++ b/colout/colout_django.py @@ -0,0 +1,36 @@ + +def theme(context): + return context,[ + # Waiting + ["^Waiting for .*$", "red", "bold"], + [".*Sending.*", "green"], + # Watches + ["^(Watching) (\S*) (.*)", "yellow", "bold,bold,normal"], + [".*reloading.$","yellow"], + # File from python/lib + ["^(File) (/.*/lib/python[^/]*/site-packages/)([^/]*)\S* (first seen) (with mtime [0-9]*.*)$", + "blue,blue,white,blue,blue", "bold,normal,bold,bold,normal"], + # File from app (last 3 name highlighted) + ["^(File) (/\S*/)(\S*/\S*/)(\S*) (first seen) (with mtime [0-9]*.*)$", + "magenta,magenta,white,white,magenta,magenta", "bold,normal,normal,bold,bold,normal"], + # SQL + ["(.*)(SELECT)(.*)(FROM)(.*)", + "green", "normal,bold,normal,bold,normal"], + ["(.*)(SELECT)(.*)(FROM)(.*)(WHERE)(.*)", + "green", "normal,bold,normal,bold,normal,bold,normal"], + # HTTP + ["\"(GET) (\S*) (HTTP\S*)\" ([0-9]+) (.*)$", + "green,white,green,green,green", "bold,bold,normal,bold,normal"], + # Errors + ["(Exception) (while .*) '(.*)' (in) (.*) '(.*)'", "red,red,white,red,red,white", "bold,normal,bold,bold,normal,bold"], + ["(.*Error): (.*) '(.*)'", "red,red,white", "bold,normal,bold"], + ["(django[^:\s]*)\.([^.:\s]*): (.*)", "red","normal,bold,normal"], + ["Traceback.*:","yellow"], + ["During handling.*","yellow"], + # File, line, in + [ + "^\s{2}(File \")(/*.*?/)*([^/:]+)(\", line) ([0-9]+)(, in) (.*)$", + "blue, none, white,blue, yellow,blue", + "normal,normal,bold, normal,normal,bold" + ], + ] From 186dc04a86000e7c482b19012511233fb30e251e Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 7 Apr 2023 16:09:52 +0200 Subject: [PATCH 108/116] adds a Catch2 theme --- colout/colout_catch2.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 colout/colout_catch2.py diff --git a/colout/colout_catch2.py b/colout/colout_catch2.py new file mode 100644 index 0000000..600b1a2 --- /dev/null +++ b/colout/colout_catch2.py @@ -0,0 +1,23 @@ +def theme(context): + + return context,[ + ["^ (Start)(.*): (.*):(.*)$", "yellow", "normal,normal,normal,bold"], # Test start. + # path file ext:line : + ["^(tests): (/.*?)/([^/:]+):([0-9]+): (.*)", "yellow,none,white,yellow,red", "bold,normal,bold,normal,bold"], + ["(`)(.*)('.*)", "red,Cpp,red", "bold,normal,bold"], + ["^\.+$", "yellow", "bold"], + ["^=+$", "yellow", "bold"], + ["(/.*?)/([^/:]+):([0-9]+): (FAILED):", "white,white,yellow,red", "normal,bold,normal,bold"], + ["(REQUIRE\(|CHECK\(|REQUIRE_THAT\()(.*)(\))$","yellow,Cpp,yellow","bold,normal,bold"], + # Hide uninteresting stuff: + ["[0-9]+/[0-9]+ Test.*","blue"], + ["^Filters:.*","blue"], + ["^Randomness seeded to:.*","blue"], + ["^tests is a Catch2.*","blue"], + ["^Run with.*", "blue"], + ["^~+$","blue"], + ["^-+$","blue"], + ["^\s*(Scenario:|Given:|When:|Then:).*","blue"], + ["^(/.*?)/([^/:]+):([0-9]+)", "blue"], + ["^(test cases|assertions)(.*)", "blue"], + ] From b20fd4e18e0069f7405496f04ae2b7216db0c987 Mon Sep 17 00:00:00 2001 From: "Konstantin Pavlov (ug)" Date: Tue, 11 Apr 2023 10:07:56 +0300 Subject: [PATCH 109/116] Add theme for AMD/Xilinx Vivado tool --- colout/colout_vivado.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 colout/colout_vivado.py diff --git a/colout/colout_vivado.py b/colout/colout_vivado.py new file mode 100644 index 0000000..72d211d --- /dev/null +++ b/colout/colout_vivado.py @@ -0,0 +1,24 @@ + +def theme(context): + # Theme for coloring AMD/Xilinx Vivado IDE synthesis and implementation output + return context,[ + [ "^#.+", "green" ], + [ "^.+ Checksum: .+$", "green" ], + + [ "^.+Time \(s\).+", "green" ], + [ "^Time \(s\).+", "green" ], + + [ "Estimated Timing Summary \|.+\|.+\|", "cyan", "bold" ], + [ "Intermediate Timing Summary \|.+\|.+\|", "cyan", "bold" ], + + [ "^INFO:", "white", "bold" ], + [ "^WARNING:.+$", "yellow" ], + [ "^CRITICAL WARNING:.+$", "red" ], + [ "^ERROR:.+$", "red" ], + + [ "^Phase [0-9]+.[0-9]+.[0-9]+.[0-9]+.+$", "magenta", "bold" ], + [ "^Phase [0-9]+.[0-9]+.[0-9]+.+$", "magenta", "bold" ], + [ "^Phase [0-9]+.[0-9]+.+$", "magenta", "bold" ], + [ "^Phase [0-9]+.+$", "magenta", "bold" ] + ] + From 292760c568433d734b48d842566a520c284c8285 Mon Sep 17 00:00:00 2001 From: "Konstantin Pavlov (ug)" Date: Fri, 14 Apr 2023 16:54:08 +0300 Subject: [PATCH 110/116] Fast commit --- colout/colout_vivado.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/colout/colout_vivado.py b/colout/colout_vivado.py index 72d211d..1e5d8a0 100644 --- a/colout/colout_vivado.py +++ b/colout/colout_vivado.py @@ -2,7 +2,9 @@ def theme(context): # Theme for coloring AMD/Xilinx Vivado IDE synthesis and implementation output return context,[ + [ "^\s*\*+.+$", "green" ], [ "^#.+", "green" ], + [ "^.+ Checksum: .+$", "green" ], [ "^.+Time \(s\).+", "green" ], From 1c07ace0e2bd3ccfc4c9334b2c9fd0d7448bca42 Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 28 Jun 2023 21:00:08 +0200 Subject: [PATCH 111/116] fix: do not chdir when looking for files Allow relative paths for palettes and themes. Refs: #114 Co-authored-by: FedericoStra --- colout/colout.py | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 8c64d68..85ed7b0 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -249,13 +249,13 @@ def hex_to_rgb(h): def load_themes( themes_dir): global context logging.debug("search for themes in: %s" % themes_dir) - os.chdir( themes_dir ) sys.path.append( themes_dir ) # load available themes - for f in glob.iglob("colout_*.py"): - module = ".".join(f.split(".")[:-1]) # remove extension - name = "_".join(module.split("_")[1:]) # remove the prefix + for f in glob.iglob(os.path.join(themes_dir, "colout_*.py")): + basename = os.path.basename(f) # Remove path. + module = os.path.splitext(basename)[0] # Remove extension. + name = "_".join(module.split("_")[1:]) # Remove the 'colout_' prefix. if name in context["themes"]: raise DuplicatedTheme(name) logging.debug("load theme %s" % name) @@ -265,10 +265,9 @@ def load_themes( themes_dir): def load_palettes( palettes_dir, ignore_duplicates = True ): global context logging.debug("search for palettes in: %s" % palettes_dir) - os.chdir( palettes_dir ) # load available colormaps (GIMP palettes format) - for p in glob.iglob("*.gpl"): + for p in glob.iglob(os.path.join(palettes_dir, "*.gpl")): try: name,palette = parse_gimp_palette(p) except Exception as e: @@ -947,23 +946,17 @@ def main(): # try additional directories if asked if palettes_dirs: for adir in palettes_dirs: - try: - os.chdir( adir ) - except OSError as e: - logging.warning("cannot read palettes directory %s, ignore it" % adir) - continue - else: + if os.path.isdir(adir): load_palettes( adir ) + else: + logging.warning("cannot read palettes directory %s, ignore it" % adir) if themes_dirs: for adir in themes_dirs: - try: - os.chdir( adir ) - except OSError as e: - logging.warning("cannot read themes directory %s, ignore it" % adir) - continue - else: + if os.path.isdir(adir): load_themes( adir ) + else: + logging.warning("cannot read themes directory %s, ignore it" % adir) except DuplicatedPalette as e: logging.error( "duplicated palette file name: %s" % e ) From 05c345f3a4167d3116d7261996662071f802b69b Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 10 Jul 2023 18:24:32 +0200 Subject: [PATCH 112/116] fix --resources [all] Allow passing `-r` without argument to display all resources. Ref: #81 Co-authored-by: tomasohara --- README.md | 6 +++--- colout/colout.py | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9d51e02..10bde37 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ colout — Color Up Arbitrary Command Output ## Synopsis -`colout [-h] [-r RESOURCE]` +`colout [-h] [-r [RESOURCE]]` `colout [-g] [-c] [-l min,max] [-a] [-t] [-T DIR] [-P DIR] [-d COLORMAP] [-s] [-e CHAR] [-E CHAR] [--debug] PATTERN [COLOR(S) [STYLE(S)]]` @@ -145,10 +145,10 @@ $ sudo apt-get/aptitude install colout Also, external palettes are converted from RGB to 256-ANSI and will thus not work if you use them as default colormaps for a 8-colors mode special color. -* `-r TYPE(S)`, `--resources TYPE(S)`: +* `-r [TYPE(S)]`, `--resources [TYPE(S)]`: Print the names of available resources. Use a comma-separated list of resources names (styles, colors, special, themes, palettes, colormaps or lexers), - use 'all' to print everything. + use 'all' (or no argument) to print all resources. * `-s`, `--source`: Interpret PATTERN as source code readable by the Pygments library. If the first letter of PATTERN diff --git a/colout/colout.py b/colout/colout.py index 85ed7b0..b7fd863 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -889,6 +889,10 @@ def _args_parse(argv, usage=""): parser.add_argument("--debug", action="store_true", help="Debug mode: print what's going on internally, useful if you want to check what features are available.") + # HACK: Mock up "--resources ALL" if just "--resources" on command line + if (len(sys.argv) == 2 and (sys.argv[1] in ["-r", "--resources"])): + sys.argv.append("ALL") + args = parser.parse_args() return args.pattern[0], args.color, args.style, args.groups, \ From 1bb4d60513a9dae22809c8b3a422bd3c11b9abdc Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 10 Jul 2023 18:25:40 +0200 Subject: [PATCH 113/116] fix: end in an error if the asked resources is unknown --- colout/colout.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/colout/colout.py b/colout/colout.py index b7fd863..94b80c9 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -41,7 +41,7 @@ context["styles"] = { "reverse": 7, "conceal": 8 } -error_codes = {"UnknownColor": 1, "DuplicatedPalette": 2, "MixedModes": 3, "UnknownLexer": 4} +error_codes = {"UnknownColor": 1, "DuplicatedPalette": 2, "MixedModes": 3, "UnknownLexer": 4, "UnknownResource": 5} # Available color names in 8-colors mode. eight_colors = ["black","red","green","yellow","blue","magenta","cyan","white"] @@ -985,33 +985,49 @@ def main(): return ", ".join(sorted(l, key=lambda s: s.lower()+s)) # print("Available resources:") + resources_not_found = [] for res in asked: + resource_found = False + if "style" in res or "all" in res: print("STYLES: %s" % join_sort(context["styles"]) ) + resource_found = True if "color" in res or "all" in res: print("COLORS: %s" % join_sort(context["colors"]) ) + resource_found = True if "special" in res or "all" in res: print("SPECIAL: %s" % join_sort(["random", "Random", "scale", "Scale", "hash", "Hash", "colormap"]) ) + resource_found = True if "theme" in res or "all" in res: if len(context["themes"]) > 0: print("THEMES: %s" % join_sort(context["themes"].keys()) ) else: print("NO THEME") + resource_found = True if "colormap" in res or "all" in res: if len(context["colormaps"]) > 0: print("COLORMAPS: %s" % join_sort(context["colormaps"]) ) else: print("NO COLORMAPS") + resource_found = True if "lexer" in res or "all" in res: if len(context["lexers"]) > 0: print("SYNTAX COLORING: %s" % join_sort(context["lexers"]) ) else: print("NO SYNTAX COLORING (check that python3-pygments is installed)") + resource_found = True + + if not resource_found: + resources_not_found.append(res) + + if resources_not_found: + logging.error( "Unknown resources: %s" % ", ".join(resources_not_found) ) + sys.exit( error_codes["UnknownResource"] ) sys.exit(0) # not an error, we asked for help From 6a8fe89969cc4ccd6f89bdccd075b659579399c6 Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 29 Jan 2024 22:31:13 +0100 Subject: [PATCH 114/116] add clang theme --- colout/colout_clang.py | 86 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) mode change 120000 => 100644 colout/colout_clang.py diff --git a/colout/colout_clang.py b/colout/colout_clang.py deleted file mode 120000 index 2df53b5..0000000 --- a/colout/colout_clang.py +++ /dev/null @@ -1 +0,0 @@ -colout_g++.py \ No newline at end of file diff --git a/colout/colout_clang.py b/colout/colout_clang.py new file mode 100644 index 0000000..c4abe03 --- /dev/null +++ b/colout/colout_clang.py @@ -0,0 +1,85 @@ +#encoding: utf-8 + +def default_gettext( msg ): + return msg + +def theme(context): + import os + import gettext + import locale + + section="blue" + + # get g++ version + gv = os.popen("g++ -dumpversion").read().strip() + + # get the current translations of gcc + try: + t = gettext.translation("gcc-"+gv) + except IOError: + _ = default_gettext + else: + _ = t.gettext + # _("msg") will return the given message, translated + + # if the locale is unicode + enc = locale.getpreferredencoding() + if "UTF" in enc: + # gcc will use unicode quotes + qo = "[‘`]" + qc = "[’']" + else: + # rather than ascii ones + qo = "['`]" + qc = "'" + + return context,[ + # Command line + [ "[/\s]([cg]\+\+-*[0-9]*\.*[0-9]*)", "white", "bold" ], + [ "\s(\-D)(\s*[^\s]+)", "none,green", "normal,bold" ], + [ "\s(-g)", "green", "normal" ], + [ "\s-O[0-4]", "green", "normal" ], + [ "\s-[Wf][^\s]*", "magenta", "normal" ], + [ "\s-pedantic", "magenta", "normal" ], + [ "\s(-I)(/*[^\s]+/)([^/\s]+)", "none,blue", "normal,normal,bold" ], + [ "\s(-L)(/*[^\s]+/)([^/\s]+)", "none,cyan", "normal,normal,bold" ], + [ "\s(-l)([^/\s]+)", "none,cyan", "normal,bold" ], + [ "\s-[oc]", "red", "bold" ], + [ "\s(-+std(?:lib)?)=?([^\s]+)", "red", "normal,bold" ], + + # Important messages + [ _("error: "), "red", "bold" ], + [ _("fatal error: "), "red", "bold" ], + [ _("warning: "), "magenta", "bold" ], + [ _("undefined reference to "), "red", "bold" ], + # [-Wflag] + [ "\[-W.*\]", "magenta"], + + # Highlight message start: + # path file ext : line : col … + [ "(/.*?)/([^/:]+): (In .*)"+qo, + section, + "normal,normal,bold" ], + + [ "(/.*?)/([^/:]+): (At .*)", + section, + "normal,normal,bold" ], + + [ _("In file included from"), section ], + + # Highlight locations: + # path file ext : line : col … + [ "(/.*?)/([^/:]+):([0-9]+):*([0-9]*)(.*)", + "none,white,yellow,none,none", + "normal,normal,normal,normal" ], + + # source code in single quotes + [ qo+"(.*?)"+qc, "Cpp", "monokai" ], + + # source code after a "note: candidate are/is:" + [ _("note: ")+"((?!.*("+qo+"|"+qc+")).*)$", "Cpp", "monokai" ], + # [ _("note: ")+"(candidate:)(.*)$", "green,Cpp", "normal,monokai" ], + # after the code part, to avoid matching ANSI escape chars + [ _("note: "), "green", "normal" ] + ] + From 49d0b9884321a44f67a401a5c00d144dc190acb7 Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 14 Oct 2024 14:33:09 +0200 Subject: [PATCH 115/116] fix(tests): remove unit tests unable to handle raw strings --- colout/colout.py | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/colout/colout.py b/colout/colout.py index 94b80c9..2d51fac 100755 --- a/colout/colout.py +++ b/colout/colout.py @@ -177,7 +177,7 @@ def parse_gimp_palette( filename ): palette = [] for line in lines: # skip lines with only a comment - if re.match("^\s*#.*$", line ): + if re.match(r"^\s*#.*$", line ): continue # decode the columns-ths codes. Generally [R G B] followed by a comment colors = [ int(c) for c in line.split()[:columns] ] @@ -663,20 +663,8 @@ def colorup(text, pattern, color="red", style="normal", on_groups=False, sep_lis in which case the different matching groups may be formatted differently. If there is less colors/styles than groups, the last format is used for the additional groups. - - >>> colorup("Fetchez la vache", "vache", "red", "bold") - 'Fetchez la \x1b[1;31mvache\x1b[0m' - >>> colorup("Faites chier la vache", "[Fv]a", "red", "bold") - '\x1b[1;31mFa\x1b[0mites chier la \x1b[1;31mva\x1b[0mche' - >>> colorup("Faites Chier la Vache", "[A-Z](\S+)\s", "red", "bold") - 'F\x1b[1;31maites\x1b[0m C\x1b[1;31mhier\x1b[0m la Vache' - >>> colorup("Faites Chier la Vache", "([A-Z])(\S+)\s", "red,green", "bold") - '\x1b[1;31mF\x1b[0m\x1b[1;32maites\x1b[0m \x1b[1;31mC\x1b[0m\x1b[1;32mhier\x1b[0m la Vache' - >>> colorup("Faites Chier la Vache", "([A-Z])(\S+)\s", "green") - '\x1b[0;32mF\x1b[0m\x1b[0;32maites\x1b[0m \x1b[0;32mC\x1b[0m\x1b[0;32mhier\x1b[0m la Vache' - >>> colorup("Faites Chier la Vache", "([A-Z])(\S+)\s", "blue", "bold,italic") - '\x1b[1;34mF\x1b[0m\x1b[3;34maites\x1b[0m \x1b[1;34mC\x1b[0m\x1b[3;34mhier\x1b[0m la Vache' """ + global context global debug From d20d094db0ebbadbcdfa0e6c5c6ad49ce4b0d302 Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 14 Oct 2024 14:41:16 +0200 Subject: [PATCH 116/116] fix(themes): use raw strings where applicable --- colout/colout_catch2.py | 6 +++--- colout/colout_clang.py | 24 ++++++++++++------------ colout/colout_cmake.py | 14 +++++++------- colout/colout_configure.py | 4 ++-- colout/colout_ctest.py | 6 +++--- colout/colout_django.py | 12 ++++++------ colout/colout_g++.py | 24 ++++++++++++------------ colout/colout_javac.py | 14 +++++++------- colout/colout_json.py | 6 +++--- colout/colout_latex.py | 12 ++++++------ colout/colout_ninja.py | 4 ++-- colout/colout_perm.py | 2 +- colout/colout_python.py | 8 ++++---- colout/colout_valgrind.py | 36 ++++++++++++++++++------------------ colout/colout_vivado.py | 10 +++++----- 15 files changed, 91 insertions(+), 91 deletions(-) diff --git a/colout/colout_catch2.py b/colout/colout_catch2.py index 600b1a2..e67d86a 100644 --- a/colout/colout_catch2.py +++ b/colout/colout_catch2.py @@ -5,10 +5,10 @@ def theme(context): # path file ext:line : ["^(tests): (/.*?)/([^/:]+):([0-9]+): (.*)", "yellow,none,white,yellow,red", "bold,normal,bold,normal,bold"], ["(`)(.*)('.*)", "red,Cpp,red", "bold,normal,bold"], - ["^\.+$", "yellow", "bold"], + [r"^\.+$", "yellow", "bold"], ["^=+$", "yellow", "bold"], ["(/.*?)/([^/:]+):([0-9]+): (FAILED):", "white,white,yellow,red", "normal,bold,normal,bold"], - ["(REQUIRE\(|CHECK\(|REQUIRE_THAT\()(.*)(\))$","yellow,Cpp,yellow","bold,normal,bold"], + [r"(REQUIRE\(|CHECK\(|REQUIRE_THAT\()(.*)(\))$","yellow,Cpp,yellow","bold,normal,bold"], # Hide uninteresting stuff: ["[0-9]+/[0-9]+ Test.*","blue"], ["^Filters:.*","blue"], @@ -17,7 +17,7 @@ def theme(context): ["^Run with.*", "blue"], ["^~+$","blue"], ["^-+$","blue"], - ["^\s*(Scenario:|Given:|When:|Then:).*","blue"], + [r"^\s*(Scenario:|Given:|When:|Then:).*","blue"], ["^(/.*?)/([^/:]+):([0-9]+)", "blue"], ["^(test cases|assertions)(.*)", "blue"], ] diff --git a/colout/colout_clang.py b/colout/colout_clang.py index c4abe03..a5525ef 100644 --- a/colout/colout_clang.py +++ b/colout/colout_clang.py @@ -35,17 +35,17 @@ def theme(context): return context,[ # Command line - [ "[/\s]([cg]\+\+-*[0-9]*\.*[0-9]*)", "white", "bold" ], - [ "\s(\-D)(\s*[^\s]+)", "none,green", "normal,bold" ], - [ "\s(-g)", "green", "normal" ], - [ "\s-O[0-4]", "green", "normal" ], - [ "\s-[Wf][^\s]*", "magenta", "normal" ], - [ "\s-pedantic", "magenta", "normal" ], - [ "\s(-I)(/*[^\s]+/)([^/\s]+)", "none,blue", "normal,normal,bold" ], - [ "\s(-L)(/*[^\s]+/)([^/\s]+)", "none,cyan", "normal,normal,bold" ], - [ "\s(-l)([^/\s]+)", "none,cyan", "normal,bold" ], - [ "\s-[oc]", "red", "bold" ], - [ "\s(-+std(?:lib)?)=?([^\s]+)", "red", "normal,bold" ], + [ r"[/\s]([cg]\+\+-*[0-9]*\.*[0-9]*)", "white", "bold" ], + [ r"\s(\-D)(\s*[^\s]+)", "none,green", "normal,bold" ], + [ r"\s(-g)", "green", "normal" ], + [ r"\s-O[0-4]", "green", "normal" ], + [ r"\s-[Wf][^\s]*", "magenta", "normal" ], + [ r"\s-pedantic", "magenta", "normal" ], + [ r"\s(-I)(/*[^\s]+/)([^/\s]+)", "none,blue", "normal,normal,bold" ], + [ r"\s(-L)(/*[^\s]+/)([^/\s]+)", "none,cyan", "normal,normal,bold" ], + [ r"\s(-l)([^/\s]+)", "none,cyan", "normal,bold" ], + [ r"\s-[oc]", "red", "bold" ], + [ r"\s(-+std(?:lib)?)=?([^\s]+)", "red", "normal,bold" ], # Important messages [ _("error: "), "red", "bold" ], @@ -53,7 +53,7 @@ def theme(context): [ _("warning: "), "magenta", "bold" ], [ _("undefined reference to "), "red", "bold" ], # [-Wflag] - [ "\[-W.*\]", "magenta"], + [ r"\[-W.*\]", "magenta"], # Highlight message start: # path file ext : line : col … diff --git a/colout/colout_cmake.py b/colout/colout_cmake.py index a9588ca..66ab5a8 100644 --- a/colout/colout_cmake.py +++ b/colout/colout_cmake.py @@ -36,20 +36,20 @@ def theme(context): [ "^(Linking .* )(library|executable) (.*)$", untimed, "normal,normal,bold" ], # [percent] Creating something - [ "^\[\s*[0-9/]+%?\]\s(.*Creating.*)$", + [ r"^\[\s*[0-9/]+%?\]\s(.*Creating.*)$", performing, "normal" ], # [percent] Built - [ "^\[\s*[0-9/]+%?\]\s(Built target)(\s.*)$", + [ r"^\[\s*[0-9/]+%?\]\s(Built target)(\s.*)$", performed, "normal,bold" ], # [percent] Building - [ "^\[\s*[0-9/]+%?\]\s(Building \w* object)\s+(.*)(\.dir)(.*/)([-\w]+).c.*.o$", + [ r"^\[\s*[0-9/]+%?\]\s(Building \w* object)\s+(.*)(\.dir)(.*/)([-\w]+).c.*.o$", performing+","+performing+","+performing+",Hash,"+performing, "normal,normal,normal,normal,bold"], # [percent] Generating - [ "^\[\s*[0-9/]+%?\]\s(Generating)(\s+.*)$", + [ r"^\[\s*[0-9/]+%?\]\s(Generating)(\s+.*)$", performing, "normal,bold"], # make errors - [ "make\[[0-9]+\].*", "yellow"], - [ "(make: \*\*\* \[.+\] )(.* [0-9]+)", "red", "normal,bold"], + [ r"make\[[0-9]+\].*", "yellow"], + [ r"(make: \*\*\* \[.+\] )(.* [0-9]+)", "red", "normal,bold"], # progress percentage (make) - [ "^(\[\s*[0-9]+%\])","Scale" ] + [ r"^(\[\s*[0-9]+%\])","Scale" ] ] diff --git a/colout/colout_configure.py b/colout/colout_configure.py index 2f5e2b7..63e63a4 100644 --- a/colout/colout_configure.py +++ b/colout/colout_configure.py @@ -11,6 +11,6 @@ def theme(context): ["^(config.status:) (creating|linking)(.*)", "cyan,blue","normal,normal,bold"], ["^(config.status:) (executing )(.*)", "cyan,green","normal,normal,bold"], ["^(config.status:) (.*)(is unchanged)", "cyan,green","normal,normal,bold"], - ["^\s*(Build.*)(yes)$","green", "normal,bold"], - ["^\s*(Build.*)(no)$","yellow", "normal,bold"], + [r"^\s*(Build.*)(yes)$","green", "normal,bold"], + [r"^\s*(Build.*)(no)$","yellow", "normal,bold"], ] diff --git a/colout/colout_ctest.py b/colout/colout_ctest.py index ee6e36d..f2dd372 100644 --- a/colout/colout_ctest.py +++ b/colout/colout_ctest.py @@ -13,7 +13,7 @@ def theme(context): return context,[ # Passed - [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+\s+(Passed)", "blue,"+passed], - [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(\*{3}Not Run.*)\s+.*", "blue,"+notrun], - [ "^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(.*\*{3}.*)\s+.*", "blue,"+notpassed], + [ r"^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+\s+(Passed)", "blue,"+passed], + [ r"^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(\*{3}Not Run.*)\s+.*", "blue,"+notrun], + [ r"^\s*[0-9]+/[0-9]+ Test\s+#[0-9]+: (.*)\s+\.+(.*\*{3}.*)\s+.*", "blue,"+notpassed], ] diff --git a/colout/colout_django.py b/colout/colout_django.py index e6ca473..fcacc00 100644 --- a/colout/colout_django.py +++ b/colout/colout_django.py @@ -5,13 +5,13 @@ def theme(context): ["^Waiting for .*$", "red", "bold"], [".*Sending.*", "green"], # Watches - ["^(Watching) (\S*) (.*)", "yellow", "bold,bold,normal"], + [r"^(Watching) (\S*) (.*)", "yellow", "bold,bold,normal"], [".*reloading.$","yellow"], # File from python/lib - ["^(File) (/.*/lib/python[^/]*/site-packages/)([^/]*)\S* (first seen) (with mtime [0-9]*.*)$", + [r"^(File) (/.*/lib/python[^/]*/site-packages/)([^/]*)\S* (first seen) (with mtime [0-9]*.*)$", "blue,blue,white,blue,blue", "bold,normal,bold,bold,normal"], # File from app (last 3 name highlighted) - ["^(File) (/\S*/)(\S*/\S*/)(\S*) (first seen) (with mtime [0-9]*.*)$", + [r"^(File) (/\S*/)(\S*/\S*/)(\S*) (first seen) (with mtime [0-9]*.*)$", "magenta,magenta,white,white,magenta,magenta", "bold,normal,normal,bold,bold,normal"], # SQL ["(.*)(SELECT)(.*)(FROM)(.*)", @@ -19,17 +19,17 @@ def theme(context): ["(.*)(SELECT)(.*)(FROM)(.*)(WHERE)(.*)", "green", "normal,bold,normal,bold,normal,bold,normal"], # HTTP - ["\"(GET) (\S*) (HTTP\S*)\" ([0-9]+) (.*)$", + [r"\"(GET) (\S*) (HTTP\S*)\" ([0-9]+) (.*)$", "green,white,green,green,green", "bold,bold,normal,bold,normal"], # Errors ["(Exception) (while .*) '(.*)' (in) (.*) '(.*)'", "red,red,white,red,red,white", "bold,normal,bold,bold,normal,bold"], ["(.*Error): (.*) '(.*)'", "red,red,white", "bold,normal,bold"], - ["(django[^:\s]*)\.([^.:\s]*): (.*)", "red","normal,bold,normal"], + [r"(django[^:\s]*)\.([^.:\s]*): (.*)", "red","normal,bold,normal"], ["Traceback.*:","yellow"], ["During handling.*","yellow"], # File, line, in [ - "^\s{2}(File \")(/*.*?/)*([^/:]+)(\", line) ([0-9]+)(, in) (.*)$", + r"^\s{2}(File \")(/*.*?/)*([^/:]+)(\", line) ([0-9]+)(, in) (.*)$", "blue, none, white,blue, yellow,blue", "normal,normal,bold, normal,normal,bold" ], diff --git a/colout/colout_g++.py b/colout/colout_g++.py index c4abe03..a5525ef 100644 --- a/colout/colout_g++.py +++ b/colout/colout_g++.py @@ -35,17 +35,17 @@ def theme(context): return context,[ # Command line - [ "[/\s]([cg]\+\+-*[0-9]*\.*[0-9]*)", "white", "bold" ], - [ "\s(\-D)(\s*[^\s]+)", "none,green", "normal,bold" ], - [ "\s(-g)", "green", "normal" ], - [ "\s-O[0-4]", "green", "normal" ], - [ "\s-[Wf][^\s]*", "magenta", "normal" ], - [ "\s-pedantic", "magenta", "normal" ], - [ "\s(-I)(/*[^\s]+/)([^/\s]+)", "none,blue", "normal,normal,bold" ], - [ "\s(-L)(/*[^\s]+/)([^/\s]+)", "none,cyan", "normal,normal,bold" ], - [ "\s(-l)([^/\s]+)", "none,cyan", "normal,bold" ], - [ "\s-[oc]", "red", "bold" ], - [ "\s(-+std(?:lib)?)=?([^\s]+)", "red", "normal,bold" ], + [ r"[/\s]([cg]\+\+-*[0-9]*\.*[0-9]*)", "white", "bold" ], + [ r"\s(\-D)(\s*[^\s]+)", "none,green", "normal,bold" ], + [ r"\s(-g)", "green", "normal" ], + [ r"\s-O[0-4]", "green", "normal" ], + [ r"\s-[Wf][^\s]*", "magenta", "normal" ], + [ r"\s-pedantic", "magenta", "normal" ], + [ r"\s(-I)(/*[^\s]+/)([^/\s]+)", "none,blue", "normal,normal,bold" ], + [ r"\s(-L)(/*[^\s]+/)([^/\s]+)", "none,cyan", "normal,normal,bold" ], + [ r"\s(-l)([^/\s]+)", "none,cyan", "normal,bold" ], + [ r"\s-[oc]", "red", "bold" ], + [ r"\s(-+std(?:lib)?)=?([^\s]+)", "red", "normal,bold" ], # Important messages [ _("error: "), "red", "bold" ], @@ -53,7 +53,7 @@ def theme(context): [ _("warning: "), "magenta", "bold" ], [ _("undefined reference to "), "red", "bold" ], # [-Wflag] - [ "\[-W.*\]", "magenta"], + [ r"\[-W.*\]", "magenta"], # Highlight message start: # path file ext : line : col … diff --git a/colout/colout_javac.py b/colout/colout_javac.py index 0acaba0..92e5a2c 100644 --- a/colout/colout_javac.py +++ b/colout/colout_javac.py @@ -3,13 +3,13 @@ def theme(context): style="monokai" return context,[ - [ "^(.*\.java):([0-9]+):\s*(warning:.*)$", "white,yellow,magenta", "normal,normal,bold" ], - [ "^(.*\.java):([0-9]+):(.*)$", "white,yellow,red", "normal,normal,bold" ], - [ "^(symbol|location)\s*:\s*(.*)$", "blue,Java", "bold,"+style ], - [ "^(found)\s*:\s*(.*)", "red,Java", "bold,"+style ], - [ "^(required)\s*:\s*(.*)", "green,Java", "bold,"+style ], - [ "^\s*\^$", "cyan", "bold" ], - [ "^\s+.*$", "Java", style ], + [ r"^(.*\.java):([0-9]+):\s*(warning:.*)$", "white,yellow,magenta", "normal,normal,bold" ], + [ r"^(.*\.java):([0-9]+):(.*)$", "white,yellow,red", "normal,normal,bold" ], + [ r"^(symbol|location)\s*:\s*(.*)$", "blue,Java", "bold,"+style ], + [ r"^(found)\s*:\s*(.*)", "red,Java", "bold,"+style ], + [ r"^(required)\s*:\s*(.*)", "green,Java", "bold,"+style ], + [ r"^\s*\^$", "cyan", "bold" ], + [ r"^\s+.*$", "Java", style ], [ "[0-9]+ error[s]*", "red", "bold" ], [ "[0-9]+ warning[s]*", "magenta", "bold" ], ] diff --git a/colout/colout_json.py b/colout/colout_json.py index 62ddee4..2f9898e 100644 --- a/colout/colout_json.py +++ b/colout/colout_json.py @@ -3,10 +3,10 @@ def theme(context): # This theme expect a formatted JSON input, with items spread across lines. # See tools like "python -m json.tool" or "json_xs" return context,[ - [ '[\[\]{}],*\s*\n' ], + [ r'[\[\]{}],*\s*\n' ], [ '" (:) ', "yellow" ], - [ '[\]}"](,)', "yellow" ], - [ "\"(-*[0-9]+\.*[0-9]*e*-*[0-9]*)\"", "blue" ], + [ r'[\]}"](,)', "yellow" ], + [ r"\"(-*[0-9]+\.*[0-9]*e*-*[0-9]*)\"", "blue" ], [ '"(.*)"', "green" ], [ """["']""", "cyan" ] ] diff --git a/colout/colout_latex.py b/colout/colout_latex.py index 7c57be5..5567fbd 100644 --- a/colout/colout_latex.py +++ b/colout/colout_latex.py @@ -7,16 +7,16 @@ def theme(context): "magenta,magenta,white,magenta", "normal,bold,normal" ], ["(LaTeX Warning): (.*)", "magenta", "normal,bold" ], ["(LaTeX Error): (.*)", "red", "normal,bold" ], - ["^(.*\.tex):([0-9]+): (.*)", "white,yellow,red", "normal,normal,bold" ], + [r"^(.*\.tex):([0-9]+): (.*)", "white,yellow,red", "normal,normal,bold" ], # ["on (page [0-9]+)", "yellow", "normal" ], ["on input (line [0-9]+)", "yellow", "normal" ], ["^! .*$", "red", "bold"], - ["(.*erfull) ([^\s]+).* in [^\s]+ at (lines [0-9]+--[0-9]+)", + [r"(.*erfull) ([^\s]+).* in [^\s]+ at (lines [0-9]+--[0-9]+)", "magenta,magenta,yellow", "normal"], - ["\\[^\s]+\s", "white", "bold"], - ["^l\.([0-9]+) (.*)", "yellow,tex"], - ["^\s+(.*)", "tex"], - ["(Output written on) (.*) \(([0-9]+ pages), [0-9]+ bytes\).", + [r"\\[^\s]+\s", "white", "bold"], + [r"^l\.([0-9]+) (.*)", "yellow,tex"], + [r"^\s+(.*)", "tex"], + [r"(Output written on) (.*) \(([0-9]+ pages), [0-9]+ bytes\).", "blue,white,blue", "normal,bold,normal"], ["WARNING.*", "magenta", "normal"], ["[wW]arning.*", "magenta", "normal"], diff --git a/colout/colout_ninja.py b/colout/colout_ninja.py index 1d416c9..34dd9ec 100644 --- a/colout/colout_ninja.py +++ b/colout/colout_ninja.py @@ -11,9 +11,9 @@ def theme(context): context["scale"] = (0,1) # Link (ninja) - th.append( [ "^\[[0-9/]+\]\s?(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", + th.append( [ r"^\[[0-9/]+\]\s?(Linking .* )(library|executable) (.*/)*(.+(\.[aso]+)*)$", "blue", "normal,normal,bold" ] ) # progress percentage (ninja) - th.append( [ "^(\[[0-9]+/[0-9]+\])","Scale" ] ) + th.append( [ r"^(\[[0-9]+/[0-9]+\])","Scale" ] ) return context,th diff --git a/colout/colout_perm.py b/colout/colout_perm.py index ffcb2a5..048230c 100644 --- a/colout/colout_perm.py +++ b/colout/colout_perm.py @@ -1,7 +1,7 @@ def theme(context): p="([-rwxsStT])" - reg="^([-dpcCDlMmpPs?])"+p*9+"\s.*$" + reg=r"^([-dpcCDlMmpPs?])"+p*9+r"\s.*$" colors="blue"+",green"*3+",yellow"*3+",red"*3 styles="normal"+ ",normal,italic,bold"*3 return context,[ [reg, colors, styles] ] diff --git a/colout/colout_python.py b/colout/colout_python.py index 3623d04..40e4b34 100644 --- a/colout/colout_python.py +++ b/colout/colout_python.py @@ -5,16 +5,16 @@ def theme(context): ["^Traceback .*$", "blue" ], # File, line, in [ - "^\s{2}(File \")(/*.*?/)*([^/:]+)(\", line) ([0-9]+)(, in) (.*)$", + r"^\s{2}(File \")(/*.*?/)*([^/:]+)(\", line) ([0-9]+)(, in) (.*)$", "blue, none, white,blue, yellow,blue", "normal,normal,bold, normal,normal,bold" ], - # ["^\s{2}File \"(.*)\", line ([0-9]+), in (.*)$", "white,yellow,white", "normal,normal,bold" ], + # [r"^\s{2}File \"(.*)\", line ([0-9]+), in (.*)$", "white,yellow,white", "normal,normal,bold" ], # Error name ["^([A-Za-z]*Error):*", "red", "bold" ], ["^([A-Za-z]*Exception):*", "red", "bold" ], # any quoted things - ["Error.*['\"](.*)['\"]", "magenta" ], + [r"Error.*['\"](.*)['\"]", "magenta" ], # python code - ["^\s{4}.*$", "Python", "monokai" ], + [r"^\s{4}.*$", "Python", "monokai" ], ] diff --git a/colout/colout_valgrind.py b/colout/colout_valgrind.py index fe95982..7fc33a2 100644 --- a/colout/colout_valgrind.py +++ b/colout/colout_valgrind.py @@ -4,30 +4,30 @@ def theme(context): return context, [ # section title - ["^(==[0-9]+==\s{1})(Memcheck|Copyright|Using)(.*)$","blue",""], - ["^(==[0-9]+==\s{1})(Warning)(.*)$","magenta",""], - ["^(==[0-9]+==\s{1}Command: )(\S*)(.*)$","green,white","normal,bold,normal"], - ["^(==[0-9]+==\s{1})(HEAP SUMMARY:)(.*)$","green",""], - ["^(==[0-9]+==\s{1})(All heap blocks were freed)(.*)$","green",""], - ["^(==[0-9]+==\s{1})(.*[rR]erun.*)$","blue",""], - ["^(==[0-9]+==\s{1})(Use --.*)$","blue",""], - ["^(==[0-9]+==\s{1}\S+.*)$","red",""], + [r"^(==[0-9]+==\s{1})(Memcheck|Copyright|Using)(.*)$","blue",""], + [r"^(==[0-9]+==\s{1})(Warning)(.*)$","magenta",""], + [r"^(==[0-9]+==\s{1}Command: )(\S*)(.*)$","green,white","normal,bold,normal"], + [r"^(==[0-9]+==\s{1})(HEAP SUMMARY:)(.*)$","green",""], + [r"^(==[0-9]+==\s{1})(All heap blocks were freed)(.*)$","green",""], + [r"^(==[0-9]+==\s{1})(.*[rR]erun.*)$","blue",""], + [r"^(==[0-9]+==\s{1})(Use --.*)$","blue",""], + [r"^(==[0-9]+==\s{1}\S+.*)$","red",""], # section explanation - ["^==[0-9]+==\s{2}(\S+.*)$","orange",""], + [r"^==[0-9]+==\s{2}(\S+.*)$","orange",""], # locations adresses - ["^==[0-9]+==\s{4}([atby]{2}) (0x0): (\?{3})", + [r"^==[0-9]+==\s{4}([atby]{2}) (0x0): (\?{3})", "blue,yellow,red", "normal,normal,bold"], - ["^==[0-9]+==\s{4}([atby]{2}) (0x)([^:]*:) (\S+)", + [r"^==[0-9]+==\s{4}([atby]{2}) (0x)([^:]*:) (\S+)", "blue,blue,blue,none", "normal"], # locations: library - ["\(in (.*)\)", "cyan", "normal"], + [r"\(in (.*)\)", "cyan", "normal"], # locations: file - ["\(([^\.]*\.[^:]+):([0-9]+)\)", "white,yellow", "bold,normal"], + [r"\(([^\.]*\.[^:]+):([0-9]+)\)", "white,yellow", "bold,normal"], # leak summary - ["^==[0-9]+==\s{4}(definitely lost): .* (in) .*","red","bold"], - ["^==[0-9]+==\s{4}(indirectly lost): .* (in) .*","orange","bold"], - ["^==[0-9]+==\s{6}(possibly lost): .* (in) .*","yellow","bold"], - ["^==[0-9]+==\s{4}(still reachable): .* (in) .*","green","bold"], - ["^==[0-9]+==\s{9}(suppressed): .* (in) .*","cyan","bold"], + [r"^==[0-9]+==\s{4}(definitely lost): .* (in) .*","red","bold"], + [r"^==[0-9]+==\s{4}(indirectly lost): .* (in) .*","orange","bold"], + [r"^==[0-9]+==\s{6}(possibly lost): .* (in) .*","yellow","bold"], + [r"^==[0-9]+==\s{4}(still reachable): .* (in) .*","green","bold"], + [r"^==[0-9]+==\s{9}(suppressed): .* (in) .*","cyan","bold"], ] diff --git a/colout/colout_vivado.py b/colout/colout_vivado.py index 1e5d8a0..aa74216 100644 --- a/colout/colout_vivado.py +++ b/colout/colout_vivado.py @@ -2,16 +2,16 @@ def theme(context): # Theme for coloring AMD/Xilinx Vivado IDE synthesis and implementation output return context,[ - [ "^\s*\*+.+$", "green" ], + [ r"^\s*\*+.+$", "green" ], [ "^#.+", "green" ], [ "^.+ Checksum: .+$", "green" ], - [ "^.+Time \(s\).+", "green" ], - [ "^Time \(s\).+", "green" ], + [ r"^.+Time \(s\).+", "green" ], + [ r"^Time \(s\).+", "green" ], - [ "Estimated Timing Summary \|.+\|.+\|", "cyan", "bold" ], - [ "Intermediate Timing Summary \|.+\|.+\|", "cyan", "bold" ], + [ r"Estimated Timing Summary \|.+\|.+\|", "cyan", "bold" ], + [ r"Intermediate Timing Summary \|.+\|.+\|", "cyan", "bold" ], [ "^INFO:", "white", "bold" ], [ "^WARNING:.+$", "yellow" ],