-
Notifications
You must be signed in to change notification settings - Fork 324
v2: viewport: refactor softwrap; improve perf; various bug fixes #823
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
base: v2-exp
Are you sure you want to change the base?
v2: viewport: refactor softwrap; improve perf; various bug fixes #823
Conversation
Signed-off-by: Liam Stanley <liam@liam.sh>
acfa031
to
35ab0d6
Compare
Signed-off-by: Liam Stanley <liam@liam.sh>
This PR is so awesome. @lrstanley, it looks like the golden files need to be updated. Do you mind doing that? |
Thanks, didn't catch the table tests failing. Looking at those tests, many don't have height or width set, and then take an immediate snapshot to render the table. What's the expected outcome in that situation? Right now with this PR, it's expected that viewport won't render anything until width/height are set, which means many of those tests effectively render nothing because they are missing width and/or height. Should the table tests always have |
PR looks great! Thanks @lrstanley 🙏🏻 Regarding the failed tests, I think we could probably set a width and height for all the tests 🤔 ...Or, if width/height isn't set, render everything - not sure if this is the best behavior though |
Signed-off-by: Liam Stanley <liam@liam.sh>
I've done this for now, mostly just matching up the explicit dimensions to how it was previously rendered to reduce the diffs, though:
Right now, table has a built-in default height of I think that viewport should not have a "free form" mode (width or height), because I think it defeats the purpose of a viewport in the first place (someone is using it because of the size constraints, be it scrolling or wrapping, so they should know the constraints), and makes wrapping (which is new to v2), impossible to calculate correctly. Thoughts? |
Signed-off-by: Liam Stanley <liam@liam.sh>
@aymanbagabas and @caarlos0: are we good to merge this one? |
Describe your changes
GetVisibleLines()
returning more results than is rendered in the viewport.softWrap
slice tomaxHeight
, and accounting for the correct virtual offset (see below).visibleLines()
now also returns exactly what is needed for visibility, where it was returning ALL lines after the visible real-index.GetTotalLines()
not returning the correct wrapped results withSoftWrap
.float64
+math.Ceil
.SoftWrap
is enabled, which caused lines that are exactly the width of the viewport to add an additional empty line to the output.ansi.Cut
at the exact length returns an empty string as the remaining, which wasn't being accounted for.SoftWrap
and non-SoftWrap
modes.SoftWrap
is enabled, so it scrolls through the wrapped lines, rather than scrolling only "real" lines, which previously felt more jagged.1
height tall.SoftWrap
'd line spans greater than the entire height of the viewport, where softwrapping would previously not work correctly/cut off lines.-1
values)max()
in a few places.SetContentLines()
didn't do CRLF normalization (even though it technically allows newlines in the provided string slice).SetContentLines()
cause total and visible line calculations to be incorrect.Model.maxWidth()
and also inModel.calculateLines()
, resulting in slightly off visible line calculations.LeftGutterFunc
that the resulting width of the gutter must be stable, as this is what the original, and updated code expects when calculating visible/total height (both in non-softwrapping and when usingSoftWrap
).Performance
Also took a little bit of time to improve performance, given viewport is commonly used to house other components, and performance hits here can affect other core parts of folks apps, especially if they are actively scrolling. There were quite a few inefficient allocations, re-invocations of heavy methods in multiple places, as well as re-processing and re-stitching of data multiple times. The changes made should have little to no readability overhead, but result in the following perf wins (tl;dr: 35% less CPU usage, 38% less memory usage, and 38% less allocations on average, with more/less depending on if
SoftWrap
is enabled or not. upwards of 55%, 58%, and 51% respectively depending on the usecase):Related issue/discussions
Checklist before requesting a review
CONTRIBUTING.md
This was one of the example usecases that when tested with the current v2-exp HEAD, has all sorts of rendering issues, and visible/total line calculation issues:
Reviewer Notes
Currently, with soft wrapping, if you have a lot of wrapped lines (more lines added virtually, than your viewport height, if you resize the window larger, it can easily leave the yoffset in a state where it's beyond the visible lines completely. Should we always check
Model.PastBottom()
inside ofModel.SetWidth()
andModel.SetHeight()
? Feel like that's a sane/reasonable default, as I can't imagine someone not wanting it.