Created
October 22, 2017 14:27
-
-
Save jsbueno/6577d5514f43f128af826148605f2a2a to your computer and use it in GitHub Desktop.
Terminal colors and gradients in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import io | |
import sys | |
ANSI_SEQ = "\x1b[{}m" | |
FG_RGB = "38;2;{};{};{}" | |
BG_RGB = "48;2;{};{};{}" | |
RESET="0" | |
FRAMED="51" | |
ATTRS = {key:code for key, code in [line.strip().split() for line in """\ | |
bold 1 | |
faint 2 | |
italic 3 | |
underline 4 | |
blink 5 | |
fast_blink 6 | |
reverse 7 | |
conceal 8 | |
crossed 9 | |
fraktur 20 | |
double_underline 21 | |
framed 51 | |
encircled 52 | |
overlined 54\ | |
""".split("\n")]} | |
def printc(*args, **kw): | |
"""Extends print function to add color printing parameters in compatible terminals. | |
Use the optional bg= or fg= parameters to pass colors for foreground or background | |
respectively. Parameters should be a 3-sequence with RGB numbers from 0 to 255 | |
as string or decimal. | |
Use the optional end_fg and end_bg parameters to create color gradients | |
from the starting color to the ending ones. | |
Other attributes can be accepted as "True" according the keys in ATTRS | |
""" | |
extra_options = {} | |
for argname, value in list(kw.items()): | |
if argname in ATTRS: | |
extra_options[argname] = kw.pop(argname) | |
fg_param = kw.pop("start_fg", kw.pop("fg", None)) | |
bg_param = kw.pop("start_bg", kw.pop("bg", None)) | |
start_fg = fg = tuple(int(comp) for comp in (fg_param if fg_param else (0, 0, 0))) | |
start_bg = bg = tuple(int(comp) for comp in (bg_param if bg_param else (0, 0, 0))) | |
end_fg = tuple(int(comp) for comp in kw.pop("end_fg", fg)) | |
end_bg = tuple(int(comp) for comp in kw.pop("end_bg", bg)) | |
original_file = kw.pop("file", sys.stdout) | |
original_flush = kw.pop("flush", False) | |
original_end = kw.pop("end", None) | |
text_io = io.StringIO() | |
print(*args, **kw, file=text_io, end="") | |
text = text_io.getvalue() | |
if not fg_param and not bg_param or not len(text): | |
return print(*args, **kw) | |
fg_gradient = start_fg != end_fg | |
bg_gradient = start_bg != end_bg | |
text_io = io.StringIO() | |
extra_attrs = ";".join(ATTRS[key] for key in extra_options) | |
if extra_attrs: | |
text_io.write(ANSI_SEQ.format(extra_attrs)) | |
for i, character in enumerate(text): | |
ansi_str = "" | |
if start_fg and (i == 0 or fg_gradient): | |
ansi_str = FG_RGB.format(*fg) | |
if start_bg and (i == 0 or bg_gradient): | |
ansi_str += (";" if ansi_str else "") + BG_RGB.format(*bg) | |
if ansi_str: | |
text_io.write(ANSI_SEQ.format(ansi_str)) | |
text_io.write(character) | |
fg = tuple(int(comp + i * (end_comp - comp) / len(text)) for comp, end_comp in zip(fg, end_fg)) | |
bg = tuple(int(comp + i * (end_comp - comp) / len(text)) for comp, end_comp in zip(bg, end_bg)) | |
text_io.write(ANSI_SEQ.format(RESET)) | |
return print(text_io.getvalue(), end=original_end, flush=original_flush, file=original_file) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This needs a compatible and configured terminal - this includes a terminal with support for 16M colors, which does not come by default eihter on Windows or Mac OS. For Windows use the "terminal" app in the microsoft store, and for Mac OS the "iterm2" program. Anyway, after creating this, I authored the "terminedia" package which features a
print
function with similar capabilities and can take tokens on the formterminidia.print("[color: red][effects: blink] This text in blinking red")