diff --git a/.gitignore b/.gitignore index 12b43b0..a464544 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ lolcat.o censor.o +lolcat +censor diff --git a/Makefile b/Makefile index 1be84e5..c751508 100644 --- a/Makefile +++ b/Makefile @@ -1,25 +1,29 @@ CC ?= gcc -LOLCAT_SRC ?= lolcat.c -CENSOR_SRC ?= censor.c -CFLAGS ?= -std=c11 -Wall -Wextra -g +CFLAGS ?= -std=c11 -Wall -Wextra -O3 -Wno-sign-compare +LIBS := -lm -DESTDIR ?= /usr/local/bin +PREFIX ?= /usr/local all: lolcat censor -.PHONY: install clean +debug: CFLAGS += -g +debug: all -lolcat: $(LOLCAT_SRC) - $(CC) $(CFLAGS) -o $@ $^ +.PHONY: install clean debug -censor: $(CENSOR_SRC) - $(CC) $(CFLAGS) -o $@ $^ +xterm256lut.h: xterm256lut_gen.py + python $< > $@ + +lolcat: lolcat.c xterm256lut.h + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) + +censor: censor.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) install: lolcat censor - install lolcat $(DESTDIR)/lolcat - install censor $(DESTDIR)/censor + install lolcat $(DESTDIR)$(PREFIX)/bin/lolcat + install censor $(DESTDIR)$(PREFIX)/bin/censor clean: rm -f lolcat censor - diff --git a/PKGBUILD b/PKGBUILD index 6b7ef0c..baec990 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Ricardo (XenGi) Band pkgname=c-lolcat -pkgver=r26.502d379 +pkgver=v1.5 pkgrel=1 pkgdesc="High-performance implementation of lolcat" arch=('i686' 'x86_64') diff --git a/README.md b/README.md index a4e9560..602a390 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # What? -![](https://raw.githubusercontent.com/jaseg/lolcat/master/LOLCat-Rainbow.jpg) +![](./LOLCat-Rainbow.jpg) ## Screenshot -![](https://raw.githubusercontent.com/jaseg/lolcat/master/screenshot.png) +![](./screenshot.png) ![](./sl.gif) @@ -15,7 +15,15 @@ There's an [AUR package](https://aur.archlinux.org/packages/c-lolcat): ```bash -$ yaourt -S c-lolcat +$ git clone https://aur.archlinux.org/packages/c-lolcat +$ cd c-lolcat +$ makepkg -csi +``` + +### Fedora ### + +```bash +$ dnf install lolcat ``` ### Ubuntu (Snap) @@ -36,6 +44,8 @@ $ make lolcat ### Others +Note: Debian users may need the `python-is-python3` package. + ```bash $ make && sudo make install ``` diff --git a/autotools/Makefile.am b/autotools/Makefile.am new file mode 100644 index 0000000..002d475 --- /dev/null +++ b/autotools/Makefile.am @@ -0,0 +1,7 @@ +bin_PROGRAMS = lolcat censor +lolcat_SOURCES = ../lolcat.c +censor_SOURCES = ../censor.c + +LIBS += -lm +CFLAGS ?= -O3 +AM_CFLAGS = -std=c11 -Wall -Wextra -Wno-sign-compare -Werror=implicit diff --git a/autotools/README b/autotools/README new file mode 100644 index 0000000..7845e4e --- /dev/null +++ b/autotools/README @@ -0,0 +1,7 @@ +This directory contains an autotools config for building lolcat for those who need it. This is an alternative to the +Makefile provided in the git root. Run it like so: + +cd autotools # go here +./autogen.sh +./configure +make diff --git a/autotools/autogen.sh b/autotools/autogen.sh new file mode 100755 index 0000000..1f3109d --- /dev/null +++ b/autotools/autogen.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +auxdir=autoscripts + +set -x + +# aclocal generated files +rm -rf aclocal.m4 autom4te.cache + +# autoheader generated files +rm -f config.h.in + +# autoconf generated files +rm -f configure + +# automake generated files +rm -f ${auxdir}/{config.guess,config.sub,depcomp,install-sh,missing} +rm -f Makefile.in + +# configure generated files +rm -f config.h config.log config.status Makefile Makefile.in stamp-h1 + +rm -f $(find ${auxdir} -type l 2>/dev/null) +rmdir ${auxdir} 2>/dev/null + +if [[ "$1" == clean ]]; then + exit 0 +fi + +mkdir ${auxdir} 2>/dev/null + +aclocal +autoheader +autoconf +automake --add-missing + diff --git a/autotools/configure.ac b/autotools/configure.ac new file mode 100644 index 0000000..28f5d08 --- /dev/null +++ b/autotools/configure.ac @@ -0,0 +1,35 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.69]) +AC_INIT([lolcat], [1.5], [jaseg ]) +AC_CONFIG_SRCDIR([../lolcat.c]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_AUX_DIR([autoscripts]) +AC_CANONICAL_TARGET +AC_CANONICAL_HOST + +# Automake +AM_INIT_AUTOMAKE([foreign subdir-objects]) + +# Checks for programs. +AC_PROG_CC +AC_PROG_INSTALL + +# Checks for libraries. +AC_CHECK_LIB([m], [cos]) + +# Checks for header files. +AC_CHECK_HEADERS([locale.h stdint.h stdlib.h string.h sys/time.h unistd.h wchar.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_SIZE_T +AC_CHECK_HEADER_STDBOOL +AC_TYPE_UINT8_T + +# Checks for library functions. +AC_FUNC_STRTOD +AC_CHECK_FUNCS([gettimeofday setlocale strchr strerror strstr wcwidth]) + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/censor.c b/censor.c index 64e936b..39b25a4 100644 --- a/censor.c +++ b/censor.c @@ -27,10 +27,10 @@ int main(int argc, char** argv) { + char* foo[] = { "-" }; char** inputs = argv + 1; char** inputs_end = argv + argc; if (inputs == inputs_end) { - char* foo[] = { "-" }; inputs = foo; inputs_end = inputs + 1; } diff --git a/do_release.sh b/do_release.sh new file mode 100755 index 0000000..4d437e8 --- /dev/null +++ b/do_release.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +set -e + +if [ $# -lt 1 ]; then + echo "do_release.sh must be called with a version number as its first argument." + exit 1 +fi + +if [ -n "$(git status --porcelain|grep -v '^??')" ]; then + echo "do_release.sh must be called from a clean working directory." + exit 2 +fi + +VER="$1" + +if echo "$VER" | grep -v '^[0-9]\+\.[0-9]\+$'; then + echo "do_release.sh must be called with a version number formatted like "1.23" as its first argument, with no leading \"v\"." + exit 1 +fi + +echo "Updating files for version v$VER" + +sed -i "/L\"lolcat version [0-9.]\+, (c) [0-9]\+ jaseg\\\\n\"/s/version [0-9.]\+/version $VER/" lolcat.c +sed -i "s/^pkgver=v[0-9.]\+/pkgver=v$VER/" PKGBUILD +sed -i "/^AC_INIT/s/\[[0-9.]\+\]/[$VER]/" autotools/configure.ac +git add lolcat.c PKGBUILD autotools/configure.ac +git commit -m 'Bump version to v$VER' +git tag "v$VER" +echo "Success." + diff --git a/lolcat.c b/lolcat.c old mode 100644 new mode 100755 index b141d4b..011f5dc --- a/lolcat.c +++ b/lolcat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 jaseg +/* Copyright (C) 2020 jaseg * * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE * Version 2, December 2004 @@ -24,8 +24,12 @@ #include #include #include +#include #include +#include #include +#include +#include "math.h" static char helpstr[] = "\n" "Usage: lolcat [-h horizontal_speed] [-v vertical_speed] [--] [FILES...]\n" @@ -33,46 +37,150 @@ static char helpstr[] = "\n" "Concatenate FILE(s), or standard input, to standard output.\n" "With no FILE, or when FILE is -, read standard input.\n" "\n" - " -h : Horizontal rainbow frequency (default: 0.23)\n" - " -v : Vertical rainbow frequency (default: 0.1)\n" - " -f: Force color even when stdout is not a tty\n" - " -l: Use encoding from system locale instead of assuming UTF-8\n" - " --version: Print version and exit\n" - " --help: Show this message\n" + "--horizontal-frequency , -h : Horizontal rainbow frequency (default: 0.23)\n" + " --vertical-frequency , -v : Vertical rainbow frequency (default: 0.1)\n" + " --force-color, -f: Force color even when stdout is not a tty\n" + " --no-force-locale, -l: Use encoding from system locale instead of\n" + " assuming UTF-8\n" + " --random, -r: Random colors\n" + " --seed , -s : Random colors based on given seed,\n" + " implies --random\n" + " --color_offset , -o : Start with a different color\n" + " --gradient , -g : Use color gradient from given start to end color,\n" + " format: -g ff4444:00ffff\n" + " --24bit, -b: Output in 24-bit \"true\" RGB mode (slower and\n" + " not supported by all terminals)\n" + " --16color, -x: Output in 16-color mode for basic terminals\n" + " --invert, -i: Invert foreground and background\n" + " --version: Print version and exit\n" + " --help: Show this message\n" "\n" "Examples:\n" " lolcat f - g Output f's contents, then stdin, then g's contents.\n" " lolcat Copy standard input to standard output.\n" " fortune | lolcat Display a rainbow cookie.\n" "\n" - "Report lolcat bugs to \n" - "lolcat home page: \n" - "Original idea: \n"; + "Report lolcat bugs to \n" + "lolcat home page: \n" + "Original idea: \n"; #define ARRAY_SIZE(foo) (sizeof(foo) / sizeof(foo[0])) const unsigned char codes[] = { 39, 38, 44, 43, 49, 48, 84, 83, 119, 118, 154, 148, 184, 178, 214, 208, 209, 203, 204, 198, 199, 163, 164, 128, 129, 93, 99, 63, 69, 33 }; +const unsigned char codes16[] = {31, 33, 32, 36, 34, 35, 95, 94, 96, 92, 93, 91}; +unsigned int codes_gradient[128]; -static void find_escape_sequences(wint_t c, int* state) +union rgb_c { + struct { + unsigned char b; + unsigned char g; + unsigned char r; + }; + unsigned int i; +}; + +#include "xterm256lut.h" + +int xterm256lookup(union rgb_c *in) { + size_t min_i; + int min_v = INT_MAX; + for (size_t i=0; ir - xterm256lut[i].r; + int dg = in->g - xterm256lut[i].g; + int db = in->b - xterm256lut[i].b; + int d = dr*dr + dg*dg + db*db; + if (d < min_v) { + min_v = d; + min_i = i; + } + } + return 16 + min_i; +} + +void rgb_interpolate(union rgb_c *start, union rgb_c *end, union rgb_c *out, double f) { + out->r = start->r + (end->r - start->r)*f; + out->g = start->g + (end->g - start->g)*f; + out->b = start->b + (end->b - start->b)*f; +} + +enum esc_st { + ST_NONE=0, + ST_ESC_BEGIN, + ST_ESC_STRING, + ST_ESC_CSI, + ST_ESC_STRING_TERM, + ST_ESC_CSI_TERM, + ST_ESC_TERM, + NUM_ST +}; + +const char * esc_st_names[NUM_ST] = { + [ST_NONE] = "NONE", + [ST_ESC_BEGIN] = "BEGIN", + [ST_ESC_STRING] = "STRING", + [ST_ESC_CSI] = "CSI", + [ST_ESC_STRING_TERM] = "STRING_TERM", + [ST_ESC_CSI_TERM] = "CSI_TERM", + [ST_ESC_TERM] = "TERM", +}; + +static enum esc_st find_escape_sequences(wint_t c, enum esc_st st) { - if (c == '\033') { /* Escape sequence YAY */ - *state = 1; - } else if (*state == 1) { - if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) - *state = 2; + + if (st == ST_NONE || st == ST_ESC_CSI_TERM) { + if (c == '\033') { /* Escape sequence YAY */ + return ST_ESC_BEGIN; + } else { + return ST_NONE; + } + + } else if (st == ST_ESC_BEGIN) { + if (c == '[') { + return ST_ESC_CSI; + } else if (c == 'P' || c == ']' || c == 'X' || c == '^' || c == '_') { + return ST_ESC_STRING; + } else { + return ST_ESC_TERM; + } + + } else if (st == ST_ESC_CSI) { + if (0x40 <= c && c <= 0x7e) { + return ST_ESC_CSI_TERM; + } else { + return st; + } + + } else if (st == ST_ESC_STRING) { + if (c == '\007') { + return ST_NONE; + } else if (c == '\033') { + return ST_ESC_STRING_TERM; + } else { + return st; + } + + } else if (st == ST_ESC_STRING_TERM) { + if (c == '\\') { + return ST_NONE; + } else { + return ST_ESC_STRING; + } + } else { - *state = 0; + return ST_NONE; } } static void usage(void) { wprintf(L"Usage: lolcat [-h horizontal_speed] [-v vertical_speed] [--] [FILES...]\n"); - exit(1); + wprintf(L"\n"); + wprintf(L"Use lolcat --help to print the full help text.\n"); + exit(2); } static void version(void) { - wprintf(L"lolcat version 0.1, (c) 2014 jaseg\n"); + wprintf(L"lolcat version 1.5, (c) 2024 jaseg\n"); exit(0); } @@ -94,6 +202,14 @@ int main(int argc, char** argv) wint_t c; int colors = isatty(STDOUT_FILENO); int force_locale = 1; + int random = 0; + unsigned int seed = time(NULL); + int start_color = 0; + int rgb = 0; + int ansi16 = 0; + int invert = 0; + int gradient = 0; + union rgb_c rgb_start, rgb_end; double freq_h = 0.23, freq_v = 0.1; struct timeval tv; @@ -102,7 +218,7 @@ int main(int argc, char** argv) for (i = 1; i < argc; i++) { char* endptr; - if (!strcmp(argv[i], "-h")) { + if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--horizontal-frequency")) { if ((++i) < argc) { freq_h = strtod(argv[i], &endptr); if (*endptr) @@ -110,7 +226,7 @@ int main(int argc, char** argv) } else { usage(); } - } else if (!strcmp(argv[i], "-v")) { + } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--vertical-frequency")) { if ((++i) < argc) { freq_v = strtod(argv[i], &endptr); if (*endptr) @@ -118,10 +234,59 @@ int main(int argc, char** argv) } else { usage(); } - } else if (!strcmp(argv[i], "-f")) { + } else if (!strcmp(argv[i], "-f") || !strcmp(argv[i], "--force-color")) { colors = 1; - } else if (!strcmp(argv[i], "-l")) { + } else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--no-force-locale")) { force_locale = 0; + } else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--random")) { + random = 1; + } else if (!strcmp(argv[i], "-S") || !strcmp(argv[i], "--seed")) { + random = 1; + if ((++i) < argc) { + seed = strtoul(argv[i], &endptr, 10); + if (*endptr) + usage(); + } else { + usage(); + } + } else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--color_offset")) { + if ((++i) < argc) { + start_color = strtod(argv[i], &endptr); + if (*endptr) + usage(); + } else { + usage(); + } + } else if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--24bit")) { + rgb = 1; + } else if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--16color")) { + ansi16 = 1; + } else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--invert")) { + invert = 1; + } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--gradient")) { + if ((++i) >= argc) { + usage(); + } + + if (strlen(argv[i]) != 6+1+6 || argv[i][6] != ':') { + wprintf(L"Invalid format for --gradient\n"); + usage(); + } + + argv[i][6] = '\0'; + rgb_start.i = strtoul(argv[i], &endptr, 16); + if (*endptr) { + wprintf(L"Invalid format for --gradient\n"); + usage(); + } + + rgb_end.i = strtoul(argv[i]+6+1, &endptr, 16); + if (*endptr) { + wprintf(L"Invalid format for --gradient\n"); + usage(); + } + + gradient = 1; } else if (!strcmp(argv[i], "--version")) { version(); } else { @@ -131,6 +296,44 @@ int main(int argc, char** argv) } } + if (rgb && ansi16) { + wprintf(L"Only one of --24bit and --16color can be given at a time\n"); + usage(); + } + + if (gradient) { + if (ansi16) { + wprintf(L"--gradient and --16color are mutually exclusive\n"); + usage(); + } + + if (!rgb) { + double correction_factor =(2*ARRAY_SIZE(codes_gradient)) / (double)ARRAY_SIZE(codes); + freq_h *= correction_factor; + freq_v *= correction_factor; + for (size_t i=0; i 32 ? c : '.', esc_st_names[escape_state]); +#endif + + if (escape_state == ST_ESC_CSI_TERM) { + putwchar(c); + } + + if (escape_state == ST_NONE || escape_state == ST_ESC_CSI_TERM) { if (c == '\n') { l++; i = 0; + cc = -1; + if (invert) { + wprintf(L"\033[49m"); + } else { + wprintf(L"\033[0m"); + } + } else { - int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); - if (cc != ncc) - wprintf(L"\033[38;5;%hhum", codes[(cc = ncc) % ARRAY_SIZE(codes)]); + if (escape_state == ST_NONE) { + i += wcwidth(c); + } + + if (rgb) { + float theta = i * freq_h / 5.0f + l * freq_v + (offx + 2.0f * (rand_offset + start_color) / RAND_MAX)*M_PI; + + union rgb_c c; + if (gradient) { + theta = fmodf(theta/2.0/M_PI, 2.0f); + if (theta > 1.0f) { + theta = 2.0f - theta; + } + rgb_interpolate(&rgb_start, &rgb_end, &c, theta); + } else { + float offset = 0.1; + c.r = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 0 ))) * 255.0f); + c.g = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 2 * M_PI / 3 ))) * 255.0f); + c.b = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 4 * M_PI / 3 ))) * 255.0f); + } + wprintf(L"\033[%d;2;%d;%d;%dm", (invert ? 48 : 38), c.r, c.g, c.b); + + } else if (ansi16) { + int ncc = offx * ARRAY_SIZE(codes16) + (int)(i * freq_h + l * freq_v); + if (cc != ncc || escape_state == ST_ESC_CSI_TERM) { + wprintf(L"\033[%hhum", (invert ? 10 : 0) + codes16[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes16)]); + } + + } else { + if (gradient) { + int ncc = offx * ARRAY_SIZE(codes_gradient) + (int)(i * freq_h + l * freq_v); + if (cc != ncc || escape_state == ST_ESC_CSI_TERM) { + size_t lookup = (rand_offset + start_color + (cc = ncc)) % (2*ARRAY_SIZE(codes_gradient)); + if (lookup >= ARRAY_SIZE(codes_gradient)) { + lookup = 2*ARRAY_SIZE(codes_gradient) - 1 - lookup; + } + wprintf(L"\033[%d;5;%hhum", (invert ? 48 : 38), codes_gradient[lookup]); + } + + } else { + int ncc = offx * ARRAY_SIZE(codes) + (int)(i * freq_h + l * freq_v); + if (cc != ncc || escape_state == ST_ESC_CSI_TERM) { + wprintf(L"\033[%d;5;%hhum", (invert ? 48 : 38), codes[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes)]); + } + } + } } } } - putwchar(c); - - if (escape_state == 2) - wprintf(L"\033[38;5;%hhum", codes[cc % ARRAY_SIZE(codes)]); + if (escape_state != ST_ESC_CSI_TERM) { + putwchar(c); + } } - if (colors) - wprintf(L"\n\033[0m"); + if (colors) { + wprintf(L"\033[0m"); + } cc = -1; if (f) { - fclose(f); - if (ferror(f)) { fwprintf(stderr, L"Error reading input file \"%s\": %s\n", *filename, strerror(errno)); + fclose(f); + return 2; + } + + if (fclose(f)) { + fwprintf(stderr, L"Error closing input file \"%s\": %s\n", *filename, strerror(errno)); return 2; } } diff --git a/xterm256lut.h b/xterm256lut.h new file mode 100644 index 0000000..ea8c515 --- /dev/null +++ b/xterm256lut.h @@ -0,0 +1,243 @@ +/* GENERATED HEADER FILE DO NOT EDIT */ +union rgb_c xterm256lut[256-16] = { + {{0x00, 0x00, 0x00}}, + {{0x5f, 0x00, 0x00}}, + {{0x87, 0x00, 0x00}}, + {{0xaf, 0x00, 0x00}}, + {{0xd7, 0x00, 0x00}}, + {{0xff, 0x00, 0x00}}, + {{0x00, 0x5f, 0x00}}, + {{0x5f, 0x5f, 0x00}}, + {{0x87, 0x5f, 0x00}}, + {{0xaf, 0x5f, 0x00}}, + {{0xd7, 0x5f, 0x00}}, + {{0xff, 0x5f, 0x00}}, + {{0x00, 0x87, 0x00}}, + {{0x5f, 0x87, 0x00}}, + {{0x87, 0x87, 0x00}}, + {{0xaf, 0x87, 0x00}}, + {{0xd7, 0x87, 0x00}}, + {{0xff, 0x87, 0x00}}, + {{0x00, 0xaf, 0x00}}, + {{0x5f, 0xaf, 0x00}}, + {{0x87, 0xaf, 0x00}}, + {{0xaf, 0xaf, 0x00}}, + {{0xd7, 0xaf, 0x00}}, + {{0xff, 0xaf, 0x00}}, + {{0x00, 0xd7, 0x00}}, + {{0x5f, 0xd7, 0x00}}, + {{0x87, 0xd7, 0x00}}, + {{0xaf, 0xd7, 0x00}}, + {{0xd7, 0xd7, 0x00}}, + {{0xff, 0xd7, 0x00}}, + {{0x00, 0xff, 0x00}}, + {{0x5f, 0xff, 0x00}}, + {{0x87, 0xff, 0x00}}, + {{0xaf, 0xff, 0x00}}, + {{0xd7, 0xff, 0x00}}, + {{0xff, 0xff, 0x00}}, + {{0x00, 0x00, 0x5f}}, + {{0x5f, 0x00, 0x5f}}, + {{0x87, 0x00, 0x5f}}, + {{0xaf, 0x00, 0x5f}}, + {{0xd7, 0x00, 0x5f}}, + {{0xff, 0x00, 0x5f}}, + {{0x00, 0x5f, 0x5f}}, + {{0x5f, 0x5f, 0x5f}}, + {{0x87, 0x5f, 0x5f}}, + {{0xaf, 0x5f, 0x5f}}, + {{0xd7, 0x5f, 0x5f}}, + {{0xff, 0x5f, 0x5f}}, + {{0x00, 0x87, 0x5f}}, + {{0x5f, 0x87, 0x5f}}, + {{0x87, 0x87, 0x5f}}, + {{0xaf, 0x87, 0x5f}}, + {{0xd7, 0x87, 0x5f}}, + {{0xff, 0x87, 0x5f}}, + {{0x00, 0xaf, 0x5f}}, + {{0x5f, 0xaf, 0x5f}}, + {{0x87, 0xaf, 0x5f}}, + {{0xaf, 0xaf, 0x5f}}, + {{0xd7, 0xaf, 0x5f}}, + {{0xff, 0xaf, 0x5f}}, + {{0x00, 0xd7, 0x5f}}, + {{0x5f, 0xd7, 0x5f}}, + {{0x87, 0xd7, 0x5f}}, + {{0xaf, 0xd7, 0x5f}}, + {{0xd7, 0xd7, 0x5f}}, + {{0xff, 0xd7, 0x5f}}, + {{0x00, 0xff, 0x5f}}, + {{0x5f, 0xff, 0x5f}}, + {{0x87, 0xff, 0x5f}}, + {{0xaf, 0xff, 0x5f}}, + {{0xd7, 0xff, 0x5f}}, + {{0xff, 0xff, 0x5f}}, + {{0x00, 0x00, 0x87}}, + {{0x5f, 0x00, 0x87}}, + {{0x87, 0x00, 0x87}}, + {{0xaf, 0x00, 0x87}}, + {{0xd7, 0x00, 0x87}}, + {{0xff, 0x00, 0x87}}, + {{0x00, 0x5f, 0x87}}, + {{0x5f, 0x5f, 0x87}}, + {{0x87, 0x5f, 0x87}}, + {{0xaf, 0x5f, 0x87}}, + {{0xd7, 0x5f, 0x87}}, + {{0xff, 0x5f, 0x87}}, + {{0x00, 0x87, 0x87}}, + {{0x5f, 0x87, 0x87}}, + {{0x87, 0x87, 0x87}}, + {{0xaf, 0x87, 0x87}}, + {{0xd7, 0x87, 0x87}}, + {{0xff, 0x87, 0x87}}, + {{0x00, 0xaf, 0x87}}, + {{0x5f, 0xaf, 0x87}}, + {{0x87, 0xaf, 0x87}}, + {{0xaf, 0xaf, 0x87}}, + {{0xd7, 0xaf, 0x87}}, + {{0xff, 0xaf, 0x87}}, + {{0x00, 0xd7, 0x87}}, + {{0x5f, 0xd7, 0x87}}, + {{0x87, 0xd7, 0x87}}, + {{0xaf, 0xd7, 0x87}}, + {{0xd7, 0xd7, 0x87}}, + {{0xff, 0xd7, 0x87}}, + {{0x00, 0xff, 0x87}}, + {{0x5f, 0xff, 0x87}}, + {{0x87, 0xff, 0x87}}, + {{0xaf, 0xff, 0x87}}, + {{0xd7, 0xff, 0x87}}, + {{0xff, 0xff, 0x87}}, + {{0x00, 0x00, 0xaf}}, + {{0x5f, 0x00, 0xaf}}, + {{0x87, 0x00, 0xaf}}, + {{0xaf, 0x00, 0xaf}}, + {{0xd7, 0x00, 0xaf}}, + {{0xff, 0x00, 0xaf}}, + {{0x00, 0x5f, 0xaf}}, + {{0x5f, 0x5f, 0xaf}}, + {{0x87, 0x5f, 0xaf}}, + {{0xaf, 0x5f, 0xaf}}, + {{0xd7, 0x5f, 0xaf}}, + {{0xff, 0x5f, 0xaf}}, + {{0x00, 0x87, 0xaf}}, + {{0x5f, 0x87, 0xaf}}, + {{0x87, 0x87, 0xaf}}, + {{0xaf, 0x87, 0xaf}}, + {{0xd7, 0x87, 0xaf}}, + {{0xff, 0x87, 0xaf}}, + {{0x00, 0xaf, 0xaf}}, + {{0x5f, 0xaf, 0xaf}}, + {{0x87, 0xaf, 0xaf}}, + {{0xaf, 0xaf, 0xaf}}, + {{0xd7, 0xaf, 0xaf}}, + {{0xff, 0xaf, 0xaf}}, + {{0x00, 0xd7, 0xaf}}, + {{0x5f, 0xd7, 0xaf}}, + {{0x87, 0xd7, 0xaf}}, + {{0xaf, 0xd7, 0xaf}}, + {{0xd7, 0xd7, 0xaf}}, + {{0xff, 0xd7, 0xaf}}, + {{0x00, 0xff, 0xaf}}, + {{0x5f, 0xff, 0xaf}}, + {{0x87, 0xff, 0xaf}}, + {{0xaf, 0xff, 0xaf}}, + {{0xd7, 0xff, 0xaf}}, + {{0xff, 0xff, 0xaf}}, + {{0x00, 0x00, 0xd7}}, + {{0x5f, 0x00, 0xd7}}, + {{0x87, 0x00, 0xd7}}, + {{0xaf, 0x00, 0xd7}}, + {{0xd7, 0x00, 0xd7}}, + {{0xff, 0x00, 0xd7}}, + {{0x00, 0x5f, 0xd7}}, + {{0x5f, 0x5f, 0xd7}}, + {{0x87, 0x5f, 0xd7}}, + {{0xaf, 0x5f, 0xd7}}, + {{0xd7, 0x5f, 0xd7}}, + {{0xff, 0x5f, 0xd7}}, + {{0x00, 0x87, 0xd7}}, + {{0x5f, 0x87, 0xd7}}, + {{0x87, 0x87, 0xd7}}, + {{0xaf, 0x87, 0xd7}}, + {{0xd7, 0x87, 0xd7}}, + {{0xff, 0x87, 0xd7}}, + {{0x00, 0xaf, 0xd7}}, + {{0x5f, 0xaf, 0xd7}}, + {{0x87, 0xaf, 0xd7}}, + {{0xaf, 0xaf, 0xd7}}, + {{0xd7, 0xaf, 0xd7}}, + {{0xff, 0xaf, 0xd7}}, + {{0x00, 0xd7, 0xd7}}, + {{0x5f, 0xd7, 0xd7}}, + {{0x87, 0xd7, 0xd7}}, + {{0xaf, 0xd7, 0xd7}}, + {{0xd7, 0xd7, 0xd7}}, + {{0xff, 0xd7, 0xd7}}, + {{0x00, 0xff, 0xd7}}, + {{0x5f, 0xff, 0xd7}}, + {{0x87, 0xff, 0xd7}}, + {{0xaf, 0xff, 0xd7}}, + {{0xd7, 0xff, 0xd7}}, + {{0xff, 0xff, 0xd7}}, + {{0x00, 0x00, 0xff}}, + {{0x5f, 0x00, 0xff}}, + {{0x87, 0x00, 0xff}}, + {{0xaf, 0x00, 0xff}}, + {{0xd7, 0x00, 0xff}}, + {{0xff, 0x00, 0xff}}, + {{0x00, 0x5f, 0xff}}, + {{0x5f, 0x5f, 0xff}}, + {{0x87, 0x5f, 0xff}}, + {{0xaf, 0x5f, 0xff}}, + {{0xd7, 0x5f, 0xff}}, + {{0xff, 0x5f, 0xff}}, + {{0x00, 0x87, 0xff}}, + {{0x5f, 0x87, 0xff}}, + {{0x87, 0x87, 0xff}}, + {{0xaf, 0x87, 0xff}}, + {{0xd7, 0x87, 0xff}}, + {{0xff, 0x87, 0xff}}, + {{0x00, 0xaf, 0xff}}, + {{0x5f, 0xaf, 0xff}}, + {{0x87, 0xaf, 0xff}}, + {{0xaf, 0xaf, 0xff}}, + {{0xd7, 0xaf, 0xff}}, + {{0xff, 0xaf, 0xff}}, + {{0x00, 0xd7, 0xff}}, + {{0x5f, 0xd7, 0xff}}, + {{0x87, 0xd7, 0xff}}, + {{0xaf, 0xd7, 0xff}}, + {{0xd7, 0xd7, 0xff}}, + {{0xff, 0xd7, 0xff}}, + {{0x00, 0xff, 0xff}}, + {{0x5f, 0xff, 0xff}}, + {{0x87, 0xff, 0xff}}, + {{0xaf, 0xff, 0xff}}, + {{0xd7, 0xff, 0xff}}, + {{0xff, 0xff, 0xff}}, + {{0x00, 0x00, 0x00}}, + {{0x12, 0x12, 0x12}}, + {{0x1c, 0x1c, 0x1c}}, + {{0x26, 0x26, 0x26}}, + {{0x30, 0x30, 0x30}}, + {{0x3a, 0x3a, 0x3a}}, + {{0x44, 0x44, 0x44}}, + {{0x4e, 0x4e, 0x4e}}, + {{0x58, 0x58, 0x58}}, + {{0x62, 0x62, 0x62}}, + {{0x6c, 0x6c, 0x6c}}, + {{0x76, 0x76, 0x76}}, + {{0x80, 0x80, 0x80}}, + {{0x8a, 0x8a, 0x8a}}, + {{0x94, 0x94, 0x94}}, + {{0x9e, 0x9e, 0x9e}}, + {{0xa8, 0xa8, 0xa8}}, + {{0xb2, 0xb2, 0xb2}}, + {{0xbc, 0xbc, 0xbc}}, + {{0xc6, 0xc6, 0xc6}}, + {{0xd0, 0xd0, 0xd0}}, + {{0xda, 0xda, 0xda}}, + {{0xe4, 0xe4, 0xe4}}, + {{0xee, 0xee, 0xee}}, +}; diff --git a/xterm256lut_gen.py b/xterm256lut_gen.py new file mode 100644 index 0000000..16d8f4b --- /dev/null +++ b/xterm256lut_gen.py @@ -0,0 +1,24 @@ + +xterm_colors = [] + +# This is ripped out of pygments +# I leave out the 16 standard colors since people tend to re-define them to their liking. + +# colors 16..232: the 6x6x6 color cube +_valuerange = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff) +for i in range(217): + r = _valuerange[(i // 36) % 6] + g = _valuerange[(i // 6) % 6] + b = _valuerange[i % 6] + xterm_colors.append((r, g, b)) + +# colors 233..253: grayscale +for i in range(1, 24): + v = 8 + i * 10 + xterm_colors.append((v, v, v)) + +print('/* GENERATED HEADER FILE DO NOT EDIT */') +print('union rgb_c xterm256lut[256-16] = {') +for r,g,b in xterm_colors: + print(f' {{{{0x{b:02x}, 0x{g:02x}, 0x{r:02x}}}}},'); +print('};');