Open AndydeCleyre opened 4 weeks ago
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
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:
date_before_glow: Mon Nov 11 05:19:21 MSK 2024
]10;?\[6n
date_before_glow: Mon Nov 11 05:25:08 MSK 2024
]10;?\[6n]11;?\[6n
date_before_glow: Mon Nov 11 05:25:08 MSK 2024
]10;?\[6n]11;?\[6n]11;?\[6n
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](https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797) and this [character inspector](https://apps.timwhitlock.info/unicode/inspect?s=%1B%5D11%3B%3F%1B%5C%1B%5B6n).
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:
Describe the bug When output is redirected/piped, terminal capabilities are ignored and colors are illegible.
Setup
To Reproduce
README.md
. . .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
Additional context
See discussion at https://github.com/charmbracelet/glow/issues/440#issuecomment-2358748595