Support non-sticky range selection in patch explorer views

This commit is contained in:
Jesse Duffield 2024-01-11 10:34:05 +11:00
parent 24a4302c52
commit c0c3aac02e
3 changed files with 96 additions and 6 deletions

View file

@ -12,9 +12,12 @@ import (
type State struct {
selectedLineIdx int
rangeStartLineIdx int
diff string
patch *patch.Patch
selectMode selectMode
// If a range is sticky, it means we expand the range when we move up or down.
// Otherwise, we cancel the range when we move up or down.
rangeIsSticky bool
diff string
patch *patch.Patch
selectMode selectMode
}
// these represent what select mode we're in
@ -46,10 +49,12 @@ func NewState(diff string, selectedLineIdx int, oldState *State, log *logrus.Ent
}
selectMode := LINE
rangeIsSticky := false
// if we have clicked from the outside to focus the main view we'll pass in a non-negative line index so that we can instantly select that line
if selectedLineIdx >= 0 {
selectMode = RANGE
rangeStartLineIdx = selectedLineIdx
rangeIsSticky = true
} else if oldState != nil {
// if we previously had a selectMode of RANGE, we want that to now be line again
if oldState.selectMode == HUNK {
@ -65,6 +70,7 @@ func NewState(diff string, selectedLineIdx int, oldState *State, log *logrus.Ent
selectedLineIdx: selectedLineIdx,
selectMode: selectMode,
rangeStartLineIdx: rangeStartLineIdx,
rangeIsSticky: rangeIsSticky,
diff: diff,
}
}
@ -85,15 +91,24 @@ func (s *State) ToggleSelectHunk() {
}
}
func (s *State) ToggleSelectRange() {
func (s *State) ToggleStickySelectRange() {
s.ToggleSelectRange(true)
}
func (s *State) ToggleSelectRange(sticky bool) {
if s.selectMode == RANGE {
s.selectMode = LINE
} else {
s.selectMode = RANGE
s.rangeStartLineIdx = s.selectedLineIdx
s.rangeIsSticky = sticky
}
}
func (s *State) SetRangeIsSticky(value bool) {
s.rangeIsSticky = value
}
func (s *State) SelectingHunk() bool {
return s.selectMode == HUNK
}
@ -110,7 +125,18 @@ func (s *State) SetLineSelectMode() {
s.selectMode = LINE
}
// For when you move the cursor without holding shift (meaning if we're in
// a non-sticky range select, we'll cancel it)
func (s *State) SelectLine(newSelectedLineIdx int) {
if s.selectMode == RANGE && !s.rangeIsSticky {
s.selectMode = LINE
}
s.selectLineWithoutRangeCheck(newSelectedLineIdx)
}
// This just moves the cursor without caring about range select
func (s *State) selectLineWithoutRangeCheck(newSelectedLineIdx int) {
if newSelectedLineIdx < 0 {
newSelectedLineIdx = 0
} else if newSelectedLineIdx > s.patch.LineCount()-1 {
@ -124,8 +150,9 @@ func (s *State) SelectNewLineForRange(newSelectedLineIdx int) {
s.rangeStartLineIdx = newSelectedLineIdx
s.selectMode = RANGE
s.rangeIsSticky = true
s.SelectLine(newSelectedLineIdx)
s.selectLineWithoutRangeCheck(newSelectedLineIdx)
}
func (s *State) CycleSelection(forward bool) {
@ -161,6 +188,23 @@ func (s *State) CycleLine(forward bool) {
s.SelectLine(s.selectedLineIdx + change)
}
// This is called when we use shift+arrow to expand the range (i.e. a non-sticky
// range)
func (s *State) CycleRange(forward bool) {
if !s.SelectingRange() {
s.ToggleSelectRange(false)
}
s.SetRangeIsSticky(false)
change := 1
if !forward {
change = -1
}
s.selectLineWithoutRangeCheck(s.selectedLineIdx + change)
}
// returns first and last patch line index of current hunk
func (s *State) CurrentHunkBounds() (int, int) {
hunkIdx := s.patch.HunkContainingLine(s.selectedLineIdx)
@ -226,3 +270,11 @@ func (s *State) CalculateOrigin(currentOrigin int, bufferHeight int, numLines in
return calculateOrigin(currentOrigin, bufferHeight, numLines, firstLineIdx, lastLineIdx, s.GetSelectedLineIdx(), s.selectMode)
}
func (s *State) RangeStartLineIdx() (int, bool) {
if s.selectMode == RANGE {
return s.rangeStartLineIdx, true
}
return 0, false
}