commit
add176306a
1 changed files with 56 additions and 57 deletions
113
colout.py
113
colout.py
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
#encoding: utf-8
|
#encoding: utf-8
|
||||||
|
|
||||||
# Color Up Arbitrary Command Ouput
|
# Color Up Arbitrary Command Ouput
|
||||||
# Licensed under the GPL version 3
|
# Licensed under the GPL version 3
|
||||||
# 2012 (c) nojhan <nojhan@nojhan.net>
|
# 2012 (c) nojhan <nojhan@nojhan.net>
|
||||||
|
|
||||||
|
|
@ -14,23 +14,23 @@ import random
|
||||||
|
|
||||||
# Available styles
|
# Available styles
|
||||||
styles = {
|
styles = {
|
||||||
"normal":0, "bold":1, "faint":2, "italic":3, "underline":4,
|
"normal": 0, "bold": 1, "faint": 2, "italic": 3, "underline": 4,
|
||||||
"blink":5, "rapid_blink":6,
|
"blink": 5, "rapid_blink": 6,
|
||||||
"reverse":7, "conceal":8
|
"reverse": 7, "conceal": 8
|
||||||
}
|
}
|
||||||
|
|
||||||
# Available color names in 8-colors mode
|
# Available color names in 8-colors mode
|
||||||
colors = {
|
colors = {
|
||||||
"black":0, "red":1, "green":2, "yellow":3, "blue":4,
|
"black": 0, "red": 1, "green": 2, "yellow": 3, "blue": 4,
|
||||||
"magenta":5, "cyan":6, "white":7
|
"magenta": 5, "cyan": 6, "white": 7
|
||||||
}
|
}
|
||||||
|
|
||||||
rainbow = [ "red", "yellow", "green", "cyan", "blue", "magenta" ]
|
rainbow = ["red", "yellow", "green", "cyan", "blue", "magenta"]
|
||||||
colormap = rainbow # default colormap to rainbow
|
colormap = rainbow # default colormap to rainbow
|
||||||
colormap_idx = 0
|
colormap_idx = 0
|
||||||
|
|
||||||
# Escaped end markers for given color modes
|
# Escaped end markers for given color modes
|
||||||
endmarks = {8:";", 256:";38;5;"}
|
endmarks = {8: ";", 256: ";38;5;"}
|
||||||
|
|
||||||
# load available themes
|
# load available themes
|
||||||
themes = {}
|
themes = {}
|
||||||
|
|
@ -52,10 +52,10 @@ except ImportError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
for lexer in get_all_lexers():
|
for lexer in get_all_lexers():
|
||||||
lexers.append( lexer[1][0] )
|
lexers.append(lexer[1][0])
|
||||||
|
|
||||||
|
|
||||||
def colorin( text, color = "red", style = "normal" ):
|
def colorin(text, color="red", style="normal"):
|
||||||
"""
|
"""
|
||||||
Return the given text, surrounded by the given color ASCII markers.
|
Return the given text, surrounded by the given color ASCII markers.
|
||||||
|
|
||||||
|
|
@ -79,24 +79,24 @@ def colorin( text, color = "red", style = "normal" ):
|
||||||
if style == "random" or style == "Random":
|
if style == "random" or style == "Random":
|
||||||
style = random.choice(list(styles.keys()))
|
style = random.choice(list(styles.keys()))
|
||||||
else:
|
else:
|
||||||
assert( style in styles)
|
assert(style in styles)
|
||||||
|
|
||||||
style_code = str(styles[style])
|
style_code = str(styles[style])
|
||||||
|
|
||||||
if color == "random":
|
if color == "random":
|
||||||
mode = 8
|
mode = 8
|
||||||
color_code = random.choice(list(colors.values()))
|
color_code = random.choice(list(colors.values()))
|
||||||
color_code = str( 30 + color_code )
|
color_code = str(30 + color_code)
|
||||||
|
|
||||||
elif color == "Random":
|
elif color == "Random":
|
||||||
mode = 256
|
mode = 256
|
||||||
color_nb = random.randint(0,255)
|
color_nb = random.randint(0, 255)
|
||||||
color_code = str( color_nb )
|
color_code = str(color_nb)
|
||||||
|
|
||||||
elif color == "rainbow":
|
elif color == "rainbow":
|
||||||
mode = 8
|
mode = 8
|
||||||
color = colormap[colormap_idx]
|
color = colormap[colormap_idx]
|
||||||
color_code = str( 30 + colors[color] )
|
color_code = str(30 + colors[color])
|
||||||
|
|
||||||
if colormap_idx < len(colormap)-1:
|
if colormap_idx < len(colormap)-1:
|
||||||
colormap_idx += 1
|
colormap_idx += 1
|
||||||
|
|
@ -107,12 +107,12 @@ def colorin( text, color = "red", style = "normal" ):
|
||||||
color = colormap[colormap_idx]
|
color = colormap[colormap_idx]
|
||||||
if color in colors:
|
if color in colors:
|
||||||
mode = 8
|
mode = 8
|
||||||
color_code = str( 30 + colors[color] )
|
color_code = str(30 + colors[color])
|
||||||
else:
|
else:
|
||||||
mode = 256
|
mode = 256
|
||||||
color_nb = int( color )
|
color_nb = int(color)
|
||||||
assert( 0 <= color_nb <= 255 )
|
assert(0 <= color_nb <= 255)
|
||||||
color_code = str( color_nb )
|
color_code = str(color_nb)
|
||||||
|
|
||||||
if colormap_idx < len(colormap)-1:
|
if colormap_idx < len(colormap)-1:
|
||||||
colormap_idx += 1
|
colormap_idx += 1
|
||||||
|
|
@ -122,19 +122,19 @@ def colorin( text, color = "red", style = "normal" ):
|
||||||
# 8 colors modes
|
# 8 colors modes
|
||||||
elif color in colors:
|
elif color in colors:
|
||||||
mode = 8
|
mode = 8
|
||||||
color_code = str( 30 + colors[color] )
|
color_code = str(30 + colors[color])
|
||||||
|
|
||||||
# 256 colors mode
|
# 256 colors mode
|
||||||
else:
|
else:
|
||||||
mode = 256
|
mode = 256
|
||||||
color_nb = int( color )
|
color_nb = int(color)
|
||||||
assert( 0 <= color_nb <= 255 )
|
assert(0 <= color_nb <= 255)
|
||||||
color_code = str( color_nb )
|
color_code = str(color_nb)
|
||||||
|
|
||||||
return start + style_code + endmarks[mode] + color_code + "m" + text + stop
|
return start + style_code + endmarks[mode] + color_code + "m" + text + stop
|
||||||
|
|
||||||
|
|
||||||
def colorout( text, match, prev_end, color = "red", style = "normal", group=0 ):
|
def colorout(text, match, prev_end, color="red", style="normal", group=0):
|
||||||
"""
|
"""
|
||||||
Build the text from the previous re.match to the current one,
|
Build the text from the previous re.match to the current one,
|
||||||
coloring up the matching characters.
|
coloring up the matching characters.
|
||||||
|
|
@ -143,11 +143,11 @@ def colorout( text, match, prev_end, color = "red", style = "normal", group=0 ):
|
||||||
colored_text = text[prev_end:start]
|
colored_text = text[prev_end:start]
|
||||||
end = match.end(group)
|
end = match.end(group)
|
||||||
|
|
||||||
colored_text += colorin(text[start:end], color, style )
|
colored_text += colorin(text[start:end], color, style)
|
||||||
return colored_text,end
|
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.
|
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.
|
||||||
|
|
@ -171,7 +171,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'
|
'\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 colormap_idx
|
||||||
regex = re.compile(pattern)#, re.IGNORECASE)
|
regex = re.compile(pattern) # , re.IGNORECASE)
|
||||||
|
|
||||||
# Prepare the colored text.
|
# Prepare the colored text.
|
||||||
colored_text = ""
|
colored_text = ""
|
||||||
|
|
@ -181,7 +181,7 @@ def colorup( text, pattern, color = "red", style = "normal", on_groups=False):
|
||||||
# If no groups are specified
|
# If no groups are specified
|
||||||
if not match.groups():
|
if not match.groups():
|
||||||
# Color the previous partial line,
|
# Color the previous partial line,
|
||||||
partial,end = colorout( text, match, end, color, style )
|
partial, end = colorout(text, match, end, color, style)
|
||||||
# add it to the final text.
|
# add it to the final text.
|
||||||
colored_text += partial
|
colored_text += partial
|
||||||
|
|
||||||
|
|
@ -206,8 +206,8 @@ def colorup( text, pattern, color = "red", style = "normal", on_groups=False):
|
||||||
# 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].
|
||||||
# Thus, we need to range in [1,n+1[.
|
# Thus, we need to range in [1,n+1[.
|
||||||
for group in range(1,nb_groups+1):
|
for group in range(1, nb_groups+1):
|
||||||
partial,end = colorout( text, match, end, group_colors[group-1], group_styles[group-1], group )
|
partial, end = colorout(text, match, end, group_colors[group-1], group_styles[group-1], group)
|
||||||
colored_text += partial
|
colored_text += partial
|
||||||
|
|
||||||
# Append the remaining part of the text, if any.
|
# Append the remaining part of the text, if any.
|
||||||
|
|
@ -216,7 +216,7 @@ def colorup( text, pattern, color = "red", style = "normal", on_groups=False):
|
||||||
return colored_text
|
return colored_text
|
||||||
|
|
||||||
|
|
||||||
def colorgen( stream, pattern, color = "red", style = "normal", on_groups=False):
|
def colorgen(stream, 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.
|
||||||
|
|
||||||
|
|
@ -232,14 +232,14 @@ def colorgen( stream, pattern, color = "red", style = "normal", on_groups=False)
|
||||||
break
|
break
|
||||||
if not item:
|
if not item:
|
||||||
break
|
break
|
||||||
yield colorup( item, pattern, color, style, on_groups)
|
yield colorup(item, pattern, color, style, on_groups)
|
||||||
|
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# Command line tools #
|
# Command line tools #
|
||||||
######################
|
######################
|
||||||
|
|
||||||
def __args_dirty__(argv,usage=""):
|
def __args_dirty__(argv, usage=""):
|
||||||
"""
|
"""
|
||||||
Roughly extract options from the command line arguments.
|
Roughly extract options from the command line arguments.
|
||||||
To be used only when argparse is not available.
|
To be used only when argparse is not available.
|
||||||
|
|
@ -256,19 +256,19 @@ def __args_dirty__(argv,usage=""):
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# 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) > 9 \
|
or len(argv) > 9 \
|
||||||
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?>] [<iterate over groups?>]")
|
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")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
assert( len(argv) >= 2 )
|
assert(len(argv) >= 2)
|
||||||
# Get mandatory arguments
|
# Get mandatory arguments
|
||||||
pattern = argv[1]
|
pattern = argv[1]
|
||||||
|
|
||||||
|
|
@ -292,10 +292,10 @@ def __args_dirty__(argv,usage=""):
|
||||||
if len(argv) == 9:
|
if len(argv) == 9:
|
||||||
as_source = bool(argv[8])
|
as_source = bool(argv[8])
|
||||||
|
|
||||||
return pattern,color,style,on_stderr,on_groups,as_colormap,as_theme,as_source
|
return pattern, color, style, on_stderr, on_groups, as_colormap, as_theme, as_source
|
||||||
|
|
||||||
|
|
||||||
def __args_parse__(argv,usage=""):
|
def __args_parse__(argv, usage=""):
|
||||||
"""
|
"""
|
||||||
Parse command line arguments with the argparse library.
|
Parse command line arguments with the argparse library.
|
||||||
Returns a tuple of (pattern,color,style,on_stderr).
|
Returns a tuple of (pattern,color,style,on_stderr).
|
||||||
|
|
@ -309,12 +309,12 @@ def __args_parse__(argv,usage=""):
|
||||||
parser.add_argument("color", metavar="COLOR", type=str, nargs='?',
|
parser.add_argument("color", metavar="COLOR", type=str, nargs='?',
|
||||||
default="red",
|
default="red",
|
||||||
help="A number in [0…255], one of the available colors or a comma-separated list of values. \
|
help="A number in [0…255], one of the available colors or a comma-separated list of values. \
|
||||||
Available colors: "+", ".join(colors) )
|
Available colors: "+", ".join(colors))
|
||||||
|
|
||||||
parser.add_argument("style", metavar="STYLE", type=str, nargs='?',
|
parser.add_argument("style", metavar="STYLE", type=str, nargs='?',
|
||||||
default="bold",
|
default="bold",
|
||||||
help="One of the available styles or a comma-separated list of styles.\
|
help="One of the available styles or a comma-separated list of styles.\
|
||||||
Available styles: "+", ".join(styles) )
|
Available styles: "+", ".join(styles))
|
||||||
|
|
||||||
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")
|
||||||
|
|
@ -340,7 +340,7 @@ def __args_parse__(argv,usage=""):
|
||||||
return args.pattern[0], args.color, args.style, args.stderr, args.groups, args.colormap, args.theme, args.source
|
return args.pattern[0], args.color, args.style, args.stderr, args.groups, args.colormap, args.theme, args.source
|
||||||
|
|
||||||
|
|
||||||
def write( colored, on_stderr=False ):
|
def write(colored, on_stderr=False):
|
||||||
"""
|
"""
|
||||||
If on_stderr, write "colored" on sys.stderr, else write it on sys.stdout.
|
If on_stderr, write "colored" on sys.stderr, else write it on sys.stdout.
|
||||||
Then flush.
|
Then flush.
|
||||||
|
|
@ -356,27 +356,27 @@ def write( colored, on_stderr=False ):
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
usage="A regular expression based formatter that color up an arbitrary text stream."
|
usage = "A regular expression based formatter that color up an arbitrary text stream."
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
# if argparse is not installed
|
# if argparse is not installed
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pattern,color,style,on_stderr,on_groups,as_colormap,as_theme,as_source = __args_dirty__(sys.argv,usage)
|
pattern, color, style, on_stderr, on_groups, as_colormap, as_theme, as_source = __args_dirty__(sys.argv, usage)
|
||||||
|
|
||||||
# if argparse is available
|
# if argparse is available
|
||||||
else:
|
else:
|
||||||
pattern,color,style,on_stderr,on_groups,as_colormap,as_theme,as_source = __args_parse__(sys.argv,usage)
|
pattern, color, style, on_stderr, on_groups, as_colormap, as_theme, as_source = __args_parse__(sys.argv, usage)
|
||||||
|
|
||||||
# use the generator: output lines as they come
|
# use the generator: output lines as they come
|
||||||
if as_colormap == True and color != "rainbow":
|
if as_colormap is True and color != "rainbow":
|
||||||
colormap = color.split(",") # replace the colormap by the given colors
|
colormap = color.split(",") # replace the colormap by the given colors
|
||||||
color = "colormap" # use the keyword to switch to colormap instead of list of colors
|
color = "colormap" # use the keyword to switch to colormap instead of list of colors
|
||||||
|
|
||||||
# if theme
|
# if theme
|
||||||
if as_theme:
|
if as_theme:
|
||||||
assert( pattern in themes.keys() )
|
assert(pattern in themes.keys())
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
item = sys.stdin.readline()
|
item = sys.stdin.readline()
|
||||||
|
|
@ -389,14 +389,14 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
# if pygments
|
# if pygments
|
||||||
elif as_source:
|
elif as_source:
|
||||||
assert( pattern.lower() in lexers )
|
assert(pattern.lower() in lexers)
|
||||||
lexer = get_lexer_by_name(pattern.lower())
|
lexer = get_lexer_by_name(pattern.lower())
|
||||||
# Python => 256 colors, python => 8 colors
|
# Python => 256 colors, python => 8 colors
|
||||||
ask_256 = pattern[0].isupper()
|
ask_256 = pattern[0].isupper()
|
||||||
if ask_256:
|
if ask_256:
|
||||||
try:
|
try:
|
||||||
formatter = Terminal256Formatter(style = color)
|
formatter = Terminal256Formatter(style=color)
|
||||||
except: # style not found
|
except: # style not found
|
||||||
formatter = Terminal256Formatter()
|
formatter = Terminal256Formatter()
|
||||||
else:
|
else:
|
||||||
formatter = TerminalFormatter()
|
formatter = TerminalFormatter()
|
||||||
|
|
@ -408,11 +408,10 @@ if __name__ == "__main__":
|
||||||
break
|
break
|
||||||
if not item:
|
if not item:
|
||||||
break
|
break
|
||||||
colored = highlight( item, lexer, formatter)
|
colored = highlight(item, lexer, formatter)
|
||||||
write(colored)
|
write(colored)
|
||||||
|
|
||||||
# if color
|
# if color
|
||||||
else:
|
else:
|
||||||
for colored in colorgen( sys.stdin, pattern, color, style, on_groups):
|
for colored in colorgen(sys.stdin, pattern, color, style, on_groups):
|
||||||
write(colored)
|
write(colored)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue