Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When output is redirected, terminal capabilities are ignored and colors are illegible #654

Open
AndydeCleyre opened this issue Oct 17, 2024 · 11 comments

Comments

@AndydeCleyre
Copy link

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

  1. Given a markdown README.md . . .
  2. Run:
$ CLICOLOR_FORCE=1 glow --style dark README.md | head

Source Code

Sample README

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

image

Additional context

See discussion at #440 (comment)

@meowgorithm
Copy link
Member

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).

image

@folliehiyuki
Copy link

folliehiyuki commented Oct 18, 2024

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.

@meowgorithm
Copy link
Member

meowgorithm commented Oct 18, 2024

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

@Chaitanyabsprip
Copy link

instead of the --force-color-profile flag, just use whatever value COLORTERM env var contains

@meowgorithm
Copy link
Member

That’s fine by me, but termenv will need to be corrected upstream.

@nikelborm
Copy link

#21 (comment)

script -q -c "glow README.md" | tail -n +2

@nikelborm
Copy link

nikelborm commented Nov 11, 2024

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: #21 (comment))

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:

  1. immediately after start file becomes:
date_before_glow: Mon Nov 11 05:19:21 MSK 2024
�]10;?�\�[6n
  1. exactly after 5 second hanging file becomes:
date_before_glow: Mon Nov 11 05:25:08 MSK 2024
�]10;?�\�[6n�]11;?�\�[6n
  1. 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
  1. 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?

@nikelborm
Copy link

Until the fix is made somewhere, you can just use bat
Prints more-less acceptable colored .md file.

bat --style=plain --color=always "$file"

@nikelborm
Copy link

nikelborm commented Nov 11, 2024

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)

I assume (honestly nothing more that intuition) it's either muesli/reflow or muesli/termenv because the same issue (muesli/termenv#136) appears to be there.

@nikelborm
Copy link

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.

@nikelborm
Copy link

Next I'm gonna look for how margin is used and can we remove 2 ANSI sequences left

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants