From 0aa351443f4331b56f2d69e07182cf06de858b85 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sat, 24 Aug 2024 10:47:25 +0200 Subject: [PATCH 1/2] Bump gocui --- go.mod | 2 +- go.sum | 4 +- vendor/github.com/jesseduffield/gocui/view.go | 61 +++++++++++-------- vendor/modules.txt | 2 +- 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index 73a312f99..c0a6b36de 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/integrii/flaggy v1.4.0 github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d - github.com/jesseduffield/gocui v0.3.1-0.20240824083442-15b7fbca7ae9 + github.com/jesseduffield/gocui v0.3.1-0.20240824084618-5083ac1413f5 github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e diff --git a/go.sum b/go.sum index caeb5acf7..65cbc2e6e 100644 --- a/go.sum +++ b/go.sum @@ -188,8 +188,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk= github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE= github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o= -github.com/jesseduffield/gocui v0.3.1-0.20240824083442-15b7fbca7ae9 h1:1muwCO0cmCGHpOvNz1qTOrCFPECnBAV87yDE9Fgwy6U= -github.com/jesseduffield/gocui v0.3.1-0.20240824083442-15b7fbca7ae9/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8= +github.com/jesseduffield/gocui v0.3.1-0.20240824084618-5083ac1413f5 h1:o1UykbP+XdUYrYooTWx2K4emyE1ke6spIfU7aVd5CAc= +github.com/jesseduffield/gocui v0.3.1-0.20240824084618-5083ac1413f5/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8= github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0= github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo= github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY= diff --git a/vendor/github.com/jesseduffield/gocui/view.go b/vendor/github.com/jesseduffield/gocui/view.go index 0752a5e9c..4dcadd67e 100644 --- a/vendor/github.com/jesseduffield/gocui/view.go +++ b/vendor/github.com/jesseduffield/gocui/view.go @@ -1095,34 +1095,8 @@ func (v *View) draw() error { } v.ox = 0 } - if v.tainted { - lineIdx := 0 - lines := v.lines - if v.HasLoader { - lines = v.loaderLines() - } - for i, line := range lines { - wrap := 0 - if v.Wrap { - wrap = maxX - } - ls := lineWrap(line, wrap) - for j := range ls { - vline := viewLine{linesX: j, linesY: i, line: ls[j]} - - if lineIdx > len(v.viewLines)-1 { - v.viewLines = append(v.viewLines, vline) - } else { - v.viewLines[lineIdx] = vline - } - lineIdx++ - } - } - if !v.HasLoader { - v.tainted = false - } - } + v.refreshViewLinesIfNeeded() visibleViewLinesHeight := v.viewLineLengthIgnoringTrailingBlankLines() if v.Autoscroll && visibleViewLinesHeight > maxY { @@ -1207,6 +1181,38 @@ func (v *View) draw() error { return nil } +func (v *View) refreshViewLinesIfNeeded() { + if v.tainted { + maxX := v.Width() + lineIdx := 0 + lines := v.lines + if v.HasLoader { + lines = v.loaderLines() + } + for i, line := range lines { + wrap := 0 + if v.Wrap { + wrap = maxX + } + + ls := lineWrap(line, wrap) + for j := range ls { + vline := viewLine{linesX: j, linesY: i, line: ls[j]} + + if lineIdx > len(v.viewLines)-1 { + v.viewLines = append(v.viewLines, vline) + } else { + v.viewLines[lineIdx] = vline + } + lineIdx++ + } + } + if !v.HasLoader { + v.tainted = false + } + } +} + // if autoscroll is enabled but we only have a single row of cells shown to the // user, we don't want to scroll to the final line if it contains no text. So // this tells us the view lines height when we ignore any trailing blank lines @@ -1310,6 +1316,7 @@ func (v *View) LinesHeight() int { // ViewLinesHeight is the count of view lines (i.e. lines including wrapping) func (v *View) ViewLinesHeight() int { + v.refreshViewLinesIfNeeded() return len(v.viewLines) } diff --git a/vendor/modules.txt b/vendor/modules.txt index e1a96bb7b..6c6035f22 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -172,7 +172,7 @@ github.com/jesseduffield/go-git/v5/utils/merkletrie/filesystem github.com/jesseduffield/go-git/v5/utils/merkletrie/index github.com/jesseduffield/go-git/v5/utils/merkletrie/internal/frame github.com/jesseduffield/go-git/v5/utils/merkletrie/noder -# github.com/jesseduffield/gocui v0.3.1-0.20240824083442-15b7fbca7ae9 +# github.com/jesseduffield/gocui v0.3.1-0.20240824084618-5083ac1413f5 ## explicit; go 1.12 github.com/jesseduffield/gocui # github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 From 6114f69ee5ef38d0adac4a0d2fc1294e7ec19083 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 18 Aug 2024 20:51:38 +0200 Subject: [PATCH 2/2] Scroll views up if needed to show all their content There are many situations where this can arise. Some examples are: - the terminal window is small, and you are showing a view that shows more content than fits into the view port, and the view is scrolled all the way down; now you resize the terminal window to a taller size. Previously, the scroll position of the view would stay the same, so it would add blank space at the bottom; now it will scroll to fill that blank space with content - expandFocusedSidePanel is on, you go to the bottom of a list view, now switch to a different panel, then scroll that (now unfocused) panel all the way down with the scroll wheel; now you focus that panel again. It becomes larger because of the accordion behavior, but would show blank space at the bottom. And probably others that I can't remember right now. I only remember that I always found it confusing to look at a view that had blank space at the bottom even though it had more content to scroll into view. --- pkg/gui/context/base_context.go | 4 ++++ pkg/gui/context/list_context_trait.go | 8 ++++++++ pkg/gui/layout.go | 13 +++++++++++++ pkg/gui/types/context.go | 3 +++ 4 files changed, 28 insertions(+) diff --git a/pkg/gui/context/base_context.go b/pkg/gui/context/base_context.go index ca04a2fa9..2fd37bb9a 100644 --- a/pkg/gui/context/base_context.go +++ b/pkg/gui/context/base_context.go @@ -212,3 +212,7 @@ func (self *BaseContext) NeedsRerenderOnHeightChange() bool { func (self *BaseContext) Title() string { return "" } + +func (self *BaseContext) TotalContentHeight() int { + return self.view.ViewLinesHeight() +} diff --git a/pkg/gui/context/list_context_trait.go b/pkg/gui/context/list_context_trait.go index 773f946a9..bce3ae344 100644 --- a/pkg/gui/context/list_context_trait.go +++ b/pkg/gui/context/list_context_trait.go @@ -140,3 +140,11 @@ func (self *ListContextTrait) RangeSelectEnabled() bool { func (self *ListContextTrait) RenderOnlyVisibleLines() bool { return self.renderOnlyVisibleLines } + +func (self *ListContextTrait) TotalContentHeight() int { + result := self.list.Len() + if self.getNonModelItems != nil { + result += len(self.getNonModelItems()) + } + return result +} diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index 62c2233dd..03cd07b60 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -73,6 +73,19 @@ func (gui *Gui) layout(g *gocui.Gui) error { } mustRerender := false + newHeight := dimensionsObj.Y1 - dimensionsObj.Y0 + 2*frameOffset + maxOriginY := context.TotalContentHeight() + if !view.CanScrollPastBottom { + maxOriginY -= newHeight - 1 + } + if oldOriginY := view.OriginY(); oldOriginY > maxOriginY { + view.ScrollUp(oldOriginY - maxOriginY) + // the view might not have scrolled actually (if it was at the limit + // already), so we need to check if it did + if oldOriginY != view.OriginY() && context.NeedsRerenderOnHeightChange() { + mustRerender = true + } + } if context.NeedsRerenderOnWidthChange() == types.NEEDS_RERENDER_ON_WIDTH_CHANGE_WHEN_WIDTH_CHANGES { // view.Width() returns the width -1 for some reason oldWidth := view.Width() + 1 diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go index 2948f2eda..f48a6b595 100644 --- a/pkg/gui/types/context.go +++ b/pkg/gui/types/context.go @@ -71,6 +71,9 @@ type IBaseContext interface { // determined independently. HasControlledBounds() bool + // the total height of the content that the view is currently showing + TotalContentHeight() int + // to what extent the view needs to be rerendered when its width changes NeedsRerenderOnWidthChange() NeedsRerenderOnWidthChangeLevel