diff options
Diffstat (limited to 'scripts/terminal-colors')
-rwxr-xr-x | scripts/terminal-colors | 550 |
1 files changed, 30 insertions, 520 deletions
diff --git a/scripts/terminal-colors b/scripts/terminal-colors index 985cefb..c39164a 100755 --- a/scripts/terminal-colors +++ b/scripts/terminal-colors @@ -1,529 +1,39 @@ -#!/usr/bin/env python +#!/usr/bin/bash +# +# ANSI color scheme script featuring Space Invaders +# +# Original: http://crunchbang.org/forums/viewtopic.php?pid=126921%23p126921#p126921 +# Modified by lolilolicon +# -"""2.2 John Eikenberry <jae@zhar.net> GPL-3+ http://zhar.net/projects/ +f=3 b=4 +for j in f b; do + for i in {0..7}; do + printf -v $j$i %b "\e[${!j}${i}m" + done +done +bld=$'\e[1m' +rst=$'\e[0m' -Copyright - Copyright (C) 2010-2013 John Eikenberry <jae@zhar.net> +cat << EOF -License - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. + $f1 ▀▄ ▄▀ $f2 ▄▄▄████▄▄▄ $f3 ▄██▄ $f4 ▀▄ ▄▀ $f5 ▄▄▄████▄▄▄ $f6 ▄██▄ $rst + $f1 ▄█▀███▀█▄ $f2███▀▀██▀▀███ $f3▄█▀██▀█▄ $f4 ▄█▀███▀█▄ $f5███▀▀██▀▀███ $f6▄█▀██▀█▄$rst + $f1█▀███████▀█ $f2▀▀███▀▀███▀▀ $f3▀█▀██▀█▀ $f4█▀███████▀█ $f5▀▀███▀▀███▀▀ $f6▀█▀██▀█▀$rst + $f1▀ ▀▄▄ ▄▄▀ ▀ $f2 ▀█▄ ▀▀ ▄█▀ $f3▀▄ ▄▀ $f4▀ ▀▄▄ ▄▄▀ ▀ $f5 ▀█▄ ▀▀ ▄█▀ $f6▀▄ ▄▀$rst - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + $bld$f1▄ ▀▄ ▄▀ ▄ $f2 ▄▄▄████▄▄▄ $f3 ▄██▄ $f4▄ ▀▄ ▄▀ ▄ $f5 ▄▄▄████▄▄▄ $f6 ▄██▄ $rst + $bld$f1█▄█▀███▀█▄█ $f2███▀▀██▀▀███ $f3▄█▀██▀█▄ $f4█▄█▀███▀█▄█ $f5███▀▀██▀▀███ $f6▄█▀██▀█▄$rst + $bld$f1▀█████████▀ $f2▀▀▀██▀▀██▀▀▀ $f3▀▀█▀▀█▀▀ $f4▀█████████▀ $f5▀▀▀██▀▀██▀▀▀ $f6▀▀█▀▀█▀▀$rst + $bld$f1 ▄▀ ▀▄ $f2▄▄▀▀ ▀▀ ▀▀▄▄ $f3▄▀▄▀▀▄▀▄ $f4 ▄▀ ▀▄ $f5▄▄▀▀ ▀▀ ▀▀▄▄ $f6▄▀▄▀▀▄▀▄$rst - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -Description - My goal in writing this script was to provide all the functionality of all - the various perl/sh scripts found around the web in one place with some - additional bells and whistles. + $f7▌$rst - It automatically detects 8, 16, 88, 256 color capabilities (via ncurses) - and displays the appropriate color charts. It can display the colors as - blocks or (2d) cubes optionally with color values overlaid in int or hex - values. It can show the full rgb text string as well. It can also show the - display with a vertical (default) or horizontal orientation. It has the - option of additional padding and supports -h --help as well. + $f7▌$rst - It also works as a utility for converting between 256 and 88 color values. - -Development - A note on coding style. I was playing around with using classes as simple - module-esque namespaces; i.e. having classes that have all staticmethods - and never get instatiated. As a side effect of this it makes calls at the - module level thus this script is not really importable, thus limiting - reuse. - -Contributors - Isaac Cammann <icammann@gmail.com> - cube display bugfix - Jan Larres <jan@majutsushi.net> - submitted patches for.. - - compact rgb display - - use of color intensity to determine foreground contrast color - - 16 color SGR ANSI chart - - 88 color rgb display bugfix - -""" -from __future__ import print_function - -__version__ = __doc__.split('\n')[0] - -import sys -import curses -from optparse import OptionParser, OptionGroup, make_option -from math import ceil, sqrt -from functools import wraps - -# output constants -fg_escape = "\x1b[38;5;%dm" -bg_escape = "\x1b[48;5;%dm" -clear = "\x1b[0m" - -def _get_options(args): - """ Setup and parse options. - """ - option_list = [ - make_option("-b", "--block", action="store_true", dest="block", - default=True, help="Display as block format (vs cube) [default]."), - make_option("-c", "--cube-slice", action="store_true", dest="cube", - default=False, help="Display as cube slices (vs block)."), - make_option("-f", "--foreground", action="store_true", - dest="foreground", default=False, - help="Use color for foreground text."), - make_option("-l", "--rgb", action="store_true", dest="rgb", - default=False, help="Long format. RGB values as text."), - make_option("-n", "--numbers", action="store_true", dest="numbers", - default=False, help="Include color escape numbers on chart."), - make_option("-o", "--basiccodes", action="store_true", - dest="basiccodes", default=False, - help="Display 16 color chart with SGR ANSI escape codes."), - make_option("-p", "--padding", action="store_true", dest="padding", - default=False, help="Add extra padding (helps discern colors)."), - make_option("-v", "--vertical", action="store_true", dest="vertical", - default=True, help="Display with vertical orientation [default]."), - make_option("-x", "--hex", action="store_true", dest="hex", - default=False, help="Include hex color numbers on chart."), - make_option("-z", "--horizontal", action="store_true", - dest="horizontal", default=False, - help="Display with horizontal orientation."), - ] - - parser = OptionParser(version=__version__, option_list=option_list) - - convert_option_list = [ - make_option("-r", "--256to88", action="store", dest="reduce", - metavar="N", type="int", - help="Convert (reduce) 256 color value N to an 88 color value."), - make_option("-e", "--88to256", action="store", dest="expand", - metavar="N", type="int", - help="Convert (expand) 88 color value N to an 256 color value."), - ] - group = OptionGroup(parser, "Conversion options") - group.add_options(option_list=convert_option_list) - parser.add_option_group(group) - - (options, args) = parser.parse_args(args) - return options - -# instantiate global options based on command arguments -options = _get_options(sys.argv[1:]) -# don't allow -f by itself -options.foreground = options.foreground and ( - options.numbers or options.hex or options.rgb ) - -class _staticmethods(type): - """ Got tired of adding @staticmethod in front of every method. - """ - def __new__(m, n, b, d): - """ turn all methods in to staticmethods. - staticmethod() deals correctly with class attributes. - """ - for (n, f) in d.items(): - if callable(f): - d[n] = staticmethod(f) - return type.__new__(m, n, b, d) - -def _cached(f): - """ Memoize function w/ no params - """ - _cache = {} - def cache(): - if None not in _cache: - _cache[None] = f() - return _cache[None] - return cache - - -class term16(object): - """ Basic 16 color terminal. - """ - __metaclass__ = _staticmethods - - def label(n, esc): - """ color label for 256 color values - """ - if options.numbers: - return esc(n) + "%3d " % n - elif options.hex: - return esc(n) + " %2x " % n - return esc(n) + " " - - def _render(): - """ 16 color info - """ - if options.foreground: - esc = lambda n: fg_escape % n - else: - esc = lambda n: bg_escape % n + fg_escape % (15 if n < 9 else 0) - return [[term16.label(n, esc) + clear for n in range(8)], - [term16.label(n, esc) + clear for n in range(8,16)]] - - def basiccodes(): - text = " gYw " - esc_code = "\x1b[%sm" - print(' ' * 17 + ' '.join([str(40 + n) + "m" for n in range(8)])) - fg_codes = ['0', '1'] - for i in range(30, 38): - fg_codes.extend([str(i), "1;%d" % i]) - for fg in fg_codes: - print("%5sm " % fg + esc_code % fg + text + clear + ' ', end='') - print(' '.join([esc_code % fg + esc_code % bg + text + clear - for bg in range(40, 48)])) - - def display(): - """ display 16 color info - """ - print("System colors:") - colors = term16._render() - padding=' ' if options.padding else '' - for r in colors: - print(padding.join(i for i in r)) - if options.padding: print() - - -class term256(term16): - """ eg. xterm-256 - """ - - @_cached - def _rgb_lookup(): - """ color rgb lookup dict - """ - # color increment is based on xterm/rxvt palette - cincr = [0] + [95+40*n for n in range(5)] - color_rgb = [rgb(i, j, k) - for i in cincr for j in cincr for k in cincr] - color_rgb = dict(zip(range(16, len(color_rgb)+16), color_rgb)) - greys = [rgb(*((n,)*3)) for n in range(8, 248, 10)] - greys = dict(zip(range(232, 256), greys)) - color_rgb.update(greys) - return color_rgb - - def _to_rgb(n): - """ Convert color value to rgb tuple. - """ - return term256._rgb_lookup()[n] - - def _rgb_color_table(): - """ 256 color info - """ - rgbl = term256._rgb_lookup() - label_num = "% 4d: " - label_val = "%s" - if options.foreground: - render = lambda n: fg_escape % n + label_num % n + \ - label_val % str(rgbl[n]) + clear - else: - render = lambda n: fg_escape % n + label_num % n + \ - fg_escape % (16 if rgbl[n].is_light() else 255) \ - + bg_escape % n + label_val % str(rgbl[n]) + clear - return [[render(n) for n in [i+j for j in range(6)]] - for i in range(16, 256, 6)] - - def _rgb_display(): - """ display colors with rgb hex info - """ - colors = term256._rgb_color_table() - padding=' ' if options.padding else '' - while colors: - rows, colors = colors[:6], colors[6:] - if not options.horizontal: - rows = zip(*rows) - for r in rows: - print(padding.join(i for i in r)) - if options.padding: print() - print() - - def _colors(): - """ 256 color numbers - """ - return [[i+j for j in range(6)] for i in range(16, 232, 6)] - - def _greyscale(): - """ 256 greyscale numbers - """ - return [[i+j for j in range(12)] for i in range(232, 256, 12)] - - def _render(palette): - """ compact 256 color info - """ - if options.foreground: - esc = lambda n: fg_escape % n - render = lambda n: term256.label(n, esc) + clear - else: - esc = lambda n: fg_escape % \ - (16 if term256._to_rgb(n).is_light() else 255) - render = lambda n: bg_escape % n + term256.label(n, esc) + clear - return [[render(n) for n in i] for i in palette] - - def _compact_display(): - """ display colors in compact format - """ - colors = term256._render(term256._colors()) - if options.cube: - _cube_display(colors) - elif options.block: - _block_display(colors) - print() - greys = term256._render(term256._greyscale()) - padding=' ' if options.padding else '' - for r in greys: - print(padding.join(i for i in r)) - if options.padding: print() - - def display(): - """ display 256 color info (+ 16 in compact format) - """ - if options.rgb: - print("Xterm RGB values for 6x6x6 color cube and greyscale.") - print() - term256._rgb_display() - else: - term16.display() - print() - print("6x6x6 color cube and greyscale:") - term256._compact_display() - - -class term88(term16): - """ xterm-88 or urxvt - """ - - @_cached - def _rgb_lookup(): - """ color rgb lookup dict - """ - # color increment is based on rxvt palette - cincr = [0, 0x8b, 0xcd, 0xff] - color_rgb = [rgb(i, j, k) - for i in cincr for j in cincr for k in cincr] - color_rgb = dict(zip(range(16, len(color_rgb)+16), color_rgb)) - greys = [rgb(*((n,)*3)) - for n in [0x2e, 0x5c, 0x73, 0x8b, 0xa2, 0xb9, 0xd0, 0xe7]] - greys = dict(zip(range(80, 88), greys)) - color_rgb.update(greys) - return color_rgb - - def _to_rgb(n): - """ Convert color value to rgb tuple. - """ - return term88._rgb_lookup()[n] - - def _rgb_color_table(): - """ 88 color info - """ - rgbl = term88._rgb_lookup() - label_num = "% 4d: " - label_val = "%s" - if options.foreground: - render = lambda n: fg_escape % n + label_num % n + \ - label_val % str(rgbl[n]) + clear - else: - render = lambda n: fg_escape % n + label_num % n + \ - fg_escape % (16 if rgbl[n].is_light() else 87) \ - + bg_escape % n + label_val % str(rgbl[n]) + clear - return [[render(n) for n in [i+j for j in range(4)]] - for i in range(16, 88, 4)] - - def _rgb_display(): - """ display colors with rgb hex info - """ - colors = term88._rgb_color_table() - while colors: - rows, colors = colors[:4], colors[4:] - for r in zip(*rows): - print(''.join(i for i in r)) - print() - - def _render(palette): - """ 88 color info - """ - if options.foreground: - esc = lambda n: fg_escape % n - render = lambda n: term88.label(n, esc) + clear - else: - esc = lambda n: fg_escape % \ - (16 if term88._to_rgb(n).is_light() else 87) - render = lambda n: bg_escape % n + term88.label(n, esc) + clear - return [[render(n) for n in i] for i in palette] - #for n in [i+j for j in range(4)]] - #for i in range(16, 80, 4)] - - def _colors(): - """ 88 color numbers - """ - return [[i+j for j in range(4)] for i in range(16, 80, 4)] - - def _greyscale(): - """ 88 greyscale numbers - """ - return [range(80,88)] - - - def display(): - """ display 16 + 88 color info - """ - if options.rgb: - print("Xterm RGB values for 4x4x4 color cube and greyscale.") - print() - term88._rgb_display() - else: - padding = ' ' if options.padding else '' - term16.display() - print() - print("4x4x4 color cube and greyscale:") - colors = term88._render(term88._colors()) - if options.cube: - _cube_display(colors) - elif options.block: - _block_display(colors) - print() - greys = term88._render(term88._greyscale()) - for r in greys: - print(padding.join(i for i in r)) - -class rgb(tuple): - """ An RGB, (red, green, blue) tuple. Takes integers. - """ - def __new__(cls, r, g, b): - """ We want 3 colors. - """ - return super(rgb, cls).__new__(cls, (r,g,b)) - - def __str__(self): - """ Display in compact rgb format. - """ - return "#%02x%02x%02x" % self - - def is_light(self): - """ Is this color light (or dark). - """ - red, green, blue = self[0], self[1], self[2] - intensity = red*0.2126 + green*0.7152 + blue*0.0722 - return intensity > 127 - - -def _cube_display(colors): - """ Display color cube as color aligned flatten cube sides. - """ - padding = ' ' if options.padding else '' - if options.horizontal: - def _horizontal(colors): - size = int(sqrt(len(colors))) - for n in (n*size for n in range(size)): - colors[n:n+size] = zip(*colors[n:n+size]) - while colors: - rows, colors = colors[:size*2], colors[size*2:] - for n in range(size): - print(padding.join(i - for i in rows[n]+tuple(reversed(rows[n+size])))) - if options.padding: print(padding) - if colors: print() - _horizontal(colors) - else: #options.vertical - default - def _vertical(colors): - size = int(sqrt(len(colors))) - top = [colors[n:len(colors):size*2] for n in range(size)] - bottom = [colors[n+size:len(colors):size*2] - for n in reversed(range(size))] - for group in [top, bottom]: - for rows in group: - for r in rows: - print(padding.join(i for i in r), end=' ') - if options.padding: print(padding, end=' ') - if options.padding: print() - print() - _vertical(colors) - -def _block_display(colors): - """ Display color cube as cube sides organized by color #s (default). - """ - padding = ' ' if options.padding else '' - size = int(sqrt(len(colors))) - if not options.horizontal: - for n in (n*size for n in range(size)): - colors[n:n+size] = zip(*colors[n:n+size]) - while colors: - half = size*(size//2) - rows, colors = colors[:half], colors[half:] - for n in range(size): - for r in rows[n:len(rows):size]: - print(padding.join(i for i in r), end=' ') - if options.padding: print(padding, end=' ') - if options.padding: print() - print() - if colors: print() - -def convert88to256(n): - """ 88 (4x4x4) color cube to 256 (6x6x6) color cube values - """ - if n < 16: - return n - elif n > 79: - return 234 + (3 * (n - 80)) - else: - def m(n): - "0->0, 1->1, 2->3, 3->5" - return n and n + n-1 or n - b = n - 16 - x = b % 4 - y = (b // 4) % 4 - z = b // 16 - return 16 + m(x) + (6 * m(y) + 36 * m(z)) - -def convert256to88(n): - """ 256 (6x6x6) color cube to 88 (4x4x4) color cube values - """ - if n < 16: - return n - elif n > 231: - if n < 234: - return 0 - return 80 + ((n - 234) // 3) - else: - def m(n, _ratio=(4./6.)): - if n < 2: - return int(ceil(_ratio*n)) - else: - return int(_ratio*n) - b = n - 16 - x = b % 6 - y = (b // 6) % 6 - z = b // 36 - return 16 + m(x) + (4 * m(y) + 16 * m(z)) - -def _terminal(): - """ detect # of colors supported by terminal and return appropriate - terminal class - """ - curses.setupterm() - num_colors = curses.tigetnum('colors') - if num_colors > 0: - return {16:term16, 88:term88, 256:term256}.get(num_colors, term16) - -def main(): - if options.reduce: - v = convert256to88(options.reduce) - # reconvert back to display reduction in context - print("%s (equivalent to 256 value: %s)" % (v, convert88to256(v))) - elif options.expand: - print(convert88to256(options.expand)) - else: - term = _terminal() - if term is None: - print("Your terminal reports that it has no color support.") - else: - if options.basiccodes: - print("Basic 16 color chart with SGR ANSI escape codes.\n") - term16.basiccodes() - else: - term.display() - -if __name__ == "__main__": - main() + $f7 ▄█▄ $rst + $f7▄█████████▄$rst + $f7▀▀▀▀▀▀▀▀▀▀▀$rst +EOF |