summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2021-06-05 13:18:53 +1000
committerJesse Duffield <jessedduffield@gmail.com>2021-06-05 13:54:05 +1000
commitf91adf026bfbddc9505d6d84d3fabc80d49c7ca0 (patch)
treec905b864450ed998dc0d039039aa48adfeebf046
parent6d91661d5e3c0cc25bd16083523204951b7dccd3 (diff)
fix lbl scrollingv0.28.2
-rw-r--r--pkg/gui/lbl/focus.go52
-rw-r--r--pkg/gui/lbl/focus_test.go100
-rw-r--r--pkg/gui/lbl/state.go6
-rw-r--r--pkg/gui/line_by_line_panel.go15
4 files changed, 161 insertions, 12 deletions
diff --git a/pkg/gui/lbl/focus.go b/pkg/gui/lbl/focus.go
new file mode 100644
index 000000000..ea70fbb3d
--- /dev/null
+++ b/pkg/gui/lbl/focus.go
@@ -0,0 +1,52 @@
+package lbl
+
+import "github.com/jesseduffield/lazygit/pkg/utils"
+
+func calculateOrigin(currentOrigin int, bufferHeight int, firstLineIdx int, lastLineIdx int, selectedLineIdx int, mode selectMode) int {
+ needToSeeIdx, wantToSeeIdx := getNeedAndWantLineIdx(firstLineIdx, lastLineIdx, selectedLineIdx, mode)
+
+ return calculateNewOriginWithNeededAndWantedIdx(currentOrigin, bufferHeight, needToSeeIdx, wantToSeeIdx)
+}
+
+// we want to scroll our origin so that the index we need to see is in view
+// and the other index we want to see (e.g. the other side of a line range)
+// is in as close to being in view as possible.
+func calculateNewOriginWithNeededAndWantedIdx(currentOrigin int, bufferHeight int, needToSeeIdx int, wantToSeeIdx int) int {
+ origin := currentOrigin
+ if needToSeeIdx < currentOrigin {
+ origin = needToSeeIdx
+ } else if needToSeeIdx > currentOrigin+bufferHeight {
+ origin = needToSeeIdx - bufferHeight
+ }
+
+ bottom := origin + bufferHeight
+
+ if wantToSeeIdx < origin {
+ requiredChange := origin - wantToSeeIdx
+ allowedChange := bottom - needToSeeIdx
+ return origin - utils.Min(requiredChange, allowedChange)
+ } else if wantToSeeIdx > origin+bufferHeight {
+ requiredChange := wantToSeeIdx - bottom
+ allowedChange := needToSeeIdx - origin
+ return origin + utils.Min(requiredChange, allowedChange)
+ } else {
+ return origin
+ }
+}
+
+func getNeedAndWantLineIdx(firstLineIdx int, lastLineIdx int, selectedLineIdx int, mode selectMode) (int, int) {
+ switch mode {
+ case LINE:
+ return selectedLineIdx, selectedLineIdx
+ case RANGE:
+ if selectedLineIdx == firstLineIdx {
+ return firstLineIdx, lastLineIdx
+ } else {
+ return lastLineIdx, firstLineIdx
+ }
+ case HUNK:
+ return firstLineIdx, lastLineIdx
+ default:
+ panic("unknown mode")
+ }
+}
diff --git a/pkg/gui/lbl/focus_test.go b/pkg/gui/lbl/focus_test.go
new file mode 100644
index 000000000..f36191ce5
--- /dev/null
+++ b/pkg/gui/lbl/focus_test.go
@@ -0,0 +1,100 @@
+package lbl
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestNewOrigin(t *testing.T) {
+ type scenario struct {
+ name string
+ origin int
+ bufferHeight int
+ firstLineIdx int
+ lastLineIdx int
+ selectedLineIdx int
+ selectMode selectMode
+ expected int
+ }
+
+ scenarios := []scenario{
+ {
+ name: "selection above scroll window",
+ origin: 50,
+ bufferHeight: 100,
+ firstLineIdx: 10,
+ lastLineIdx: 10,
+ selectedLineIdx: 10,
+ selectMode: LINE,
+ expected: 10,
+ },
+ {
+ name: "selection below scroll window",
+ origin: 0,
+ bufferHeight: 100,
+ firstLineIdx: 150,
+ lastLineIdx: 150,
+ selectedLineIdx: 150,
+ selectMode: LINE,
+ expected: 50,
+ },
+ {
+ name: "selection within scroll window",
+ origin: 0,
+ bufferHeight: 100,
+ firstLineIdx: 50,
+ lastLineIdx: 50,
+ selectedLineIdx: 50,
+ selectMode: LINE,
+ expected: 0,
+ },
+ {
+ name: "range ending below scroll window with selection at end of range",
+ origin: 0,
+ bufferHeight: 100,
+ firstLineIdx: 40,
+ lastLineIdx: 150,
+ selectedLineIdx: 150,
+ selectMode: RANGE,
+ expected: 50,
+ },
+ {
+ name: "range ending below scroll window with selection at beginning of range",
+ origin: 0,
+ bufferHeight: 100,
+ firstLineIdx: 40,
+ lastLineIdx: 150,
+ selectedLineIdx: 40,
+ selectMode: RANGE,
+ expected: 40,
+ },
+ {
+ name: "range starting above scroll window with selection at beginning of range",
+ origin: 50,
+ bufferHeight: 100,
+ firstLineIdx: 40,
+ lastLineIdx: 150,
+ selectedLineIdx: 40,
+ selectMode: RANGE,
+ expected: 40,
+ },
+ {
+ name: "hunk extending beyond both bounds of scroll window",
+ origin: 50,
+ bufferHeight: 100,
+ firstLineIdx: 40,
+ lastLineIdx: 200,
+ selectedLineIdx: 70,
+ selectMode: HUNK,
+ expected: 40,
+ },
+ }
+
+ for _, s := range scenarios {
+ s := s
+ t.Run(s.name, func(t *testing.T) {
+ assert.EqualValues(t, s.expected, calculateOrigin(s.origin, s.bufferHeight, s.firstLineIdx, s.lastLineIdx, s.selectedLineIdx, s.selectMode))
+ })
+ }
+}
diff --git a/pkg/gui/lbl/state.go b/pkg/gui/lbl/state.go
index 87a70136e..8ae828923 100644
--- a/pkg/gui/lbl/state.go
+++ b/pkg/gui/lbl/state.go
@@ -189,3 +189,9 @@ func (s *State) SelectTop() {
s.SetLineSelectMode()
s.SelectLine(0)
}
+
+func (s *State) CalculateOrigin(currentOrigin int, bufferHeight int) int {
+ firstLineIdx, lastLineIdx := s.SelectedRange()
+
+ return calculateOrigin(currentOrigin, bufferHeight, firstLineIdx, lastLineIdx, s.GetSelectedLineIdx(), s.selectMode)
+}
diff --git a/pkg/gui/line_by_line_panel.go b/pkg/gui/line_by_line_panel.go
index ff2d6d5f8..d7a5380b2 100644
--- a/pkg/gui/line_by_line_panel.go
+++ b/pkg/gui/line_by_line_panel.go
@@ -155,25 +155,16 @@ func (gui *Gui) focusSelection(state *LblPanelState) error {
bufferHeight := viewHeight - 1
_, origin := stagingView.Origin()
- firstLineIdx, lastLineIdx := state.SelectedRange()
+ selectedLineIdx := state.GetSelectedLineIdx()
- margin := 0 // we may want to have a margin in place to show context but right now I'm thinking we keep this at zero
-
- var newOrigin int
- if firstLineIdx-origin < margin {
- newOrigin = firstLineIdx - margin
- } else if lastLineIdx-origin > bufferHeight-margin {
- newOrigin = lastLineIdx - bufferHeight + margin
- } else {
- newOrigin = origin
- }
+ newOrigin := state.CalculateOrigin(origin, bufferHeight)
gui.g.Update(func(*gocui.Gui) error {
if err := stagingView.SetOrigin(0, newOrigin); err != nil {
return err
}
- return stagingView.SetCursor(0, state.GetSelectedLineIdx()-newOrigin)
+ return stagingView.SetCursor(0, selectedLineIdx-newOrigin)
})
return nil