Add the --groups option

For color maps (like "rainbow"), iterate over matching groups in the pattern instead of over patterns.

Fix #4
This commit is contained in:
nojhan 2013-03-04 22:16:59 +01:00
commit da1c2209e7
2 changed files with 35 additions and 16 deletions

View file

@ -40,6 +40,9 @@ When not specified, a *COLOR* defaults to _red_ and a *STYLE* defaults to _bold_
* `-e`, `--stderr`: * `-e`, `--stderr`:
Output on the standard error instead of standard output. Output on the standard error instead of standard output.
* `-g`, `--groups`:
For color maps (like "rainbow"), iterate over matching groups in the pattern instead of over patterns.
## REGULAR EXPRESSIONS ## REGULAR EXPRESSIONS
@ -83,3 +86,7 @@ special characters that would be recognize by your shell.
* 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: * 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` `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+
`L=$(seq 10) ; P=${L//??/(\\w+)\\W+} ; head /var/log/auth.log | ./colout.py -g "^${P}(.*)$" rainbow`

View file

@ -45,6 +45,8 @@ def colorin( text, color = "red", style = "normal" ):
>>> colout.colorin("Faites chier la vache", 41, "normal") >>> colout.colorin("Faites chier la vache", 41, "normal")
'\x1b[0;38;5;41mFaites chier la vache\x1b[0m' '\x1b[0;38;5;41mFaites chier la vache\x1b[0m'
""" """
global rainbow_idx
# Special characters. # Special characters.
start = "\033[" start = "\033["
stop = "\033[0m" stop = "\033[0m"
@ -68,7 +70,6 @@ def colorin( text, color = "red", style = "normal" ):
color_code = str( color_nb ) color_code = str( color_nb )
elif color == "rainbow": elif color == "rainbow":
global rainbow_idx
mode = 8 mode = 8
color = rainbow[rainbow_idx] color = rainbow[rainbow_idx]
color_code = str( 30 + colors[color] ) color_code = str( 30 + colors[color] )
@ -106,7 +107,7 @@ def colorout( text, match, prev_end, color = "red", style = "normal", group=0 ):
return colored_text,end return colored_text,end
def colorup( text, pattern, color = "red", style = "normal" ): def colorup( text, pattern, color = "red", style = "normal", on_groups=False ):
""" """
Color up every characters that match the given regexp patterns. Color up every characters that match the given regexp patterns.
If groups are specified, only color up them and not the whole pattern. If groups are specified, only color up them and not the whole pattern.
@ -129,6 +130,7 @@ def colorup( text, pattern, color = "red", style = "normal" ):
>>> colorup("Faites Chier la Vache", "([A-Z])(\S+)\s", "blue", "bold,italic") >>> 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' '\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
regex = re.compile(pattern)#, re.IGNORECASE) regex = re.compile(pattern)#, re.IGNORECASE)
# Prepare the colored text. # Prepare the colored text.
@ -155,6 +157,11 @@ def colorup( text, pattern, color = "red", style = "normal" ):
styles_l = style.split(",") styles_l = style.split(",")
group_styles = styles_l + [styles_l[-1]] * (nb_groups - len(styles_l)) group_styles = styles_l + [styles_l[-1]] * (nb_groups - len(styles_l))
# 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
# For each group index. # For each group index.
# Note that match.groups returns a tuple (thus being indexed in [0,n[), # Note that match.groups returns a tuple (thus being indexed in [0,n[),
# but that match.start(0) refers to the whole match, the groups being indexed in [1,n]. # but that match.start(0) refers to the whole match, the groups being indexed in [1,n].
@ -169,7 +176,7 @@ def colorup( text, pattern, color = "red", style = "normal" ):
return colored_text return colored_text
def colorgen( items, pattern, color = "red", style = "normal" ): def colorgen( items, pattern, color = "red", style = "normal", on_groups=False ):
""" """
A generator that colors the items given in an iterable input. A generator that colors the items given in an iterable input.
@ -179,7 +186,7 @@ def colorgen( items, pattern, color = "red", style = "normal" ):
'2.7\x1b[0;31m1\x1b[0m828\x1b[0;31m1\x1b[0m82846'] '2.7\x1b[0;31m1\x1b[0m828\x1b[0;31m1\x1b[0m82846']
""" """
for item in items: for item in items:
yield colorup( item, pattern, color, style ) yield colorup( item, pattern, color, style, on_groups )
###################### ######################
@ -205,11 +212,11 @@ def __args_dirty__(argv,usage=""):
# Use a dirty argument picker # Use a dirty argument picker
# Check for bad usage or an help flag # Check for bad usage or an help flag
if len(argv) < 2 \ if len(argv) < 2 \
or len(argv) > 5 \ or len(argv) > 6 \
or argv[1] == "--help" \ or argv[1] == "--help" \
or argv[1] == "-h": or argv[1] == "-h":
print(usage+"\n") print(usage+"\n")
print("Usage:",argv[0],"<pattern> <color(s)> [<style(s)>] [<print on stderr?>]") print("Usage:",argv[0],"<pattern> <color(s)> [<style(s)>] [<print on stderr?>] [<iterate over groups?>]")
print("\tAvailable colors:"," ".join(colors)) print("\tAvailable colors:"," ".join(colors))
print("\tAvailable styles:"," ".join(styles)) print("\tAvailable styles:"," ".join(styles))
print("Example:",argv[0],"'^(def)\s+(\w*).*$' blue,magenta italic,bold < colout.py") print("Example:",argv[0],"'^(def)\s+(\w*).*$' blue,magenta italic,bold < colout.py")
@ -230,8 +237,10 @@ def __args_dirty__(argv,usage=""):
style = argv[3] style = argv[3]
if len(argv) == 5: if len(argv) == 5:
on_stderr = bool(argv[4]) on_stderr = bool(argv[4])
if len(argv) == 6:
on_groups = bool(argv[5])
return pattern,color,style,on_stderr return pattern,color,style,on_stderr,on_groups
def __args_parse__(argv,usage=""): def __args_parse__(argv,usage=""):
@ -258,9 +267,12 @@ def __args_parse__(argv,usage=""):
parser.add_argument("-e", "--stderr", action="store_true", parser.add_argument("-e", "--stderr", action="store_true",
help="Output on the stderr instead of stdout") 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")
args = parser.parse_args() args = parser.parse_args()
return args.pattern[0], args.color, args.style, args.stderr return args.pattern[0], args.color, args.style, args.stderr, args.groups
if __name__ == "__main__": if __name__ == "__main__":
@ -273,14 +285,14 @@ if __name__ == "__main__":
# if argparse is not installed # if argparse is not installed
except ImportError: except ImportError:
pattern,color,style,on_stderr = __args_dirty__(sys.argv,usage) pattern,color,style,on_stderr,on_groups = __args_dirty__(sys.argv,usage)
# if argparse is available # if argparse is available
else: else:
pattern,color,style,on_stderr = __args_parse__(sys.argv,usage) pattern,color,style,on_stderr,on_groups = __args_parse__(sys.argv,usage)
# use the generator: output lines as they come # use the generator: output lines as they come
for colored in colorgen( sys.stdin, pattern, color, style ): for colored in colorgen( sys.stdin, pattern, color, style, on_groups ):
if on_stderr: if on_stderr:
sys.stderr.write(colored) sys.stderr.write(colored)
sys.stderr.flush() sys.stderr.flush()