Refactor colorin
Move conditional branches in subfunctions.
This commit is contained in:
parent
3e0535db25
commit
e291194173
1 changed files with 174 additions and 137 deletions
311
colout/colout.py
311
colout/colout.py
|
|
@ -258,6 +258,166 @@ def load_resources( themes_dir, palettes_dir ):
|
||||||
# Library
|
# 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] + "</"+color+">"
|
||||||
|
|
||||||
|
|
||||||
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.
|
||||||
|
|
@ -293,6 +453,8 @@ def colorin(text, color="red", style="normal"):
|
||||||
style_code = str(styles[style])
|
style_code = str(styles[style])
|
||||||
|
|
||||||
color = color.strip()
|
color = color.strip()
|
||||||
|
m = mode(color)
|
||||||
|
|
||||||
if color == "none":
|
if color == "none":
|
||||||
# if no color, style cannot be applied
|
# if no color, style cannot be applied
|
||||||
if not debug:
|
if not debug:
|
||||||
|
|
@ -300,180 +462,55 @@ def colorin(text, color="red", style="normal"):
|
||||||
else:
|
else:
|
||||||
return "<none>"+text+"</none>"
|
return "<none>"+text+"</none>"
|
||||||
|
|
||||||
|
elif color.lower() == "random":
|
||||||
elif color == "random":
|
color_code = color_random( color )
|
||||||
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 in colormaps.keys():
|
elif color in colormaps.keys():
|
||||||
if color[0].islower(): # lower case first letter
|
color_code = color_in_colormaps( color )
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
elif color.lower() == "scale": # "scale" or "Scale"
|
elif color.lower() == "scale": # "scale" or "Scale"
|
||||||
|
color_code = 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
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
# "hash" or "Hash"; useful to randomly but consistently color strings
|
# "hash" or "Hash"; useful to randomly but consistently color strings
|
||||||
elif color.lower() == "hash":
|
elif color.lower() == "hash":
|
||||||
hasher = hashlib.md5()
|
color_code = color_hash( color, text )
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
# Really useful only when using colout as a library
|
# Really useful only when using colout as a library
|
||||||
# thus you can change the "colormap" variable to your favorite one before calling colorin
|
# thus you can change the "colormap" variable to your favorite one before calling colorin
|
||||||
elif color == "colormap":
|
elif color == "colormap":
|
||||||
color = colormap[colormap_idx]
|
color_code = color_map()
|
||||||
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
|
# 8 colors modes
|
||||||
elif color in colors:
|
elif color in colors:
|
||||||
mode = 8
|
|
||||||
color_code = str(30 + colors[color])
|
color_code = str(30 + colors[color])
|
||||||
|
|
||||||
# hexadecimal color
|
# hexadecimal color
|
||||||
elif color[0] == "#":
|
elif color[0] == "#":
|
||||||
mode = 256
|
|
||||||
color_nb = rgb_to_ansi(*hex_to_rgb(color))
|
color_nb = rgb_to_ansi(*hex_to_rgb(color))
|
||||||
assert(0 <= color_nb <= 255)
|
assert(0 <= color_nb <= 255)
|
||||||
color_code = str(color_nb)
|
color_code = str(color_nb)
|
||||||
|
|
||||||
# 256 colors mode
|
# 256 colors mode
|
||||||
elif color.isdigit():
|
elif color.isdigit():
|
||||||
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)
|
||||||
|
|
||||||
# programming language
|
# programming language
|
||||||
elif color.lower() in lexers:
|
elif color.lower() in lexers:
|
||||||
lexer = get_lexer_by_name(color.lower())
|
# bypass color encoding and return text colored by the lexer
|
||||||
# Python => 256 colors, python => 8 colors
|
return color_lexer(color,style,text)
|
||||||
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] + "</"+color+">"
|
|
||||||
|
|
||||||
# unrecognized
|
# unrecognized
|
||||||
else:
|
else:
|
||||||
raise UnknownColor(color)
|
raise UnknownColor(color)
|
||||||
|
|
||||||
if not debug:
|
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:
|
else:
|
||||||
return start + style_code + endmarks[mode] + color_code + "m<" + str(color) + ">" + text + "</" + str(color) + ">" + stop
|
return start + style_code + endmarks[m] + color_code + "m" \
|
||||||
|
+ "<color name=" + str(color) + " code=" + color_code + " style=" + str(style) + " stylecode=" + style_code + ">" \
|
||||||
|
+ text + "</color>" + 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):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue