From 0039b3f8327960de697a08ebdf88e947a6a482dd Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 16 Jan 2021 13:21:32 +0100 Subject: [PATCH 01/21] Fix linker argument order (fixes #36) Thanks @elig0n ! --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 2c0277f..316c9b8 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,8 @@ CC ?= gcc LOLCAT_SRC ?= lolcat.c CENSOR_SRC ?= censor.c -CFLAGS ?= -std=c11 -Wall -Wextra -O3 -Wno-sign-compare -lm +CFLAGS ?= -std=c11 -Wall -Wextra -O3 -Wno-sign-compare +LIBS := -lm DESTDIR ?= /usr/local/bin @@ -14,10 +15,10 @@ debug: all .PHONY: install clean debug lolcat: $(LOLCAT_SRC) - $(CC) $(CFLAGS) -o $@ $^ + $(CC) $(CFLAGS) -o $@ $^ $(LIBS) censor: $(CENSOR_SRC) - $(CC) $(CFLAGS) -o $@ $^ + $(CC) $(CFLAGS) -o $@ $^ $(LIBS) install: lolcat censor install lolcat $(DESTDIR)/lolcat From 6a2ab611a726610c43945651c9153c10ec6d8f96 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 16 Jan 2021 13:23:22 +0100 Subject: [PATCH 02/21] Bump version to v1.2 --- lolcat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index 17935e9..3737b65 100755 --- a/lolcat.c +++ b/lolcat.c @@ -78,7 +78,7 @@ static void usage(void) static void version(void) { - wprintf(L"lolcat version 1.1, (c) 2020 jaseg\n"); + wprintf(L"lolcat version 1.2, (c) 2020 jaseg\n"); exit(0); } From 1d52554cb1023bed428d71bb3b051d2fbab4327c Mon Sep 17 00:00:00 2001 From: Thomas Friese Date: Sat, 17 Jul 2021 09:21:14 +0200 Subject: [PATCH 03/21] Add manual start color offset --- lolcat.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lolcat.c b/lolcat.c index 3737b65..bcf026a 100755 --- a/lolcat.c +++ b/lolcat.c @@ -41,6 +41,7 @@ static char helpstr[] = "\n" " --no-force-locale, -l: Use encoding from system locale instead of\n" " assuming UTF-8\n" " --random, -r: Random colors\n" + " --color_offset , -o : Start with a different color\n" " --24bit, -b: Output in 24-bit \"true\" RGB mode (slower and\n" " not supported by all terminals)\n" " --version: Print version and exit\n" @@ -101,6 +102,7 @@ int main(int argc, char** argv) int colors = isatty(STDOUT_FILENO); int force_locale = 1; int random = 0; + int start_color = 0; int rgb = 0; double freq_h = 0.23, freq_v = 0.1; @@ -132,6 +134,14 @@ int main(int argc, char** argv) force_locale = 0; } else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--random")) { random = 1; + } 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], "--version")) { @@ -199,7 +209,7 @@ int main(int argc, char** argv) } else { if (rgb) { i += wcwidth(c); - float theta = i * freq_h / 5.0f + l * freq_v + (offx + 2.0f * rand_offset / RAND_MAX) * M_PI; + float theta = i * freq_h / 5.0f + l * freq_v + (offx + 2.0f * (rand_offset + start_color) / RAND_MAX) * M_PI; float offset = 0.1; uint8_t red = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 0 ))) * 255.0f); @@ -210,7 +220,7 @@ int main(int argc, char** argv) } 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[(rand_offset + (cc = ncc)) % ARRAY_SIZE(codes)]); + wprintf(L"\033[38;5;%hhum", codes[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes)]); } } } @@ -219,7 +229,7 @@ int main(int argc, char** argv) putwchar(c); if (escape_state == 2) /* implies "colors" */ - wprintf(L"\033[38;5;%hhum", codes[(rand_offset + cc) % ARRAY_SIZE(codes)]); + wprintf(L"\033[38;5;%hhum", codes[(rand_offset + start_color + cc) % ARRAY_SIZE(codes)]); } if (colors) From 8173ed8cb62f22ca2ebb33a63b5b9954afb20d7e Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Mon, 11 Oct 2021 23:58:22 -0500 Subject: [PATCH 04/21] build: Add autotools option for those who want it Closes #40. --- autotools/Makefile.am | 7 +++++++ autotools/README | 7 +++++++ autotools/autogen.sh | 36 ++++++++++++++++++++++++++++++++++++ autotools/configure.ac | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 autotools/Makefile.am create mode 100644 autotools/README create mode 100755 autotools/autogen.sh create mode 100644 autotools/configure.ac 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..030e1d5 --- /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.2], [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 From 2a23642da7d6b98dd7c4c3b92c5e3fef3c70fb9d Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 19 Nov 2022 12:41:00 +0100 Subject: [PATCH 05/21] Add 16-color mode for limited terminals closes #43 --- lolcat.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index bcf026a..8257b34 100755 --- a/lolcat.c +++ b/lolcat.c @@ -44,6 +44,7 @@ static char helpstr[] = "\n" " --color_offset , -o : Start with a different color\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" " --version: Print version and exit\n" " --help: Show this message\n" "\n" @@ -58,6 +59,7 @@ static char helpstr[] = "\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}; static void find_escape_sequences(wint_t c, int* state) { @@ -74,7 +76,7 @@ static void find_escape_sequences(wint_t c, int* state) static void usage(void) { wprintf(L"Usage: lolcat [-h horizontal_speed] [-v vertical_speed] [--] [FILES...]\n"); - exit(1); + exit(2); } static void version(void) @@ -104,6 +106,7 @@ int main(int argc, char** argv) int random = 0; int start_color = 0; int rgb = 0; + int ansi16 = 0; double freq_h = 0.23, freq_v = 0.1; struct timeval tv; @@ -144,6 +147,8 @@ int main(int argc, char** argv) } } 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], "--version")) { version(); } else { @@ -153,6 +158,11 @@ 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(); + } + int rand_offset = 0; if (random) { srand(time(NULL)); @@ -217,6 +227,11 @@ int main(int argc, char** argv) uint8_t blue = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 4 * M_PI / 3 ))) * 255.0f); wprintf(L"\033[38;2;%d;%d;%dm", red, green, blue); + } else if (ansi16) { + int ncc = offx * ARRAY_SIZE(codes16) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); + if (cc != ncc) + wprintf(L"\033[%hhum", codes16[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes16)]); + } else { int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); if (cc != ncc) From 37bb84e2977265331503236ed78d39ca04352226 Mon Sep 17 00:00:00 2001 From: Nor Khasyatillah Date: Mon, 6 Jun 2022 18:10:53 +0700 Subject: [PATCH 06/21] Add new option `--seed` --- lolcat.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index 8257b34..bed0c6b 100755 --- a/lolcat.c +++ b/lolcat.c @@ -41,6 +41,7 @@ static char helpstr[] = "\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, implies --random\n" " --color_offset , -o : Start with a different color\n" " --24bit, -b: Output in 24-bit \"true\" RGB mode (slower and\n" " not supported by all terminals)\n" @@ -104,6 +105,7 @@ int main(int argc, char** argv) 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; @@ -137,6 +139,15 @@ int main(int argc, char** argv) 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); @@ -165,9 +176,10 @@ int main(int argc, char** argv) int rand_offset = 0; if (random) { - srand(time(NULL)); + srand(seed); rand_offset = rand(); } + char** inputs = argv + i; char** inputs_end = argv + argc; if (inputs == inputs_end) { From 6db5a0fa5005710ff1a71a721b3d625e61c37e78 Mon Sep 17 00:00:00 2001 From: Nor Khasyatillah Date: Fri, 27 May 2022 16:56:07 +0700 Subject: [PATCH 07/21] Add new option `--invert`. --- lolcat.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/lolcat.c b/lolcat.c index bed0c6b..51ab464 100755 --- a/lolcat.c +++ b/lolcat.c @@ -46,6 +46,7 @@ static char helpstr[] = "\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" @@ -109,6 +110,7 @@ int main(int argc, char** argv) int start_color = 0; int rgb = 0; int ansi16 = 0; + int invert = 0; double freq_h = 0.23, freq_v = 0.1; struct timeval tv; @@ -160,6 +162,8 @@ int main(int argc, char** argv) 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], "--version")) { version(); } else { @@ -174,6 +178,14 @@ int main(int argc, char** argv) usage(); } + if (invert) { + if (ansi16) { + wprintf(L"\033[30m\n"); + } else { + wprintf(L"\033[38;5;16m\n"); + } + } + int rand_offset = 0; if (random) { srand(seed); @@ -227,6 +239,9 @@ int main(int argc, char** argv) if (c == '\n') { l++; i = 0; + if (invert) { + wprintf(L"\033[49m"); + } } else { if (rgb) { @@ -237,17 +252,17 @@ int main(int argc, char** argv) uint8_t red = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 0 ))) * 255.0f); uint8_t green = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 2 * M_PI / 3 ))) * 255.0f); uint8_t blue = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 4 * M_PI / 3 ))) * 255.0f); - wprintf(L"\033[38;2;%d;%d;%dm", red, green, blue); + wprintf(L"\033[%d;2;%d;%d;%dm", (invert ? 48 : 38), red, green, blue); } else if (ansi16) { int ncc = offx * ARRAY_SIZE(codes16) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); if (cc != ncc) - wprintf(L"\033[%hhum", codes16[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes16)]); + wprintf(L"\033[%hhum", (invert ? 10 : 0) + codes16[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes16)]); } 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[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes)]); + wprintf(L"\033[%d;5;%hhum", (invert ? 48 : 38), codes[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes)]); } } } From 8ed4ce20a56123e0dfb0b0e1039c9a733fec3b5f Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 19 Nov 2022 14:24:04 +0100 Subject: [PATCH 08/21] Add --gradient option, allow specification of custom gradients. Closes #47 --- Makefile | 13 +-- lolcat.c | 205 +++++++++++++++++++++++++++++++++++--- xterm256lut.h | 243 +++++++++++++++++++++++++++++++++++++++++++++ xterm256lut_gen.py | 24 +++++ 4 files changed, 466 insertions(+), 19 deletions(-) create mode 100644 xterm256lut.h create mode 100644 xterm256lut_gen.py diff --git a/Makefile b/Makefile index 316c9b8..9ce889d 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,5 @@ CC ?= gcc -LOLCAT_SRC ?= lolcat.c -CENSOR_SRC ?= censor.c CFLAGS ?= -std=c11 -Wall -Wextra -O3 -Wno-sign-compare LIBS := -lm @@ -14,11 +12,14 @@ debug: all .PHONY: install clean debug -lolcat: $(LOLCAT_SRC) - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) +xterm256lut.h: xterm256lut_gen.py + python $< > $@ -censor: $(CENSOR_SRC) - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) +lolcat: lolcat.c xterm256lut.h + $(CC) $(CFLAGS) -o $@ $< $(LIBS) + +censor: censor.c + $(CC) $(CFLAGS) -o $@ $< $(LIBS) install: lolcat censor install lolcat $(DESTDIR)/lolcat diff --git a/lolcat.c b/lolcat.c index 51ab464..a70aed4 100755 --- a/lolcat.c +++ b/lolcat.c @@ -24,7 +24,9 @@ #include #include #include +#include #include +#include #include #include #include "math.h" @@ -41,8 +43,11 @@ static char helpstr[] = "\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, implies --random\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" @@ -62,6 +67,110 @@ static char helpstr[] = "\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]; + +union rgb_c { + struct { + unsigned char b; + unsigned char g; + unsigned char r; + }; + unsigned int i; +}; + +struct hsv_c { + double h; + double s; + double v; +}; + +#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 rgb2hsv(union rgb_c *in, struct hsv_c *out) { + double r = in->r/255.0, g = in->g/255.0, b = in->b/255.0; + double fCMax = MAX(MAX(r, g), b); + double fCMin = MIN(MIN(r, g), b); + double fDelta = fCMax - fCMin; + + out->v = fCMax; + if(fDelta > 0) { + if(fCMax == r) { + out->h = 60 * (fmod(((g - b) / fDelta), 6)); + } else if(fCMax == g) { + out->h = 60 * (((b - r) / fDelta) + 2); + } else if(fCMax == b) { + out->h = 60 * (((r - g) / fDelta) + 4); + } + + if(out->h < 0) { + out->h = 360 + out->h; + } + + out->s = fCMax > 0 ? fDelta / fCMax : 0; + } else { + out->h = 0; + out->s = 0; + } +} + +void hsv2rgb(struct hsv_c *in, union rgb_c *out) { + double fC = in->v * in->s; + double fHPrime = fmod(in->h / 60.0, 6); + double fX = fC * (1 - fabs(fmod(fHPrime, 2) - 1)); + double fM = in->v - fC; + + switch ((int)fHPrime) { + case 0: out->r = (fC + fM)*255; out->g = (fX + fM)*255; out->b = 0; break; + case 1: out->g = (fC + fM)*255; out->r = (fX + fM)*255; out->b = 0; break; + case 2: out->g = (fC + fM)*255; out->b = (fX + fM)*255; out->r = 0; break; + case 3: out->b = (fC + fM)*255; out->g = (fX + fM)*255; out->r = 0; break; + case 4: out->b = (fC + fM)*255; out->r = (fX + fM)*255; out->g = 0; break; + case 5: out->r = (fC + fM)*255; out->b = (fX + fM)*255; out->g = 0; break; + default: out->r = 0; out->g = 0; out->b = 0; break; + } +} + +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; +} + +void hsv_interpolate(struct hsv_c *start, struct hsv_c *end, union rgb_c *out, double f) { + double hd = end->h - start->h; + if (hd > 180) { + hd -= 360; + } else if (hd < -180) { + hd += 360; + } + + struct hsv_c hsv_intermediate = { + .h = start->h + hd*f, + .s = start->s + (end->s - start->s)*f, + .v = start->v + (end->v - start->v)*f}; + if (hsv_intermediate.h < 0) { + hsv_intermediate.h += 360; + } else if (hsv_intermediate.h > 360) { + hsv_intermediate.h -= 360; + } + hsv2rgb(&hsv_intermediate, out); +} static void find_escape_sequences(wint_t c, int* state) { @@ -111,6 +220,8 @@ int main(int argc, char** argv) 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; @@ -164,6 +275,30 @@ int main(int argc, char** argv) 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 { @@ -178,6 +313,25 @@ int main(int argc, char** argv) 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 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 += wcwidth(c)) * freq_h + l * freq_v); - if (cc != ncc) + if (cc != ncc) { wprintf(L"\033[%hhum", (invert ? 10 : 0) + codes16[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes16)]); + } } else { - int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); - if (cc != ncc) - wprintf(L"\033[%d;5;%hhum", (invert ? 48 : 38), codes[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes)]); + if (gradient) { + int ncc = offx * ARRAY_SIZE(codes_gradient) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); + if (cc != ncc) { + 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 += wcwidth(c)) * freq_h + l * freq_v); + if (cc != ncc) { + wprintf(L"\033[%d;5;%hhum", (invert ? 48 : 38), codes[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes)]); + } + } } } } @@ -270,12 +447,14 @@ int main(int argc, char** argv) putwchar(c); - if (escape_state == 2) /* implies "colors" */ + if (escape_state == 2) { /* implies "colors" */ wprintf(L"\033[38;5;%hhum", codes[(rand_offset + start_color + cc) % ARRAY_SIZE(codes)]); + } } - if (colors) + if (colors) { wprintf(L"\033[0m"); + } cc = -1; 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('};'); From 4d7a6c3bba85d84184ecfb703320243c5420d8e6 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 19 Nov 2022 14:24:45 +0100 Subject: [PATCH 09/21] Remove redundant code --- lolcat.c | 70 -------------------------------------------------------- 1 file changed, 70 deletions(-) diff --git a/lolcat.c b/lolcat.c index a70aed4..8961850 100755 --- a/lolcat.c +++ b/lolcat.c @@ -78,12 +78,6 @@ union rgb_c { unsigned int i; }; -struct hsv_c { - double h; - double s; - double v; -}; - #include "xterm256lut.h" int xterm256lookup(union rgb_c *in) { @@ -102,76 +96,12 @@ int xterm256lookup(union rgb_c *in) { return 16 + min_i; } -void rgb2hsv(union rgb_c *in, struct hsv_c *out) { - double r = in->r/255.0, g = in->g/255.0, b = in->b/255.0; - double fCMax = MAX(MAX(r, g), b); - double fCMin = MIN(MIN(r, g), b); - double fDelta = fCMax - fCMin; - - out->v = fCMax; - if(fDelta > 0) { - if(fCMax == r) { - out->h = 60 * (fmod(((g - b) / fDelta), 6)); - } else if(fCMax == g) { - out->h = 60 * (((b - r) / fDelta) + 2); - } else if(fCMax == b) { - out->h = 60 * (((r - g) / fDelta) + 4); - } - - if(out->h < 0) { - out->h = 360 + out->h; - } - - out->s = fCMax > 0 ? fDelta / fCMax : 0; - } else { - out->h = 0; - out->s = 0; - } -} - -void hsv2rgb(struct hsv_c *in, union rgb_c *out) { - double fC = in->v * in->s; - double fHPrime = fmod(in->h / 60.0, 6); - double fX = fC * (1 - fabs(fmod(fHPrime, 2) - 1)); - double fM = in->v - fC; - - switch ((int)fHPrime) { - case 0: out->r = (fC + fM)*255; out->g = (fX + fM)*255; out->b = 0; break; - case 1: out->g = (fC + fM)*255; out->r = (fX + fM)*255; out->b = 0; break; - case 2: out->g = (fC + fM)*255; out->b = (fX + fM)*255; out->r = 0; break; - case 3: out->b = (fC + fM)*255; out->g = (fX + fM)*255; out->r = 0; break; - case 4: out->b = (fC + fM)*255; out->r = (fX + fM)*255; out->g = 0; break; - case 5: out->r = (fC + fM)*255; out->b = (fX + fM)*255; out->g = 0; break; - default: out->r = 0; out->g = 0; out->b = 0; break; - } -} - 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; } -void hsv_interpolate(struct hsv_c *start, struct hsv_c *end, union rgb_c *out, double f) { - double hd = end->h - start->h; - if (hd > 180) { - hd -= 360; - } else if (hd < -180) { - hd += 360; - } - - struct hsv_c hsv_intermediate = { - .h = start->h + hd*f, - .s = start->s + (end->s - start->s)*f, - .v = start->v + (end->v - start->v)*f}; - if (hsv_intermediate.h < 0) { - hsv_intermediate.h += 360; - } else if (hsv_intermediate.h > 360) { - hsv_intermediate.h -= 360; - } - hsv2rgb(&hsv_intermediate, out); -} - static void find_escape_sequences(wint_t c, int* state) { if (c == '\033') { /* Escape sequence YAY */ From 8241091f59eced21d16449e281e4249b6af72406 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 19 Nov 2022 17:31:34 +0100 Subject: [PATCH 10/21] Extend escape sequence parser to support various ST-terminated sequences This improves interactions with programs using them to set the terminal window title or display images among other things. Closes #42. --- lolcat.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/lolcat.c b/lolcat.c index 8961850..b67ca07 100755 --- a/lolcat.c +++ b/lolcat.c @@ -102,15 +102,53 @@ void rgb_interpolate(union rgb_c *start, union rgb_c *end, union rgb_c *out, dou out->b = start->b + (end->b - start->b)*f; } -static void find_escape_sequences(wint_t c, int* state) +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, +}; + +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 && c == '\033') { /* Escape sequence YAY */ + return ST_ESC_BEGIN; + + } 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 == '\033') { + return ST_ESC_STRING_TERM; + } else { + return st; + } + + } else if (st == ST_ESC_STRING_TERM) { + if (c == '\\') { + return ST_ESC_TERM; + } else { + return ST_ESC_STRING; + } + } else { - *state = 0; + return ST_NONE; } } @@ -296,7 +334,7 @@ int main(int argc, char** argv) for (char** filename = inputs; filename < inputs_end; filename++) { wint_t (*this_file_read_wchar)(FILE*); /* Used for --help because fmemopen is universally broken when used with fgetwc */ FILE* f; - int escape_state = 0; + int escape_state = ST_NONE; if (!strcmp(*filename, "--help")) { this_file_read_wchar = &helpstr_hack; @@ -317,7 +355,7 @@ int main(int argc, char** argv) while ((c = this_file_read_wchar(f)) != WEOF) { if (colors) { - find_escape_sequences(c, &escape_state); + escape_state = find_escape_sequences(c, escape_state); if (!escape_state) { if (c == '\n') { @@ -377,7 +415,7 @@ int main(int argc, char** argv) putwchar(c); - if (escape_state == 2) { /* implies "colors" */ + if (escape_state == ST_ESC_CSI_TERM) { /* implies "colors" */ wprintf(L"\033[38;5;%hhum", codes[(rand_offset + start_color + cc) % ARRAY_SIZE(codes)]); } } From a087460a9946adf05395afe821dfff1240fc3765 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 19 Nov 2022 17:40:06 +0100 Subject: [PATCH 11/21] Bump version to v1.3 --- PKGBUILD | 2 +- autotools/configure.ac | 2 +- lolcat.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 6b7ef0c..5c2652e 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Ricardo (XenGi) Band pkgname=c-lolcat -pkgver=r26.502d379 +pkgver=v1.3 pkgrel=1 pkgdesc="High-performance implementation of lolcat" arch=('i686' 'x86_64') diff --git a/autotools/configure.ac b/autotools/configure.ac index 030e1d5..8b9871b 100644 --- a/autotools/configure.ac +++ b/autotools/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([lolcat], [1.2], [jaseg ]) +AC_INIT([lolcat], [1.3], [jaseg ]) AC_CONFIG_SRCDIR([../lolcat.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_AUX_DIR([autoscripts]) diff --git a/lolcat.c b/lolcat.c index b67ca07..38b4198 100755 --- a/lolcat.c +++ b/lolcat.c @@ -160,7 +160,7 @@ static void usage(void) static void version(void) { - wprintf(L"lolcat version 1.2, (c) 2020 jaseg\n"); + wprintf(L"lolcat version 1.3, (c) 2020 jaseg\n"); exit(0); } From f25a84cc4de2fb886389d2168621cfac88aa7003 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 26 Feb 2023 18:53:36 +0100 Subject: [PATCH 12/21] Fix handling of repeated escape sequences and certain XTERM title sequences --- lolcat.c | 64 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/lolcat.c b/lolcat.c index 38b4198..1a9533e 100755 --- a/lolcat.c +++ b/lolcat.c @@ -110,12 +110,28 @@ enum esc_st { 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 (st == ST_NONE && c == '\033') { /* Escape sequence YAY */ - return ST_ESC_BEGIN; + + 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 == '[') { @@ -134,7 +150,9 @@ static enum esc_st find_escape_sequences(wint_t c, enum esc_st st) } } else if (st == ST_ESC_STRING) { - if (c == '\033') { + if (c == '\007') { + return ST_NONE; + } else if (c == '\033') { return ST_ESC_STRING_TERM; } else { return st; @@ -142,7 +160,7 @@ static enum esc_st find_escape_sequences(wint_t c, enum esc_st st) } else if (st == ST_ESC_STRING_TERM) { if (c == '\\') { - return ST_ESC_TERM; + return ST_NONE; } else { return ST_ESC_STRING; } @@ -155,6 +173,8 @@ static enum esc_st find_escape_sequences(wint_t c, enum esc_st st) static void usage(void) { wprintf(L"Usage: lolcat [-h horizontal_speed] [-v vertical_speed] [--] [FILES...]\n"); + wprintf(L"\n"); + wprintf(L"Use lolcat --help to print the full help text.\n"); exit(2); } @@ -355,9 +375,18 @@ int main(int argc, char** argv) while ((c = this_file_read_wchar(f)) != WEOF) { if (colors) { - escape_state = find_escape_sequences(c, escape_state); - if (!escape_state) { + + escape_state = find_escape_sequences(c, escape_state); +#ifdef ESC_DEBUG + fprintf(stderr, "%02x %c %s\n", c, c > 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; @@ -366,8 +395,11 @@ int main(int argc, char** argv) } } else { - if (rgb) { + 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; @@ -386,15 +418,15 @@ int main(int argc, char** argv) 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 += wcwidth(c)) * freq_h + l * freq_v); - if (cc != ncc) { + 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 += wcwidth(c)) * freq_h + l * freq_v); - if (cc != ncc) { + 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; @@ -403,8 +435,8 @@ int main(int argc, char** argv) } } else { - int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); - if (cc != ncc) { + 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)]); } } @@ -413,10 +445,8 @@ int main(int argc, char** argv) } } - putwchar(c); - - if (escape_state == ST_ESC_CSI_TERM) { /* implies "colors" */ - wprintf(L"\033[38;5;%hhum", codes[(rand_offset + start_color + cc) % ARRAY_SIZE(codes)]); + if (escape_state != ST_ESC_CSI_TERM) { + putwchar(c); } } From dc3ddf395017bf903f5bfb8f0c5c6d08d84fcdc0 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 26 Feb 2023 18:54:34 +0100 Subject: [PATCH 13/21] Bump version to v1.4 --- lolcat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index 1a9533e..a323720 100755 --- a/lolcat.c +++ b/lolcat.c @@ -180,7 +180,7 @@ static void usage(void) static void version(void) { - wprintf(L"lolcat version 1.3, (c) 2020 jaseg\n"); + wprintf(L"lolcat version 1.4, (c) 2023 jaseg\n"); exit(0); } From f2c26ed7a72828f94f174ab8c84676856fbe2097 Mon Sep 17 00:00:00 2001 From: jaseg Date: Thu, 4 Jul 2024 11:44:47 +0200 Subject: [PATCH 14/21] Make lolcat interleave nicely with non-colored stderr This works by making lolcat always reset the color at the end of a line on its input, and only setting a new color immediately before printing the first character on the next line. This way, assuming that whatever process is piped into lolcat follow the standard convention where stdout is buffered line-wise, and only writes full lines to stderr, a process that outputs to both stdout and stderr but that has only stdout piped through lolcat (as most people would do) would have it's stderr output interleave nicely uncolored with the lolcat-colored stdout output. This won't always work, but it gets us most of the way there with little effort and negligible (2 extra escape sequences per line of output) performance overhead. Thanks to github user @kolayne for reporting this as an issue! --- lolcat.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lolcat.c b/lolcat.c index a323720..ff39189 100755 --- a/lolcat.c +++ b/lolcat.c @@ -390,8 +390,11 @@ int main(int argc, char** argv) if (c == '\n') { l++; i = 0; + cc = -1; if (invert) { wprintf(L"\033[49m"); + } else { + wprintf(L"\033[0m"); } } else { From a9ab81839f2a00fa1d831648a1d79e268bb1ddac Mon Sep 17 00:00:00 2001 From: jaseg Date: Thu, 4 Jul 2024 11:49:59 +0200 Subject: [PATCH 15/21] Bump version to v1.5 --- lolcat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index ff39189..011f5dc 100755 --- a/lolcat.c +++ b/lolcat.c @@ -180,7 +180,7 @@ static void usage(void) static void version(void) { - wprintf(L"lolcat version 1.4, (c) 2023 jaseg\n"); + wprintf(L"lolcat version 1.5, (c) 2024 jaseg\n"); exit(0); } From bfd74461983817b76b5c96824fa83e486fc1d416 Mon Sep 17 00:00:00 2001 From: Ellam ByDefault Date: Sun, 14 Jul 2024 00:20:17 +0700 Subject: [PATCH 16/21] ignore `lolcat` and `censor`, add Debian dependency --- .gitignore | 2 ++ README.md | 2 ++ 2 files changed, 4 insertions(+) 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/README.md b/README.md index f2d4af9..3cbfba4 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,8 @@ $ make lolcat ### Others +Note: Debian users may need the `python-is-python3` package. + ```bash $ make && sudo make install ``` From 10b56bcdc25698de7898bcc090ab30757e33241d Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 16 Jul 2024 11:24:39 +0200 Subject: [PATCH 17/21] Fix version number in autotools and PKGBUILD build scripts --- PKGBUILD | 2 +- autotools/configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 5c2652e..baec990 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Ricardo (XenGi) Band pkgname=c-lolcat -pkgver=v1.3 +pkgver=v1.5 pkgrel=1 pkgdesc="High-performance implementation of lolcat" arch=('i686' 'x86_64') diff --git a/autotools/configure.ac b/autotools/configure.ac index 8b9871b..28f5d08 100644 --- a/autotools/configure.ac +++ b/autotools/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([lolcat], [1.3], [jaseg ]) +AC_INIT([lolcat], [1.5], [jaseg ]) AC_CONFIG_SRCDIR([../lolcat.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_AUX_DIR([autoscripts]) From e460e3d1328f3e9e7d468da7901fe52f0fc7018a Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 16 Jul 2024 11:35:08 +0200 Subject: [PATCH 18/21] Add a little release script to keep the version numbers in sync Fixes #58 --- do_release.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100755 do_release.sh 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." + From 1ea54a14d5705cd0bd2959acbe77941bff484661 Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 16 Jul 2024 11:36:27 +0200 Subject: [PATCH 19/21] Make images embedded in README use relative paths Fixes #59 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3cbfba4..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) From 621b604edd146343c5d43fe5d889287edb4531a5 Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 16 Jul 2024 11:39:09 +0200 Subject: [PATCH 20/21] Add CPPFLAGS and LDFLAGS to compiler invocation Fixes #57 --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 9ce889d..c89fcf8 100644 --- a/Makefile +++ b/Makefile @@ -16,10 +16,10 @@ xterm256lut.h: xterm256lut_gen.py python $< > $@ lolcat: lolcat.c xterm256lut.h - $(CC) $(CFLAGS) -o $@ $< $(LIBS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) censor: censor.c - $(CC) $(CFLAGS) -o $@ $< $(LIBS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) install: lolcat censor install lolcat $(DESTDIR)/lolcat From 1212a9cc6c2a092359db460d9f62822b56dc02ef Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 16 Jul 2024 11:43:44 +0200 Subject: [PATCH 21/21] Correct DESTDIR/PREFIX usage in Makefile Closes #56 --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index c89fcf8..c751508 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC ?= gcc CFLAGS ?= -std=c11 -Wall -Wextra -O3 -Wno-sign-compare LIBS := -lm -DESTDIR ?= /usr/local/bin +PREFIX ?= /usr/local all: lolcat censor @@ -22,8 +22,8 @@ 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