glow
glow copied to clipboard
When output is redirected, terminal capabilities are ignored and colors are illegible
Describe the bug When output is redirected/piped, terminal capabilities are ignored and colors are illegible.
Setup
- Ubuntu 22.04 LTS
- Zsh
- Wezterm
- tmux
- en_US.UTF-8
To Reproduce
- Given a markdown
README.md. . . - Run:
$ CLICOLOR_FORCE=1 glow --style dark README.md | head
Source Code
Expected behavior
The colors should be the same as they are when | head is omitted, and the header titles should have enough contrast to be easily read.
Screenshots
Additional context
See discussion at https://github.com/charmbracelet/glow/issues/440#issuecomment-2358748595
Thanks for the excellent report.Β As mentioned, this looks like a regression. Off the cuff I'd guess it's downsampling to 4-bit ANSI (i.e. the 16 user-definable terminal colors; the first two rows in the following chart).
It's the behavior of termenv, which glow uses. See https://github.com/muesli/termenv/blob/82936c5ea257b458deb5238e6093773b42c43773/termenv.go#L104.
In short, when being piped, it detects that no terminal capabilities are available, hence no color profile will be chosen. If you force the color output with CLICOLOR_FORCE=1 when no color profile is detected, it will fallback to 4-color ANSI.
Aha, there we have it. Technically speaking CLICOLOR_FORCE=1 COLORTERM=truecolor glow-s dark filename.md | head should work, but it looks like it may have regressed upstream.
Alternatively, we could introduce a flag like glow --force-color-profile.
glow --force-color-profile=truecolor
glow --force-color-profile=ansi256
glow --force-color-profile=ansi
glow --force-color-profile=notty
instead of the --force-color-profile flag, just use whatever value COLORTERM env var contains
Thatβs fine by me, but termenv will need to be corrected upstream.
https://github.com/charmbracelet/glow/issues/21#issuecomment-2467020125
script -q -c "glow README.md" | tail -n +2
After some digging, I found something interesting.
bash -c "echo date_before_script: \$(date); script -q -c 'echo date_before_glow: \$(date); glow README.md; echo date_after_glow: \$(date)' > temp; cat temp; echo date_after_script: \$(date)" > temp2
Instead of > temp2 in the end you can use | sed '3d' to remove bad line and
with following README.md:
# header
1. _something_
2. *bold*
temp2 looks like this:
date_before_script: Mon Nov 11 04:22:13 MSK 2024
date_before_glow: Mon Nov 11 04:22:13 MSK 2024
]10;?\[6n]11;?\[6n]11;?\[6n
[38;5;228;48;5;63;1m[0m[38;5;228;48;5;63;1m[0m [38;5;228;48;5;63;1m [0m[38;5;228;48;5;63;1mheader[0m[38;5;228;48;5;63;1m [0m[38;5;252m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[0m
[0m [38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m
[38;5;252m[0m[38;5;252m[0m [38;5;252m1[0m[38;5;252m. [0m[38;5;252;3msomething[0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m
[38;5;252m[0m[38;5;252m[0m [38;5;252m2[0m[38;5;252m. [0m[38;5;252;3mbold[0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m
date_after_glow: Mon Nov 11 04:22:28 MSK 2024
date_after_script: Mon Nov 11 04:22:28 MSK 2024
Pairs of dates are exactly the same. Long execution is glow's or some other internally used library's responsibility. And for me it's always exactly 15 f***ing seconds. TTY is allocated immediately. And first line, that breaks output, is printed by glow too.
@eric-saintetienne (pinging because I think you'll be interested about it too because you did the same stuff here: https://github.com/charmbracelet/glow/issues/21#issuecomment-2360703369)
I tried tracing the program. I created following script:
#!/bin/bash
/bin/bash -c "echo date_before_script: \$(/sbin/date); /sbin/script -q -c 'echo date_before_glow: \$(/sbin/date); SHLVL=1 COLUMNS=180 LINES=49 /sbin/glow README.md; echo date_after_glow: \$(/sbin/date)' > temp; /sbin/cat temp; echo date_after_script: \$(/sbin/date)" > temp2
And then I'm running it
sudo strace ./sh
What I get
trace log
execve("./sh", ["./sh"], 0x7ffcd70817c0 /* 17 vars */) = 0
brk(NULL) = 0x5ae528cfd000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=194599, ...}) = 0
mmap(NULL, 194599, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a28493000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/libreadline.so.8", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=343064, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x758a28491000
mmap(NULL, 350904, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x758a2843b000
mmap(0x758a28450000, 188416, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15000) = 0x758a28450000
mmap(0x758a2847e000, 36864, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x43000) = 0x758a2847e000
mmap(0x758a28487000, 36864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x4b000) = 0x758a28487000
mmap(0x758a28490000, 2744, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x758a28490000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\340_\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
fstat(3, {st_mode=S_IFREG|0755, st_size=2014520, ...}) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 2034616, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x758a2824a000
mmap(0x758a2826e000, 1511424, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x24000) = 0x758a2826e000
mmap(0x758a283df000, 319488, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x195000) = 0x758a283df000
mmap(0x758a2842d000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e3000) = 0x758a2842d000
mmap(0x758a28433000, 31672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x758a28433000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/libncursesw.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=453896, ...}) = 0
mmap(NULL, 453856, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x758a281db000
mmap(0x758a281e8000, 290816, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xd000) = 0x758a281e8000
mmap(0x758a2822f000, 90112, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x54000) = 0x758a2822f000
mmap(0x758a28245000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6a000) = 0x758a28245000
close(3) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x758a281d9000
arch_prctl(ARCH_SET_FS, 0x758a281d9b80) = 0
set_tid_address(0x758a281d9e50) = 338133
set_robust_list(0x758a281d9e60, 24) = 0
rseq(0x758a281da4a0, 0x20, 0, 0x53053053) = 0
mprotect(0x758a2842d000, 16384, PROT_READ) = 0
mprotect(0x758a28245000, 16384, PROT_READ) = 0
mprotect(0x758a28487000, 12288, PROT_READ) = 0
mprotect(0x5ae513c4d000, 12288, PROT_READ) = 0
mprotect(0x758a284fd000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x758a28493000, 194599) = 0
openat(AT_FDCWD, "/dev/tty", O_RDWR|O_NONBLOCK) = 3
close(3) = 0
getrandom("\x9f\x6e\x12\xb3\x3b\xe2\x4e\x66", 8, GRND_NONBLOCK) = 8
brk(NULL) = 0x5ae528cfd000
brk(0x5ae528d1e000) = 0x5ae528d1e000
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=3055776, ...}) = 0
mmap(NULL, 3055776, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a27e00000
close(3) = 0
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=2998, ...}) = 0
read(3, "# Locale name alias data base.\n#"..., 4096) = 2998
read(3, "", 4096) = 0
close(3) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_IDENTIFICATION", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=258, ...}) = 0
mmap(NULL, 258, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a284c2000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/gconv/gconv-modules.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=27010, ...}) = 0
mmap(NULL, 27010, PROT_READ, MAP_SHARED, 3, 0) = 0x758a284bb000
close(3) = 0
futex(0x758a2843272c, FUTEX_WAKE_PRIVATE, 2147483647) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MEASUREMENT", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_MEASUREMENT", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=23, ...}) = 0
mmap(NULL, 23, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a284ba000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_TELEPHONE", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_TELEPHONE", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=47, ...}) = 0
mmap(NULL, 47, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a284b9000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_ADDRESS", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_ADDRESS", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=127, ...}) = 0
mmap(NULL, 127, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a284b8000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_NAME", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_NAME", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=62, ...}) = 0
mmap(NULL, 62, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a284b7000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_PAPER", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_PAPER", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=34, ...}) = 0
mmap(NULL, 34, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a284b6000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MESSAGES", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_MESSAGES", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=30, ...}) = 0
close(3) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_MESSAGES/SYS_LC_MESSAGES", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=48, ...}) = 0
mmap(NULL, 48, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a284b5000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_MONETARY", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_MONETARY", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=270, ...}) = 0
mmap(NULL, 270, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a284b4000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_COLLATE", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_COLLATE", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1406, ...}) = 0
mmap(NULL, 1406, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a284b3000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_TIME", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_TIME", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=3360, ...}) = 0
mmap(NULL, 3360, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a284b2000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_NUMERIC", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_NUMERIC", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=50, ...}) = 0
mmap(NULL, 50, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a284b1000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/locale/C.UTF-8/LC_CTYPE", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/locale/C.utf8/LC_CTYPE", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=360460, ...}) = 0
mmap(NULL, 360460, PROT_READ, MAP_PRIVATE, 3, 0) = 0x758a28180000
close(3) = 0
getuid() = 0
getgid() = 0
geteuid() = 0
getegid() = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
rt_sigaction(SIGCHLD, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGCHLD, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x758a282871d0}, 8) = 0
rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, 8) = 0
rt_sigaction(SIGTSTP, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTSTP, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, 8) = 0
rt_sigaction(SIGTTIN, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTTIN, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, 8) = 0
rt_sigaction(SIGTTOU, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTTOU, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=SIG_IGN, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, 8) = 0
uname({sysname="Linux", nodename="archhost", ...}) = 0
getcwd("/tmp/tmp.zGlsz5be5c", 4096) = 20
getpid() = 338133
getppid() = 338130
getpid() = 338133
getppid() = 338130
getpid() = 338133
getppid() = 338130
getpgrp() = 338130
ioctl(2, TIOCGPGRP, [338130]) = 0
rt_sigaction(SIGCHLD, {sa_handler=0x5ae513b93a60, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x758a282871d0}, 8) = 0
prlimit64(0, RLIMIT_NPROC, NULL, {rlim_cur=54025, rlim_max=54025}) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
openat(AT_FDCWD, "./sh", O_RDONLY) = 3
newfstatat(AT_FDCWD, "./sh", {st_mode=S_IFREG|0755, st_size=289, ...}, 0) = 0
ioctl(3, TCGETS, 0x7ffd50ed22c0) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR) = 0
read(3, "#!/bin/bash\n\n\n/bin/bash -c \"echo"..., 80) = 80
lseek(3, 0, SEEK_SET) = 0
prlimit64(0, RLIMIT_NOFILE, NULL, {rlim_cur=1024, rlim_max=512*1024}) = 0
fcntl(255, F_GETFD) = -1 EBADF (Bad file descriptor)
dup2(3, 255) = 255
close(3) = 0
fcntl(255, F_SETFD, FD_CLOEXEC) = 0
fcntl(255, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
fstat(255, {st_mode=S_IFREG|0755, st_size=289, ...}) = 0
lseek(255, 0, SEEK_CUR) = 0
read(255, "#!/bin/bash\n\n\n/bin/bash -c \"echo"..., 289) = 289
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT TERM CHLD], [], 8) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x758a281d9e50) = 338134
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {sa_handler=0x5ae513b961e0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, 8) = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 338134
rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=0x5ae513b961e0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, 8) = 0
ioctl(2, TIOCGWINSZ, {ws_row=78, ws_col=288, ws_xpixel=3456, ws_ypixel=2106}) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=338134, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, 0x7ffd50ed1210, WNOHANG, NULL) = -1 ECHILD (No child processes)
rt_sigreturn({mask=[]}) = 0
read(255, "", 289) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
exit_group(0) = ?
+++ exited with 0 +++
The most important part is where and how it hangs:
rt_sigaction(SIGINT, {sa_handler=0x5ae513b961e0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x758a282871d0}, 8) = 0
wait4(-1,
it hangs in this state with uncompleted line for 15 seconds. Here's the most interesting part. remember the trash line? Its three equal parts (]11;?\[6n) are being printed with equal noticeable time intervals one by one.
That's how stuff appears in a temp file:
- immediately after start file becomes:
date_before_glow: Mon Nov 11 05:19:21 MSK 2024
]10;?\[6n
- exactly after 5 second hanging file becomes:
date_before_glow: Mon Nov 11 05:25:08 MSK 2024
]10;?\[6n]11;?\[6n
- exactly after another 5 second hanging file becomes:
date_before_glow: Mon Nov 11 05:25:08 MSK 2024
]10;?\[6n]11;?\[6n]11;?\[6n
- exactly after YET ANOTHER 5 second hanging file becomes:
date_before_glow: Mon Nov 11 05:28:21 MSK 2024
]10;?\[6n]11;?\[6n]11;?\[6n
[38;5;228;48;5;63;1m[0m[38;5;228;48;5;63;1m[0m [38;5;228;48;5;63;1m [0m[38;5;228;48;5;63;1mheader[0m[38;5;228;48;5;63;1m [0m[38;5;252m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[0m
[0m [38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m
[38;5;252m[0m[38;5;252m[0m [38;5;252m1[0m[38;5;252m. [0m[38;5;252;3msomething[0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m
[38;5;252m[0m[38;5;252m[0m [38;5;252m2[0m[38;5;252m. [0m[38;5;252;3mbold[0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m[38;5;252m [0m
date_after_glow: Mon Nov 11 05:28:36 MSK 2024
Based on that, I conclude that it hangs each time AFTER it printed ]10;?\[6n. I don't know what's the f**k is going on. May be some kind of awaiting before output buffer filled, and flushing it when timeout expires? But why the f**k doesn't this shit appear in other case we run glow? π€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈ
Also interesting observation:
I'm 99.99% sure that glow uses something similar with gh-cli under the hood to beatify Markdown. I went ahead and run the same test, but with a different command: gh repo view.
Guess how many ]11;?\[6n in it's output?
- 1
Guess how long it executes? 06:30:36 -- 06:30:42 (6 sec)
- 5 (seconds) * 1 (
]11;?\[6n) + 1 (second -- overhead to make a call to github API)
I tried to decode this ANSI code using this cheatsheet and this character inspector.
In the end this seems like a command, to make some kind of cursor shift and then to request cursor position (ESC[6n).
And probably this artifitial TTY takes too long to respond and is being cutoff on timeout? π€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈ
Also I have a hypothesis about what's up with all the trash symbols being triggered by printing ]11;?\[6n -- I have no idea how ANSI works, but maybe that's the response with cursor position that was asked by ESC[6n? π€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈπ€·π»ββοΈ
Ideas?
Until the fix is made somewhere, you can just use bat
Prints more-less acceptable colored .md file.
bat --style=plain --color=always "$file"
If only there was a way to find and disable this cursor shift with following cursor position request... ππ
Would be nice if somebody from the team will help identify libraries or pieces of code playing the role here and how to disable them, so we will have a quite nice workaround ππ
Here are common libraries between GitHub CLI and Glow. I assume the stuff we're looking is inside one of them:
(click to expand)
- https://github.com/alecthomas/chroma
- https://github.com/aymanbagabas/go-osc52
- https://github.com/aymerick/douceur
- https://github.com/charmbracelet/glamour
- https://github.com/charmbracelet/lipgloss
- https://github.com/dlclark/regexp2
- https://github.com/fsnotify/fsnotify
- https://github.com/gorilla/css
- https://github.com/hashicorp/hcl
- https://github.com/inconshreveable/mousetrap
- https://github.com/lucasb-eyer/go-colorful
- https://github.com/magiconair/properties
- https://github.com/mattn/go-isatty
- https://github.com/mattn/go-runewidth
- https://github.com/microcosm-cc/bluemonday
- https://github.com/mitchellh/go-homedir
- https://github.com/mitchellh/mapstructure
- https://github.com/muesli/reflow
- https://github.com/muesli/termenv
- https://github.com/pelletier/go-toml
- https://github.com/rivo/uniseg
- https://github.com/spf13/afero
- https://github.com/spf13/cast
- https://github.com/spf13/cobra
- https://github.com/spf13/pflag
- https://github.com/spf13/viper
- https://github.com/subosito/gotenv
- https://github.com/yuin/goldmark
- https://github.com/yuin/goldmark-emoji
- https://golang.org/x/exp
- https://golang.org/x/net
- https://golang.org/x/sync
- https://golang.org/x/sys
- https://golang.org/x/term
- https://golang.org/x/text
- https://gopkg.in/ini.v1
- https://gopkg.in/yaml.v3
I assume (honestly nothing more that intuition) it's either muesli/reflow or muesli/termenv because the same issue (https://github.com/muesli/termenv/issues/136) appears to be there.
My findings didn't end there.
I tried to create new theme based on https://github.com/charmbracelet/glamour/blob/master/styles/dark.json and run it with new theme. I changed all margin fields from 2 to 0.
Timing improved. Now it runs 5 seconds faster.
Before
time /bin/bash -c "echo date_before_script: \$(/sbin/date); /sbin/script -q -c 'echo date_before_glow: \$(/sbin/date); SHLVL=1 COLUMNS=180 LINES=49 /sbin/glow README.md; echo date_after_glow: \$(/sbin/date)' > temp; /sbin/cat temp; echo date_after_script: \$(/sbin/date)" > temp2
real 0m15.059s
user 0m0.021s
sys 0m0.015s
cat temp2 | sed '3d'
date_before_script: Sat Nov 16 00:06:52 MSK 2024
date_before_glow: Sat Nov 16 00:06:52 MSK 2024
header
1. something
2. bold
date_after_glow: Sat Nov 16 00:07:07 MSK 2024
date_after_script: Sat Nov 16 00:07:07 MSK 2024
3rd line:
]10;?\[6n]11;?\[6n]11;?\[6n
After
time /bin/bash -c "echo date_before_script: \$(/sbin/date); /sbin/script -q -c 'echo date_before_glow: \$(/sbin/date); SHLVL=1 COLUMNS=180 LINES=49 /sbin/glow -s ./mystyle.json README.md; echo date_after_glow: \$(/sbin/date)' > temp; /sbin/cat temp; echo date_after_script: \$(/sbin/date)" > temp2
real 0m10.054s
user 0m0.020s
sys 0m0.015s
cat temp2 | sed '3d'
date_before_script: Sat Nov 16 00:10:52 MSK 2024
date_before_glow: Sat Nov 16 00:10:52 MSK 2024
header
1. something
2. bold
date_after_glow: Sat Nov 16 00:11:02 MSK 2024
date_after_script: Sat Nov 16 00:11:02 MSK 2024
3rd line:
]10;?\[6n]11;?\[6n
Edited theme:
{
"document": {
"block_prefix": "\n",
"block_suffix": "\n",
"color": "252",
"margin": 0
},
"block_quote": {
"indent": 1,
"indent_token": "β "
},
"paragraph": {},
"list": {
"level_indent": 2
},
"heading": {
"block_suffix": "\n",
"color": "39",
"bold": true
},
"h1": {
"prefix": " ",
"suffix": " ",
"color": "228",
"background_color": "63",
"bold": true
},
"h2": {
"prefix": "## "
},
"h3": {
"prefix": "### "
},
"h4": {
"prefix": "#### "
},
"h5": {
"prefix": "##### "
},
"h6": {
"prefix": "###### ",
"color": "35",
"bold": false
},
"text": {},
"strikethrough": {
"crossed_out": true
},
"emph": {
"italic": true
},
"strong": {
"bold": true
},
"hr": {
"color": "240",
"format": "\n--------\n"
},
"item": {
"block_prefix": "β’ "
},
"enumeration": {
"block_prefix": ". "
},
"task": {
"ticked": "[β] ",
"unticked": "[ ] "
},
"link": {
"color": "30",
"underline": true
},
"link_text": {
"color": "35",
"bold": true
},
"image": {
"color": "212",
"underline": true
},
"image_text": {
"color": "243",
"format": "Image: {{.text}} β"
},
"code": {
"prefix": " ",
"suffix": " ",
"color": "203",
"background_color": "236"
},
"code_block": {
"color": "244",
"margin": 0,
"chroma": {
"text": {
"color": "#C4C4C4"
},
"error": {
"color": "#F1F1F1",
"background_color": "#F05B5B"
},
"comment": {
"color": "#676767"
},
"comment_preproc": {
"color": "#FF875F"
},
"keyword": {
"color": "#00AAFF"
},
"keyword_reserved": {
"color": "#FF5FD2"
},
"keyword_namespace": {
"color": "#FF5F87"
},
"keyword_type": {
"color": "#6E6ED8"
},
"operator": {
"color": "#EF8080"
},
"punctuation": {
"color": "#E8E8A8"
},
"name": {
"color": "#C4C4C4"
},
"name_builtin": {
"color": "#FF8EC7"
},
"name_tag": {
"color": "#B083EA"
},
"name_attribute": {
"color": "#7A7AE6"
},
"name_class": {
"color": "#F1F1F1",
"underline": true,
"bold": true
},
"name_constant": {},
"name_decorator": {
"color": "#FFFF87"
},
"name_exception": {},
"name_function": {
"color": "#00D787"
},
"name_other": {},
"literal": {},
"literal_number": {
"color": "#6EEFC0"
},
"literal_date": {},
"literal_string": {
"color": "#C69669"
},
"literal_string_escape": {
"color": "#AFFFD7"
},
"generic_deleted": {
"color": "#FD5B5B"
},
"generic_emph": {
"italic": true
},
"generic_inserted": {
"color": "#00D787"
},
"generic_strong": {
"bold": true
},
"generic_subheading": {
"color": "#777777"
},
"background": {
"background_color": "#373737"
}
}
},
"table": {},
"definition_list": {},
"definition_term": {},
"definition_description": {
"block_prefix": "\nπ Ά "
},
"html_block": {},
"html_span": {}
}
It is definitely faster and definitely because of reducing amount of escape sequences which are being attempted to be printed by glow.
Next I'm gonna look for how margin is used and can we remove 2 ANSI sequences left
Came here via the other thread, after gradually realizing my intermittent problem with ANSI garble and big slow downs was coming from glow and maybe related to stuff like CLICOLOR_FORCE / COLORTERM, pty, and pipes. I had different scripts using a docker-glow and a snap-glow at different times in different places, basically the same in terms of output though. This comment https://github.com/charmbracelet/glow/issues/440#issuecomment-2307992634 got me to check the versions of each.
I can confirm downgrading just fixes this, and https://hub.docker.com/layers/charmcli/glow/v1.5.1 works for my use-case as expected. No breaking changes by using a lower version everywhere, but my usage is noninteractive, not passing any flags, and not using external config.
I also had to downgrade to version 1.5.1. It works well.
Hi guys, out of curiosity but it there any news on this? Has an upstream issue been opened? Thanks!