summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2022-04-16 15:27:56 +1000
committerJesse Duffield <jessedduffield@gmail.com>2022-04-16 17:29:17 +1000
commite68093fe9974296fe5afb22ec8e0adb1eb2f4316 (patch)
tree040dbfdb4dc438271d9f3febae410d25698f1a38
parentb838b74801102b27782cc20c7396279630e77fba (diff)
add scrollbars
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--pkg/gui/context/view_trait.go26
-rw-r--r--pkg/gui/context/viewport_list_context_trait.go4
-rw-r--r--pkg/gui/controllers/list_controller.go38
-rw-r--r--pkg/gui/extras_panel.go8
-rw-r--r--pkg/gui/global_handlers.go74
-rw-r--r--pkg/gui/gui.go2
-rw-r--r--pkg/gui/tasks_adapter.go12
-rw-r--r--pkg/gui/types/context.go2
-rw-r--r--vendor/github.com/jesseduffield/gocui/gui.go110
-rw-r--r--vendor/github.com/jesseduffield/gocui/scrollbar.go33
-rw-r--r--vendor/github.com/jesseduffield/gocui/view.go69
-rw-r--r--vendor/modules.txt2
14 files changed, 270 insertions, 116 deletions
diff --git a/go.mod b/go.mod
index f53f2645e..73124a6d1 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.20201006095850-341962be15a4
- github.com/jesseduffield/gocui v0.3.1-0.20220415005542-2eb424ce3d0a
+ github.com/jesseduffield/gocui v0.3.1-0.20220416053910-5b19e175bc67
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e
github.com/jesseduffield/yaml v2.1.0+incompatible
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0
diff --git a/go.sum b/go.sum
index 7dbd3f1b8..0a5b19b6c 100644
--- a/go.sum
+++ b/go.sum
@@ -70,8 +70,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.20201006095850-341962be15a4 h1:GOQrmaE8i+KEdB8NzAegKYd4tPn/inM0I1uo0NXFerg=
github.com/jesseduffield/go-git/v5 v5.1.2-0.20201006095850-341962be15a4/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
-github.com/jesseduffield/gocui v0.3.1-0.20220415005542-2eb424ce3d0a h1:Fd8B7eZJfwK0cFzqz2gEFLEDiY0iwJTm6oBbPRHONxA=
-github.com/jesseduffield/gocui v0.3.1-0.20220415005542-2eb424ce3d0a/go.mod h1:znJuCDnF2Ph40YZSlBwdX/4GEofnIoWLGdT4mK5zRAU=
+github.com/jesseduffield/gocui v0.3.1-0.20220416053910-5b19e175bc67 h1:6NIOoR4LMuNEkP6e9P6GVZkzgYZ7rqpfM+LieKqubnA=
+github.com/jesseduffield/gocui v0.3.1-0.20220416053910-5b19e175bc67/go.mod h1:znJuCDnF2Ph40YZSlBwdX/4GEofnIoWLGdT4mK5zRAU=
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e h1:uw/oo+kg7t/oeMs6sqlAwr85ND/9cpO3up3VxphxY0U=
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e/go.mod h1:u60qdFGXRd36jyEXxetz0vQceQIxzI13lIo3EFUDf4I=
github.com/jesseduffield/yaml v2.1.0+incompatible h1:HWQJ1gIv2zHKbDYNp0Jwjlj24K8aqpFHnMCynY1EpmE=
diff --git a/pkg/gui/context/view_trait.go b/pkg/gui/context/view_trait.go
index 4c0cd9e05..8f2a2e99e 100644
--- a/pkg/gui/context/view_trait.go
+++ b/pkg/gui/context/view_trait.go
@@ -3,7 +3,6 @@ package context
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
- "github.com/jesseduffield/lazygit/pkg/utils"
)
const HORIZONTAL_SCROLL_FACTOR = 3
@@ -43,20 +42,31 @@ func (self *ViewTrait) SetOriginX(value int) {
_ = self.view.SetOriginX(value)
}
-// tells us the bounds of line indexes shown in the view currently
+// tells us the start of line indexes shown in the view currently as well as the capacity of lines shown in the viewport.
func (self *ViewTrait) ViewPortYBounds() (int, int) {
- _, min := self.view.Origin()
- max := self.view.InnerHeight() + 1
- return min, max
+ _, start := self.view.Origin()
+ length := self.view.InnerHeight() + 1
+ return start, length
}
func (self *ViewTrait) ScrollLeft() {
- newOriginX := utils.Max(self.view.OriginX()-self.view.InnerWidth()/HORIZONTAL_SCROLL_FACTOR, 0)
- _ = self.view.SetOriginX(newOriginX)
+ self.view.ScrollLeft(self.horizontalScrollAmount())
}
func (self *ViewTrait) ScrollRight() {
- _ = self.view.SetOriginX(self.view.OriginX() + self.view.InnerWidth()/HORIZONTAL_SCROLL_FACTOR)
+ self.view.ScrollRight(self.horizontalScrollAmount())
+}
+
+func (self *ViewTrait) horizontalScrollAmount() int {
+ return self.view.InnerWidth() / HORIZONTAL_SCROLL_FACTOR
+}
+
+func (self *ViewTrait) ScrollUp() {
+ self.view.ScrollUp(1)
+}
+
+func (self *ViewTrait) ScrollDown() {
+ self.view.ScrollDown(1)
}
// this returns the amount we'll scroll if we want to scroll by a page.
diff --git a/pkg/gui/context/viewport_list_context_trait.go b/pkg/gui/context/viewport_list_context_trait.go
index ab9b04fb8..b89dea832 100644
--- a/pkg/gui/context/viewport_list_context_trait.go
+++ b/pkg/gui/context/viewport_list_context_trait.go
@@ -15,8 +15,8 @@ type ViewportListContextTrait struct {
func (self *ViewportListContextTrait) FocusLine() {
self.ListContextTrait.FocusLine()
- min, max := self.GetViewTrait().ViewPortYBounds()
- displayStrings := self.ListContextTrait.getDisplayStrings(min, max)
+ startIdx, length := self.GetViewTrait().ViewPortYBounds()
+ displayStrings := self.ListContextTrait.getDisplayStrings(startIdx, length)
content := utils.RenderDisplayStrings(displayStrings)
self.GetViewTrait().SetViewPortContent(content)
}
diff --git a/pkg/gui/controllers/list_controller.go b/pkg/gui/controllers/list_controller.go
index 0f64228bb..7da05710e 100644
--- a/pkg/gui/controllers/list_controller.go
+++ b/pkg/gui/controllers/list_controller.go
@@ -43,14 +43,42 @@ func (self *ListController) HandleNextLine() error {
}
func (self *ListController) HandleScrollLeft() error {
- return self.scroll(self.context.GetViewTrait().ScrollLeft)
+ return self.scrollHorizontal(self.context.GetViewTrait().ScrollLeft)
}
func (self *ListController) HandleScrollRight() error {
- return self.scroll(self.context.GetViewTrait().ScrollRight)
+ return self.scrollHorizontal(self.context.GetViewTrait().ScrollRight)
}
-func (self *ListController) scroll(scrollFunc func()) error {
+func (self *ListController) HandleScrollUp() error {
+ self.context.GetViewTrait().ScrollUp()
+
+ // we only need to do a line change if our line has been pushed out of the viewport, because
+ // at the moment much logic depends on the selected line always being visible
+ if !self.isSelectedLineInViewPort() {
+ return self.handleLineChange(-1)
+ }
+
+ return nil
+}
+
+func (self *ListController) HandleScrollDown() error {
+ self.context.GetViewTrait().ScrollDown()
+
+ if !self.isSelectedLineInViewPort() {
+ return self.handleLineChange(1)
+ }
+
+ return nil
+}
+
+func (self *ListController) isSelectedLineInViewPort() bool {
+ selectedLineIdx := self.context.GetList().GetSelectedLineIdx()
+ startIdx, length := self.context.GetViewTrait().ViewPortYBounds()
+ return selectedLineIdx >= startIdx && selectedLineIdx < startIdx+length
+}
+
+func (self *ListController) scrollHorizontal(scrollFunc func()) error {
scrollFunc()
return self.context.HandleFocus()
@@ -157,7 +185,7 @@ func (self *ListController) GetMouseKeybindings(opts types.KeybindingsOpts) []*g
ViewName: self.context.GetViewName(),
ToContext: string(self.context.GetKey()),
Key: gocui.MouseWheelUp,
- Handler: func(gocui.ViewMouseBindingOpts) error { return self.HandlePrevLine() },
+ Handler: func(gocui.ViewMouseBindingOpts) error { return self.HandleScrollUp() },
},
{
ViewName: self.context.GetViewName(),
@@ -169,7 +197,7 @@ func (self *ListController) GetMouseKeybindings(opts types.KeybindingsOpts) []*g
ViewName: self.context.GetViewName(),
ToContext: string(self.context.GetKey()),
Key: gocui.MouseWheelDown,
- Handler: func(gocui.ViewMouseBindingOpts) error { return self.HandleNextLine() },
+ Handler: func(gocui.ViewMouseBindingOpts) error { return self.HandleScrollDown() },
},
}
}
diff --git a/pkg/gui/extras_panel.go b/pkg/gui/extras_panel.go
index 462a5118e..6033f8516 100644
--- a/pkg/gui/extras_panel.go
+++ b/pkg/gui/extras_panel.go
@@ -46,15 +46,15 @@ func (gui *Gui) handleFocusCommandLog() error {
func (gui *Gui) scrollUpExtra() error {
gui.Views.Extras.Autoscroll = false
- return gui.scrollUpView(gui.Views.Extras)
+ gui.scrollUpView(gui.Views.Extras)
+
+ return nil
}
func (gui *Gui) scrollDownExtra() error {
gui.Views.Extras.Autoscroll = false
- if err := gui.scrollDownView(gui.Views.Extras); err != nil {
- return err
- }
+ gui.scrollDownView(gui.Views.Extras)
return nil
}
diff --git a/pkg/gui/global_handlers.go b/pkg/gui/global_handlers.go
index e76c9f1a6..97cf4650d 100644
--- a/pkg/gui/global_handlers.go
+++ b/pkg/gui/global_handlers.go
@@ -2,7 +2,6 @@ package gui
import (
"fmt"
- "math"
"strings"
"github.com/jesseduffield/gocui"
@@ -63,56 +62,17 @@ func (gui *Gui) prevScreenMode() error {
return gui.rerenderViewsWithScreenModeDependentContent()
}
-func (gui *Gui) scrollUpView(view *gocui.View) error {
- ox, oy := view.Origin()
- newOy := int(math.Max(0, float64(oy-gui.c.UserConfig.Gui.ScrollHeight)))
- return view.SetOrigin(ox, newOy)
+func (gui *Gui) scrollUpView(view *gocui.View) {
+ view.ScrollUp(gui.c.UserConfig.Gui.ScrollHeight)
}
-func (gui *Gui) scrollDownView(view *gocui.View) error {
- ox, oy := view.Origin()
- scrollHeight := gui.linesToScrollDown(view)
- if scrollHeight > 0 {
- if err := view.SetOrigin(ox, oy+scrollHeight); err != nil {
- return err
- }
- }
+func (gui *Gui) scrollDownView(view *gocui.View) {
+ scrollHeight := gui.c.UserConfig.Gui.ScrollHeight
+ view.ScrollDown(scrollHeight)
if manager, ok := gui.viewBufferManagerMap[view.Name()]; ok {
manager.ReadLines(scrollHeight)
}
- return nil
-}
-
-func (gui *Gui) linesToScrollDown(view *gocui.View) int {
- _, oy := view.Origin()
- y := oy
- canScrollPastBottom := gui.c.UserConfig.Gui.ScrollPastBottom
- if !canScrollPastBottom {
- _, sy := view.Size()
- y += sy
- }
- scrollHeight := gui.c.UserConfig.Gui.ScrollHeight
- scrollableLines := view.ViewLinesHeight() - y
- if scrollableLines < 0 {
- return 0
- }
-
- // margin is about how many lines must still appear if you scroll
- // all the way down. In practice every file ends in a newline so it will really
- // just show a single line
- margin := 1
- if canScrollPastBottom {
- margin = 2
- }
- if scrollableLines-margin < scrollHeight {
- scrollHeight = scrollableLines - margin
- }
- if oy+scrollHeight < 0 {
- return 0
- } else {
- return scrollHeight
- }
}
func (gui *Gui) scrollUpMain() error {
@@ -120,7 +80,9 @@ func (gui *Gui) scrollUpMain() error {
gui.State.Panels.Merging.UserVerticalScrolling = true
}
- return gui.scrollUpView(gui.Views.Main)
+ gui.scrollUpView(gui.Views.Main)
+
+ return nil
}
func (gui *Gui) scrollDownMain() error {
@@ -128,7 +90,9 @@ func (gui *Gui) scrollDownMain() error {
gui.State.Panels.Merging.UserVerticalScrolling = true
}
- return gui.scrollDownView(gui.Views.Main)
+ gui.scrollDownView(gui.Views.Main)
+
+ return nil
}
func (gui *Gui) scrollLeftMain() error {
@@ -153,11 +117,15 @@ func (gui *Gui) scrollRight(view *gocui.View) {
}
func (gui *Gui) scrollUpSecondary() error {
- return gui.scrollUpView(gui.Views.Secondary)
+ gui.scrollUpView(gui.Views.Secondary)
+
+ return nil
}
func (gui *Gui) scrollDownSecondary() error {
- return gui.scrollDownView(gui.Views.Secondary)
+ gui.scrollDownView(gui.Views.Secondary)
+
+ return nil
}
func (gui *Gui) scrollUpConfirmationPanel() error {
@@ -165,7 +133,9 @@ func (gui *Gui) scrollUpConfirmationPanel() error {
return nil
}
- return gui.scrollUpView(gui.Views.Confirmation)
+ gui.scrollUpView(gui.Views.Confirmation)
+
+ return nil
}
func (gui *Gui) scrollDownConfirmationPanel() error {
@@ -173,7 +143,9 @@ func (gui *Gui) scrollDownConfirmationPanel() error {
return nil
}
- return gui.scrollDownView(gui.Views.Confirmation)
+ gui.scrollDownView(gui.Views.Confirmation)
+
+ return nil
}
func (gui *Gui) handleRefresh() error {
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index 17ca26f41..23b8ae8ca 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -661,11 +661,13 @@ func (gui *Gui) createAllViews() error {
gui.Views.Secondary.Wrap = true
gui.Views.Secondary.FgColor = theme.GocuiDefaultTextColor
gui.Views.Secondary.IgnoreCarriageReturns = true
+ gui.Views.Secondary.CanScrollPastBottom = gui.c.UserConfig.Gui.ScrollPastBottom
gui.Views.Main.Title = gui.c.Tr.DiffTitle
gui.Views.Main.Wrap = true
gui.Views.Main.FgColor = theme.GocuiDefaultTextColor
gui.Views.Main.IgnoreCarriageReturns = true
+ gui.Views.Main.CanScrollPastBottom = gui.c.UserConfig.Gui.ScrollPastBottom
gui.Views.Limit.Title = gui.c.Tr.NotEnoughSpace
gui.Views.Limit.Wrap = true
diff --git a/pkg/gui/tasks_adapter.go b/pkg/gui/tasks_adapter.go
index d619c58ba..745cc3760 100644
--- a/pkg/gui/tasks_adapter.go
+++ b/pkg/gui/tasks_adapter.go
@@ -98,21 +98,15 @@ func (gui *Gui) getManager(view *gocui.View) *tasks.ViewBufferManager {
},
func() {
// Need to check if the content of the view is well past the origin.
- // It would be better to use .ViewLinesHeight here (given it considers
- // wrapping) but when this function is called they haven't been written to yet.
- linesHeight := view.LinesHeight()
- _, height := view.Size()
+ linesHeight := view.ViewLinesHeight()
_, originY := view.Origin()
if linesHeight < originY {
- newOriginY := linesHeight - height
- if newOriginY < 0 {
- newOriginY = 0
- }
+ newOriginY := linesHeight
+
err := view.SetOrigin(0, newOriginY)
if err != nil {
panic(err)
}
-
}
view.FlushStaleCells()
diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go
index 6f026fe73..253bb62ef 100644
--- a/pkg/gui/types/context.go
+++ b/pkg/gui/types/context.go
@@ -85,6 +85,8 @@ type IViewTrait interface {
ViewPortYBounds() (int, int)
ScrollLeft()
ScrollRight()
+ ScrollUp()
+ ScrollDown()
PageDelta() int
SelectedLineIdx() int
}
diff --git a/vendor/github.com/jesseduffield/gocui/gui.go b/vendor/github.com/jesseduffield/gocui/gui.go
index ba8d93ce2..58e396492 100644
--- a/vendor/github.com/jesseduffield/gocui/gui.go
+++ b/vendor/github.com/jesseduffield/gocui/gui.go
@@ -743,6 +743,8 @@ func (g *Gui) drawFrameEdges(v *View, fgColor, bgColor Attribute) error {
}
}
}
+
+ showScrollbar, realScrollbarStart, realScrollbarEnd := calcRealScrollbarStartEnd(v)
for y := v.y0 + 1; y < v.y1 && y < g.maxY; y++ {
if y < 0 {
continue
@@ -753,7 +755,9 @@ func (g *Gui) drawFrameEdges(v *View, fgColor, bgColor Attribute) error {
}
}
if v.x1 > -1 && v.x1 < g.maxX {
- if err := g.SetRune(v.x1, y, runeV, fgColor, bgColor); err != nil {
+ runeToPrint := calcScrollbarRune(showScrollbar, realScrollbarStart, realScrollbarEnd, v.y0+1, v.y1-1, y, runeV)
+
+ if err := g.SetRune(v.x1, y, runeToPrint, fgColor, bgColor); err != nil {
return err
}
}
@@ -761,6 +765,44 @@ func (g *Gui) drawFrameEdges(v *View, fgColor, bgColor Attribute) error {
return nil
}
+func calcScrollbarRune(showScrollbar bool, scrollbarStart int, scrollbarEnd int, rangeStart int, rangeEnd int, position int, runeV rune) rune {
+ if !showScrollbar {
+ return runeV
+ } else if position == rangeStart {
+ return '▲'
+ } else if position == rangeEnd {
+ return '▼'
+ } else if position > scrollbarStart && position < scrollbarEnd {
+ return '█'
+ } else if position > rangeStart && position < rangeEnd {
+ // keeping this as a separate branch in case we later want to render something different here.
+ return runeV
+ } else {
+ return runeV
+ }
+}
+
+func calcRealScrollbarStartEnd(v *View) (bool, int, int) {
+ height := v.InnerHeight() + 1
+ fullHeight := v.ViewLinesHeight() - v.scrollMargin()
+
+ if v.CanScrollPastBottom {
+ fullHeight += height
+ }
+
+ if height < 2 || height >= fullHeight {
+ return false, 0, 0
+ }
+
+ originY := v.OriginY()
+ scrollbarStart, scrollbarHeight := calcScrollbar(fullHeight, height, originY, height-1)
+ top := v.y0 + 1
+ realScrollbarStart := top + scrollbarStart
+ realScrollbarEnd := realScrollbarStart + scrollbarHeight
+
+ return true, realScrollbarStart, realScrollbarEnd
+}
+
func cornerRune(index byte) rune {
return []rune{' ', '│', '│', '│', '─', '┘', '┐', '┤', '─', '└', '┌', '├', '├', '┴', '┬', '┼'}[index]
}
@@ -1014,6 +1056,40 @@ func (g *Gui) draw(v *View) error {
if !v.Visible || v.y1 < v.y0 {
return nil
}
+
+ if g.Cursor {
+ if curview := g.currentView; curview != nil {
+ vMaxX, vMaxY := curview.Size()
+ if curview.cx < 0 {
+ curview.cx = 0
+ } else if curview.cx >= vMaxX {
+ curview.cx = vMaxX - 1
+ }
+ if curview.cy < 0 {
+ curview.cy = 0
+ } else if curview.cy >= vMaxY {
+ curview.cy = vMaxY - 1
+ }
+
+ gMaxX, gMaxY := g.Size()
+ cx, cy := curview.x0+curview.cx+1, curview.y0+curview.cy+1
+ // This test probably doesn't need to be here.
+ // tcell is hiding cursor by setting coordinates outside of screen.
+ // Keeping it here for now, as I'm not 100% sure :)
+ if cx >= 0 && cx < gMaxX && cy >= 0 && cy < gMaxY {
+ Screen.ShowCursor(cx, cy)
+ } else {
+ Screen.HideCursor()
+ }
+ }
+ } else {
+ Screen.HideCursor()
+ }
+
+ if err := v.draw(); err != nil {
+ return err
+ }
+
if v.Frame {
var fgColor, bgColor, frameColor Attribute
if g.Highlight && v == g.currentView {
@@ -1057,38 +1133,6 @@ func (g *Gui) draw(v *View) error {
}
}
- if g.Cursor {
- if curview := g.currentView; curview != nil {
- vMaxX, vMaxY := curview.Size()
- if curview.cx < 0 {
- curview.cx = 0
- } else if curview.cx >= vMaxX {
- curview.cx = vMaxX - 1
- }
- if curview.cy < 0 {
- curview.cy = 0
- } else if curview.cy >= vMaxY {
- curview.cy = vMaxY - 1
- }
-
- gMaxX, gMaxY := g.Size()
- cx, cy := curview.x0+curview.cx+1, curview.y0+curview.cy+1
- // This test probably doesn't need to be here.
- // tcell is hiding cursor by setting coordinates outside of screen.
- // Keeping it here for now, as I'm not 100% sure :)
- if cx >= 0 && cx < gMaxX && cy >= 0 && cy < gMaxY {
- Screen.ShowCursor(cx, cy)
- } else {
- Screen.HideCursor()
- }
- }
- } else {
- Screen.HideCursor()
- }
-
- if err := v.draw(); err != nil {
- return err
- }
return nil
}
diff --git a/vendor/github.com/jesseduffield/gocui/scrollbar.go b/vendor/github.com/jesseduffield/gocui/scrollbar.go
new file mode 100644
index 000000000..3bdb4a45c
--- /dev/null
+++ b/vendor/github.com/jesseduffield/gocui/scrollbar.go
@@ -0,0 +1,33 @@
+package gocui
+
+import "math"
+
+// returns start and height of scrollbar
+// `max` is the maximum possible value of `position`
+func calcScrollbar(listSize int, pageSize int, position int, scrollAreaSize int) (int, int) {
+ height := calcScrollbarHeight(listSize, pageSize, scrollAreaSize)
+ // assume we can't scroll past the last item
+ maxPosition := listSize - pageSize
+ if maxPosition <= 0 {
+ return 0, height
+ }
+ if position == maxPosition {
+ return scrollAreaSize - height, height
+ }
+ // we only want to show the scrollbar at the top or bottom positions if we're at the end. Hence the .Ceil (for moving the scrollbar once we scroll down) and the -1 (for pretending there's a smaller range than we actually have, with the above condition ensuring we snap to the bottom once we're at the end of the list)
+ start := int(math.Ceil(((float64(position) / float64(maxPosition)) * float64(scrollAreaSize-height-1))))
+ return start, height
+}
+
+func calcScrollbarHeight(listSize int, pageSize int, scrollAreaSize int) int {
+ if pageSize >= listSize {
+ return scrollAreaSize
+ }
+ height := int((float64(pageSize) / float64(listSize)) * float64(scrollAreaSize))
+ minHeight := 2
+ if height < minHeight {
+ return minHeight
+ }
+
+ return height
+}
diff --git a/vendor/github.com/jesseduffield/gocui/view.go b/vendor/github.com/jesseduffield/gocui/view.go
index d2c2b75f1..8051cce72 100644
--- a/vendor/github.com/jesseduffield/gocui/view.go
+++ b/vendor/github.com/jesseduffield/gocui/view.go
@@ -158,6 +158,9 @@ type View struct {
// something like '1 of 20' for a list view
Footer string
+
+ // if true, the user can scroll all the way past the last item until it appears at the top of the view
+ CanScrollPastBottom bool
}
// call this in the event of a view resize, or if you want to render new content
@@ -1287,3 +1290,69 @@ func (v *View) OverwriteLines(y int, content string) {
lines := strings.Replace(content, "\n", "\x1b[K\n", -1)
v.writeString(lines)
}
+
+func (v *View) ScrollUp(amount int) {
+ newOy := v.oy - amount
+ if newOy < 0 {
+ newOy = 0
+ }
+ v.oy = newOy
+}
+
+// ensures we don't scroll past the end of the view's content
+func (v *View) ScrollDown(amount int) {
+ adjustedAmount := v.adjustDownwardScrollAmount(amount)
+ if adjustedAmount > 0 {
+ v.oy += adjustedAmount
+ }
+}
+
+func (v *View) ScrollLeft(amount int) {
+ newOx := v.ox - amount
+ if newOx < 0 {
+ newOx = 0
+ }
+ v.ox = newOx
+}
+
+// not applying any limits to this
+func (v *View) ScrollRight(amount int) {
+ v.ox += amount
+}
+
+func (v *View) adjustDownwardScrollAmount(scrollHeight int) int {
+ _, oy := v.Origin()
+ y := oy
+ if !v.CanScrollPastBottom {
+ _, sy := v.Size()
+ y += sy
+ }
+ scrollableLines := v.ViewLinesHeight() - y
+ if scrollableLines < 0 {
+ return 0
+ }
+
+ margin := v.scrollMargin()
+ if scrollableLines-margin < scrollHeight {
+ scrollHeight = scrollableLines - margin
+ }
+ if oy+scrollHeight < 0 {
+ return 0
+ } else {
+ return scrollHeight
+ }
+}
+
+// scrollMargin is about how many lines must still appear if you scroll
+// all the way down. We'll subtract this from the total amount of scrollable lines
+func (v *View) scrollMargin() int {
+ if v.CanScrollPastBottom {
+ // Setting to 2 because of the newline at the end of the file that we're likely showing.
+ // If we want to scroll past bottom outside the context of reading a file's contents,
+ // we should make this into a field on the view to be configured by the client.
+ // For now we're hardcoding it.
+ return 2
+ } else {
+ return 0
+ }
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index a7f378b45..68bceb9b0 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -169,7 +169,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.20220415005542-2eb424ce3d0a
+# github.com/jesseduffield/gocui v0.3.1-0.20220416053910-5b19e175bc67
## explicit; go 1.12
github.com/jesseduffield/gocui
# github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e