Compare commits

..

45 commits
v1.0 ... main

Author SHA1 Message Date
jaseg
1212a9cc6c Correct DESTDIR/PREFIX usage in Makefile
Closes #56
2024-07-16 11:43:44 +02:00
jaseg
621b604edd Add CPPFLAGS and LDFLAGS to compiler invocation
Fixes #57
2024-07-16 11:39:09 +02:00
jaseg
1ea54a14d5 Make images embedded in README use relative paths
Fixes #59
2024-07-16 11:36:46 +02:00
jaseg
e460e3d132 Add a little release script to keep the version numbers in sync
Fixes #58
2024-07-16 11:35:08 +02:00
jaseg
10b56bcdc2 Fix version number in autotools and PKGBUILD build scripts 2024-07-16 11:24:39 +02:00
Ellam ByDefault
bfd7446198 ignore lolcat and censor, add Debian dependency 2024-07-16 11:16:39 +02:00
jaseg
a9ab81839f Bump version to v1.5 2024-07-04 11:49:59 +02:00
jaseg
f2c26ed7a7 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!
2024-07-04 11:45:58 +02:00
jaseg
dc3ddf3950 Bump version to v1.4 2023-02-26 18:57:20 +01:00
jaseg
f25a84cc4d Fix handling of repeated escape sequences and certain XTERM title sequences 2023-02-26 18:56:57 +01:00
jaseg
a087460a99 Bump version to v1.3 2022-11-19 17:40:06 +01:00
jaseg
8241091f59 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.
2022-11-19 17:31:34 +01:00
jaseg
4d7a6c3bba Remove redundant code 2022-11-19 14:24:45 +01:00
jaseg
8ed4ce20a5 Add --gradient option, allow specification of custom gradients.
Closes #47
2022-11-19 14:24:04 +01:00
Nor Khasyatillah
6db5a0fa50 Add new option --invert. 2022-11-19 13:00:17 +01:00
Nor Khasyatillah
37bb84e297 Add new option --seed 2022-11-19 12:49:46 +01:00
jaseg
2a23642da7 Add 16-color mode for limited terminals
closes #43
2022-11-19 12:41:00 +01:00
Daniel Santos
8173ed8cb6 build: Add autotools option for those who want it
Closes #40.
2021-10-14 23:11:20 +02:00
Thomas Friese
1d52554cb1 Add manual start color offset 2021-07-28 13:00:07 +02:00
jaseg
6a2ab611a7 Bump version to v1.2 2021-01-16 13:23:22 +01:00
jaseg
0039b3f832 Fix linker argument order (fixes #36)
Thanks @elig0n !
2021-01-16 13:21:53 +01:00
jaseg
a1dfac8cf4 Bump version to v1.1 2020-12-25 15:54:19 +01:00
jaseg
8d54f67f41 Fix variable scoping error 2020-12-25 15:54:09 +01:00
jaseg
b6480279fb Add fallback for locale-setting on systems without C.UTF-8 locale 2020-12-25 15:47:08 +01:00
jaseg
e6103e70be Add random support for rgb mode 2020-12-25 15:38:30 +01:00
jaseg
a924f2a523 Update help string for long options 2020-12-25 15:38:21 +01:00
jaseg
460259df6f Add long option names 2020-12-25 15:08:16 +01:00
jaseg
cac1312906 Add daytime offset to 24-bit rgb color option too 2020-12-25 15:08:06 +01:00
jaseg
861fc46bb3 Add help string for -b 24-bit rgb color option 2020-12-25 15:07:12 +01:00
jaseg
e6d4480145 Make rgb rainbow match xterm palette more closely 2020-12-25 14:47:15 +01:00
jaseg
2f5d7ab8c0 Make rgb support off-by-default 2020-12-25 14:47:00 +01:00
Remy Noulin
36cce5225b add RGB 24bits color support (default)
Option -8bits is for 256 colors

lolcat.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
2020-12-25 14:46:43 +01:00
jaseg
9efc71de4f Fix incorrect usage of ferror after fclose
Closes #35
2020-12-25 13:42:09 +01:00
ara.t.howard
5b97d040b3 Update Makefile
-Wno-sign-compare
2020-11-22 12:58:11 +01:00
Kian Kasad
931f28e08d set compiler optimization option 2020-11-22 12:55:57 +01:00
cheese1
9df2d9edef
Update README.md 2020-08-13 13:07:50 +02:00
josef radinger
a83e59dc25 https instead of http 2019-11-10 16:40:32 +01:00
jaseg
9beb9dbfc5 Fix compiler warning about missing time header 2019-11-10 16:38:35 +01:00
Edgar Fouillet
d92c9b91f7 Add random option 2019-11-10 16:36:39 +01:00
Edgar Fouillet
92831e54d8 Makefile: remove -g from default cc command 2019-11-10 16:36:39 +01:00
Edgar Fouillet
6e1caef075 lolcat: Fix segfault on launch when LANG is undefined
Closes #27
2019-11-10 16:36:39 +01:00
jaseg
35dca3d0a3 Fix project url and bump version to v1.0
Thanks @bratkartoffel . Closes #23
2019-06-17 11:07:07 +09:00
m3tav3rse
abe2bacbf9 Don't force C.UTF-8 when locale is UTF-8 already
closes #21
2019-06-17 11:07:07 +09:00
jaseg
9a928b9ff4 lolcat: Remove redundant newline at end of output 2019-06-16 21:26:00 +09:00
Ricardo Band
176478b36e README.md: Don't use yaourt on Arch (#17)
Removed the aur helper. The new guide works for everyone.
See https://wiki.archlinux.org/index.php/AUR_helpers#Discontinued_or_problematic
2019-03-19 08:48:25 +09:00
13 changed files with 726 additions and 57 deletions

2
.gitignore vendored
View file

@ -1,2 +1,4 @@
lolcat.o
censor.o
lolcat
censor

View file

@ -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

View file

@ -1,7 +1,7 @@
# Maintainer: Ricardo (XenGi) Band <email@ricardo.band>
pkgname=c-lolcat
pkgver=r26.502d379
pkgver=v1.5
pkgrel=1
pkgdesc="High-performance implementation of lolcat"
arch=('i686' 'x86_64')

View file

@ -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
```

7
autotools/Makefile.am Normal file
View file

@ -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

7
autotools/README Normal file
View file

@ -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

36
autotools/autogen.sh Executable file
View file

@ -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

35
autotools/configure.ac Normal file
View file

@ -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 <github@jaseg.de>])
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

View file

@ -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;
}

31
do_release.sh Executable file
View file

@ -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."

350
lolcat.c Normal file → Executable file
View file

@ -1,4 +1,4 @@
/* Copyright (C) 2014 jaseg <github@jaseg.net>
/* Copyright (C) 2020 jaseg <github@jaseg.net>
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* Version 2, December 2004
@ -24,8 +24,12 @@
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/param.h>
#include <unistd.h>
#include <limits.h>
#include <wchar.h>
#include <time.h>
#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 <d>: Horizontal rainbow frequency (default: 0.23)\n"
" -v <d>: 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 <d>, -h <d>: Horizontal rainbow frequency (default: 0.23)\n"
" --vertical-frequency <d>, -v <d>: 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 <d>, -s <d>: Random colors based on given seed,\n"
" implies --random\n"
" --color_offset <d>, -o <d>: Start with a different color\n"
" --gradient <g>, -g <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 <http://www.github.org/jaseg/lolcat/issues>\n"
"lolcat home page: <http://www.github.org/jaseg/lolcat/>\n"
"Original idea: <http://www.github.org/busyloop/lolcat/>\n";
"Report lolcat bugs to <https://github.com/jaseg/lolcat/issues>\n"
"lolcat home page: <https://github.com/jaseg/lolcat/>\n"
"Original idea: <https://github.com/busyloop/lolcat/>\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; i<ARRAY_SIZE(xterm256lut); i++) {
int dr = in->r - 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<ARRAY_SIZE(codes_gradient); i++) {
double f = i / (double)(ARRAY_SIZE(codes_gradient) - 1);
union rgb_c rgb_intermediate;
rgb_interpolate(&rgb_start, &rgb_end, &rgb_intermediate, f);
codes_gradient[i] = xterm256lookup(&rgb_intermediate);
}
}
}
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);
rand_offset = rand();
}
char** inputs = argv + i;
char** inputs_end = argv + argc;
if (inputs == inputs_end) {
@ -138,16 +341,20 @@ int main(int argc, char** argv)
inputs_end = inputs + 1;
}
if (force_locale)
setlocale(LC_ALL, "C.UTF-8");
else
char* env_lang = getenv("LANG");
if (force_locale && env_lang && !strstr(env_lang, "UTF-8")) {
if (!setlocale(LC_ALL, "C.UTF-8")) { /* C.UTF-8 may not be available on all platforms */
setlocale(LC_ALL, ""); /* Let's hope for the best */
}
} else {
setlocale(LC_ALL, "");
}
i = 0;
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;
@ -168,36 +375,99 @@ int main(int argc, char** argv)
while ((c = this_file_read_wchar(f)) != WEOF) {
if (colors) {
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;
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;
}
}

243
xterm256lut.h Normal file
View file

@ -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}},
};

24
xterm256lut_gen.py Normal file
View file

@ -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('};');