std.Progress: tree form and line truncation
As described in the issue (closes #14946; potentially resolves #13440), this PR converts the progress bar into a tree form and resolve the issue of smaller-sized terminals, where lines wrap automatically.
I've tested the changes both on Linux and Windows (it would make sense to test against additional environments) with mixed benchmark results, the difference when embeded into applications is only marginal. Nonetheless, it would be a good idea to consider other implementations as well for an improved performance, but I assume this first approach isn't bad, since I've also tried using linked lists which performed worse.
Just like before there are zero dynamic allocations, but since I am not the best at multi-threading it might also make sense for someone that understands atomic handling of data to look over the PR.
Merging this PR wouldn't be seamless because the frontend is still on par with the old design (ex. unnamed nodes).
There should be no breaking API changes outside the scope of the module itself, apart from a changed behavior.
I'd be glad to continue on helping and make the changes necessary to satisfy the needs and integrate it into the other existing components.
I am not entirely satisfied with the implementation. To be more precise, I have performance and design concerns, despite the addressed features inevitably increasing complexity and reducing performance.
Additionally, the whole max-width trimming methods are somewhat hard to read, and maybe storing the buffer differently, say using a nested list, could reduce some of that complexity.
Not sure how I could improve upon these changes: maybe someone else has got some ideas? Though, it could also be that I am being critical of my work and the suggested changes are mostly fine.
Thank you for approving the changes.
I will try to come up with a more elegant way of storing the buffer - probably as a nested array, since this allows for a concise separation of each row. At the moment, the code keeps track of each and every LF in a "flattened" buffer. Nesting should improve performance and maintainability.
Also, I took note of the failing CI checks and will address the issue. The checks fail due to code being moved away from a docgen function in favor of refactoring into doctest. I did not take note of the changes and assumed the function was removed altogether, my bad.
I am not entirely sure what made the CI fail before, but it seems to be building fine on my machine, so I hope the issues are resolved now. In addition, I added support for the old progress bar in the hopes of avoiding a messy output.
By the way I did check this branch out locally and play with it, and I couldn't get it to work.
I ran zig build test-behavior and observed no difference between master branch and this branch.
By the way I did check this branch out locally and play with it, and I couldn't get it to work.
I ran
zig build test-behaviorand observed no difference between master branch and this branch.
This is because the progress bar implements a mode where it mimics the old design. You can disable it by setting emulate_one_line_bar to false.
It is disabled by default, but I enabled it for all files since I did not want to mess with CI logs during the transitioning phases.
Moreover, I originally implemented it because on "dumb" terminals the single-line progress bar looks arguably better.
I resolved the Windows-related issues now.
The other additional commit should not cause any issues whatsoever.
Therefore, Linux should continue to pass absolutely fine and it would be cool if we could run the Windows CI again.
What's the point of this change if you disable it everywhere?
What's the point of this change if you disable it everywhere?
The logging by the CI does not support ansi escape sequences and is therefore considered a "dumb" terminal. In such case, a LF is written instead of ansi esc seqs that clear the previous output.
The issue is that when you are printing multiple lines, not clearing the previous output this gets rather hard to interpret, as compared to the current single-line progress bar.
A suggested middle ground would be to add checks outside of std.Progress so that on "dumb" terminals the progress bar automatically defaults to the old style.
The current state of the PR solely suggests an extended version that supports multi-line progress bars, allowing for an easy migration when and where a multi-line progress bar is desired.
In addition, this PR adds automatic truncation to the terminal width which should already be noticible.
Let me clarify even further. The current state of main.zig (, etc.) is designed for the old behavior of the progress bar. Of course, the API stayed the same and is backwards compatible but in many places the new progress bar seems out of place.
Since the build system is currently being reworked towards something that is a good fit for the new design, I did not bother to bring main.zig (, etc.) on par with the changes.
You can test it for yourself. The compilation output of the CI workflow looks bad with emulate_one_line_bar set to false. In my opinion, this isn't because std.Progress isn't capable of beautiful progress outputs but rather because the frontend doesn't yet make use of the features introduced.
I don't want to suggest changes that make it so contributers, trying to investigate why the CI failed for their PR need to scroll two miles, because the CLI isn't following the new behavior of the progress bar.
If I've got time this weekend, I will take try to integrate the reworked progress bar.
Closing in favor of #20059.