#!/usr/bin/env python3 # Author: Xyne, 2011 from colorsys import rgb_to_hsv, hsv_to_rgb from random import random from re import search from sys import argv, stdin, stderr, exit # Convert RGB values in range [0,1] to hexadecimal color codes (#rrggbb). def rgb_to_hex(r, g, b): r, g, b = map(lambda x: round(x * 0xff), (r, g, b)) return "#%02x%02x%02x" % (r, g, b) # The inverse of rgb_to_hex. def hex_to_rgb(color): if color[0] != '#': color = '#' + color m = search(r'^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$', color) if m: r = m.group(1) g = m.group(2) b = m.group(3) return list(map(lambda x: int(x,16)/255.0, (r,g,b))) else: print("error: \"%s\" is not a hexadecimal color (e.g. \"#513bb8\")" % color, file=stderr) exit(1) # Create a gradient from one hexadecimal color to another in n steps. def gradient(ha, hb, n): if n < 2: return ha else: a = hex_to_rgb(ha) b = hex_to_rgb(hb) nn = n - 1 dr = (b[0] - a[0]) / nn dg = (b[1] - a[1]) / nn db = (b[2] - a[2]) / nn return list(map(lambda x: rgb_to_hex(a[0]+x*dr, a[1]+x*dg, a[2]+x*db), range(n))) # Create a rainbow gradient in n steps. def rainbow_gradient(n): x = random() if n < 2: yield (rgb_to_hex(hsv_to_rgb(x,1,1))) else: dx = 1 / float(n-1) for i in range(n): y = (x + i * dx) % 1 yield (rgb_to_hex(*hsv_to_rgb(y,1,1))) # Add a BBCode color tag to some text. def tag(color, txt): # Do not tag single whitespace characters. if txt in " \t\r\n": return txt else: return "[color=%s]%s[/color]" % (color, txt) # Distribute x items evenly across d groups, e.g. distribute(5,3) -> [2,2,1] def distribute(x, d): n, r = divmod(x, d) l = [n] * d for i in range(r): l[i] += 1 return l # Apply a gradient to some text using tags. def grad_text(grad, text): txt = "" for color, char in zip(grad, text): txt += tag(color, char) return txt ################################################################################ # Main ################################################################################ colors = argv[1:] text = stdin.read() # No colors, nothing to do. if not colors: print(text) else: nc = len(colors) l = len(text) # Only one color if nc == 1: # Special case "rainbow". if colors[0].lower() == 'rainbow': grad = rainbow_gradient(l) print(grad_text(grad, text)) # No gradient, just tag everything. else: print(tag(colors[0], text), end="") else: # Break the text into spans for each gradient. spans = distribute(l, nc-1) t = 0 for i, s in enumerate(spans): txt = text[t:t+s] t += s grad = gradient(colors[i], colors[i+1], s) print(grad_text(grad, txt), end="")