Add the --colormap option to build adhoc colormaps

Use the given list of comma-separated colors as a colormap (cycle the colors at each match).
Support of 256 colors mode colormaps.
This commit is contained in:
nojhan 2013-03-05 21:53:38 +01:00
commit c891bda94a
2 changed files with 55 additions and 20 deletions

View file

@ -28,10 +28,13 @@ rapid_blink, reverse, conceal or random.
`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.
`rainbow` will cycle over a 8 colors rainbow at each matching pattern.
When not specified, a *COLOR* defaults to _red_ and a *STYLE* defaults to _bold_.
`colout` is released under the GNU Public License v3.
## OPTIONS
* `-h`, `--help`:
@ -43,14 +46,17 @@ When not specified, a *COLOR* defaults to _red_ and a *STYLE* defaults to _bold_
* `-g`, `--groups`:
For color maps (like "rainbow"), iterate over matching groups in the pattern instead of over patterns.
* `-c`, `--colormap`:
Use the given list of comma-separated colors as a colormap (cycle the colors at each match).
## REGULAR EXPRESSIONS
A regular expression (or _regex_) is a pattern that describes a set of strings
that matches it.
that matches it.
`colout` understands regex as specifed in the _re_ python module. Given that
`colout` is generally called by the command line, you may have to escape
`colout` is generally called by the command line, you may have to escape
special characters that would be recognize by your shell.
@ -87,6 +93,9 @@ special characters that would be recognize by your shell.
`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`
* Color each word in the head of auth.log with a rainbow color map, starting a new colormap at each new line (the
begining of the command is just bash magic to repeat the string "(\w+
begining of the command is just bash magic to repeat the string "(\\w+)\\W+":
`L=$(seq 10) ; P=${L//??/(\\w+)\\W+} ; head /var/log/auth.log | ./colout.py -g "^${P}(.*)$" rainbow`
* Color each line of a file with a different color among a 256 color gradient from cyan to green:
`head /var/log/auth.log | ./colout.py -c "^.*$" 39,38,37,36,35,34`

View file

@ -26,7 +26,8 @@ colors = {
}
rainbow = [ "red", "yellow", "green", "cyan", "blue", "magenta" ]
rainbow_idx = 0
colormap = rainbow # default colormap to rainbow
colormap_idx = 0
# Escaped end markers for given color modes
endmarks = {8:";", 256:";38;5;"}
@ -45,7 +46,7 @@ def colorin( text, color = "red", style = "normal" ):
>>> colout.colorin("Faites chier la vache", 41, "normal")
'\x1b[0;38;5;41mFaites chier la vache\x1b[0m'
"""
global rainbow_idx
global colormap_idx
# Special characters.
start = "\033["
@ -71,13 +72,29 @@ def colorin( text, color = "red", style = "normal" ):
elif color == "rainbow":
mode = 8
color = rainbow[rainbow_idx]
color = colormap[colormap_idx]
color_code = str( 30 + colors[color] )
if rainbow_idx < len(rainbow)-1:
rainbow_idx += 1
if colormap_idx < len(colormap)-1:
colormap_idx += 1
else:
rainbow_idx = 0
colormap_idx = 0
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
# 8 colors modes
elif color in colors:
@ -107,7 +124,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):
"""
Color up every characters that match the given regexp patterns.
If groups are specified, only color up them and not the whole pattern.
@ -130,7 +147,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 rainbow_idx
global colormap_idx
regex = re.compile(pattern)#, re.IGNORECASE)
# Prepare the colored text.
@ -160,7 +177,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
rainbow_idx = 0
colormap_idx = 0
# For each group index.
# Note that match.groups returns a tuple (thus being indexed in [0,n[),
@ -176,7 +193,7 @@ def colorup( text, pattern, color = "red", style = "normal", on_groups=False ):
return colored_text
def colorgen( items, pattern, color = "red", style = "normal", on_groups=False ):
def colorgen( items, pattern, color = "red", style = "normal", on_groups=False):
"""
A generator that colors the items given in an iterable input.
@ -186,7 +203,7 @@ def colorgen( items, pattern, color = "red", style = "normal", on_groups=False )
'2.7\x1b[0;31m1\x1b[0m828\x1b[0;31m1\x1b[0m82846']
"""
for item in items:
yield colorup( item, pattern, color, style, on_groups )
yield colorup( item, pattern, color, style, on_groups)
######################
@ -239,8 +256,10 @@ def __args_dirty__(argv,usage=""):
on_stderr = bool(argv[4])
if len(argv) == 6:
on_groups = bool(argv[5])
if len(argv) == 7:
as_colormap = bool(argv[6])
return pattern,color,style,on_stderr,on_groups
return pattern,color,style,on_stderr,on_groups,as_colormap
def __args_parse__(argv,usage=""):
@ -268,11 +287,14 @@ def __args_parse__(argv,usage=""):
help="Output on the stderr instead of stdout")
parser.add_argument("-g", "--groups", action="store_true",
help="For color maps (random, rainbows), iterate over matching groups in the pattern instead of over patterns")
help="For color maps (random, rainbow), iterate over matching groups 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)")
args = parser.parse_args()
return args.pattern[0], args.color, args.style, args.stderr, args.groups
return args.pattern[0], args.color, args.style, args.stderr, args.groups, args.colormap
if __name__ == "__main__":
@ -285,14 +307,18 @@ if __name__ == "__main__":
# if argparse is not installed
except ImportError:
pattern,color,style,on_stderr,on_groups = __args_dirty__(sys.argv,usage)
pattern,color,style,on_stderr,on_groups,as_colormap = __args_dirty__(sys.argv,usage)
# if argparse is available
else:
pattern,color,style,on_stderr,on_groups = __args_parse__(sys.argv,usage)
pattern,color,style,on_stderr,on_groups,as_colormap = __args_parse__(sys.argv,usage)
# use the generator: output lines as they come
for colored in colorgen( sys.stdin, pattern, color, style, on_groups ):
if as_colormap == True and color != "rainbow":
colormap = color.split(",") # replace the colormap by the given colors
color = "colormap" # use the keyword to switch to colormap instead of list of colors
for colored in colorgen( sys.stdin, pattern, color, style, on_groups):
if on_stderr:
sys.stderr.write(colored)
sys.stderr.flush()