diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2024-01-11 10:34:05 +1100 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2024-01-19 10:47:21 +1100 |
commit | c0c3aac02e048903764e4b42b513334e58855d73 (patch) | |
tree | 6d316241ca5993ce56fb9d406dc0fdece0eeda4d | |
parent | 24a4302c528e3a11b30855c006669de1adf9e1d4 (diff) |
Support non-sticky range selection in patch explorer views
-rw-r--r-- | pkg/gui/context/patch_explorer_context.go | 10 | ||||
-rw-r--r-- | pkg/gui/controllers/patch_explorer_controller.go | 30 | ||||
-rw-r--r-- | pkg/gui/patch_exploring/state.go | 62 |
3 files changed, 96 insertions, 6 deletions
diff --git a/pkg/gui/context/patch_explorer_context.go b/pkg/gui/context/patch_explorer_context.go index 54a9356ac..6f086e7f4 100644 --- a/pkg/gui/context/patch_explorer_context.go +++ b/pkg/gui/context/patch_explorer_context.go @@ -116,6 +116,16 @@ func (self *PatchExplorerContext) FocusSelection() { _ = view.SetOriginY(newOriginY) view.SetCursorY(state.GetSelectedLineIdx() - newOriginY) + + // At present this is just bookkeeping: the reason for setting this would be + // so that gocui knows which lines to highlight, but we're currently handling + // highlighting ourselves. + rangeStartLineIdx, isSelectingRange := state.RangeStartLineIdx() + if isSelectingRange { + view.SetRangeSelectStart(rangeStartLineIdx) + } else { + view.CancelRangeSelect() + } } func (self *PatchExplorerContext) GetContentToRender(isFocused bool) string { diff --git a/pkg/gui/controllers/patch_explorer_controller.go b/pkg/gui/controllers/patch_explorer_controller.go index 2083c2943..caac1f51c 100644 --- a/pkg/gui/controllers/patch_explorer_controller.go +++ b/pkg/gui/controllers/patch_explorer_controller.go @@ -57,6 +57,18 @@ func (self *PatchExplorerController) GetKeybindings(opts types.KeybindingsOpts) Handler: self.withRenderAndFocus(self.HandleNextLine), }, { + Tag: "navigation", + Key: opts.GetKey(opts.Config.Universal.RangeSelectUp), + Handler: self.withRenderAndFocus(self.HandlePrevLineRange), + Description: self.c.Tr.RangeSelectUp, + }, + { + Tag: "navigation", + Key: opts.GetKey(opts.Config.Universal.RangeSelectDown), + Handler: self.withRenderAndFocus(self.HandleNextLineRange), + Description: self.c.Tr.RangeSelectDown, + }, + { Key: opts.GetKey(opts.Config.Universal.PrevBlock), Handler: self.withRenderAndFocus(self.HandlePrevHunk), Description: self.c.Tr.PrevHunk, @@ -177,6 +189,22 @@ func (self *PatchExplorerController) HandleNextLine() error { return nil } +func (self *PatchExplorerController) HandlePrevLineRange() error { + s := self.context.GetState() + + s.CycleRange(false) + + return nil +} + +func (self *PatchExplorerController) HandleNextLineRange() error { + s := self.context.GetState() + + s.CycleRange(true) + + return nil +} + func (self *PatchExplorerController) HandlePrevHunk() error { self.context.GetState().CycleHunk(false) @@ -190,7 +218,7 @@ func (self *PatchExplorerController) HandleNextHunk() error { } func (self *PatchExplorerController) HandleToggleSelectRange() error { - self.context.GetState().ToggleSelectRange() + self.context.GetState().ToggleStickySelectRange() return nil } diff --git a/pkg/gui/patch_exploring/state.go b/pkg/gui/patch_exploring/state.go index 1c82d59cb..d54b7ec7c 100644 --- a/pkg/gui/patch_exploring/state.go +++ b/pkg/gui/patch_exploring/state.go @@ -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 +} |