Open nektro opened 1 year ago
This is a known limitation of the way std.Progress
works right now. Would be nice if there were a way to solve this.
It looks like the problem comes from output_buffer
having fixed length. For it to work with the terminal width, it would have to be dynamically allocated. (Or maybe just pick a large upperbound, like 500?)
As a guy who has been learning too much about escape codes recently 😉 I took a look and would suggest perhaps a different approach. I just Iike really quickly looked at how Progress was implemented, I didn’t see how Progress was being used so this whole response might be dumb.
Right now, std.Progress
uses ESC[nD
to move the cursor back n
so it needs to keep track of columns. That’s fine, totally workable. But another approach would be to call ESC[6n
at the start of a refresh to query cursor position, which will return the <row, col>. Then just output the whole progress no matter the length and let the terminal wrap it if it has to (auto wrap). Then for the next call use ESC[H
to set the cursor position back to an absolute row, col that was queried earlier.
You can have a call to throw away the prev position if you want to preserve it (i.e. you outputted test failure information you want to preserve and not overwrite since the last progress call).
Another approach is to query the terminal size, but this requires making a ioctl call which you may or may not want to deal with in the std.Progress implementation. Another hack that totally works is to use ESC[H
with an absurdly large number (say, 10000, 10000) which sets the cursor position. The terminal emulator must bound the cursor position by the terminal size so if you do that then call ESC[6n
it’ll report the size in grid cells.
Each of these might require small public API changes to Progress
though, but I’m very sure this problem can be solved without heap allocations.
how feasible would a loop like below work for std.Progress?
\n
ESC[1A
ESC[0K
That approach would require you keep track of terminal width. All the line-oriented escape codes treat a line as a visible line (or physical line). It doesn’t unwrap soft-wrapped stuff. So if a terminal soft wraps, that’s 2 lines and you’ll start getting artifacts unless you’re careful to never wrap.
I've already gone through this in my PRs:
The status is that there's some weird issue going on that caused my main PR to be reverted
That "weird issue" is very likely coming from this function https://github.com/ziglang/zig/pull/12079/files#diff-f05e9ed61d2716c50e09b00c1881f44cdb2a85107d1b5c95231f80e489ea265eR225 which uses ESC[6n that @mitchellh mentioned. It messes with termios which would be great if we could avoid it but there just doesn't seem to be a way to avoid it.
Querying the terminal window size is pretty easy and much less troublesome: https://github.com/ziglang/zig/pull/12079/files#diff-f05e9ed61d2716c50e09b00c1881f44cdb2a85107d1b5c95231f80e489ea265eR205
@nektro doesn't work if you have multiple std.Progress
instances from different processes (they can't communicate with each other) so if you do ESC[0K
you might clear the progress of some other process behind it (see https://github.com/ziglang/zig/pull/13148#issuecomment-1285502143)
Here's how my PR determines the optimal width to use for the terminal when a std.Progress
is created: https://github.com/ziglang/zig/pull/12079/files#diff-f05e9ed61d2716c50e09b00c1881f44cdb2a85107d1b5c95231f80e489ea265eR179-R181
It gets the terminal width and then the position of the cursor in the terminal. Then we just subtract the position from the terminal width so that we account for text printed before us.
@r00ster91 then you could make it so they have a reference to a parent that they call to print before printing their own status
That would involve communication between entirely separate processes right? For example if you have multiple separate zig
invocations. I think in that case the solution of getting the terminal cursor's x-axis is pretty simple, but maybe there is a simpler or more reliable solution? If we could communicate with std.Progress
s of other system processes, we can solve it that way too. Not sure how we could obtain such a reference to a parent.
Zig Version
0.11.0-dev.52+42755a194
Steps to Reproduce and Observed Behavior
Expected Behavior
using the full terminal width