mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-31 14:24:25 +03:00
Support non-sticky range selection in patch explorer views
This commit is contained in:
@ -116,6 +116,16 @@ func (self *PatchExplorerContext) FocusSelection() {
|
|||||||
_ = view.SetOriginY(newOriginY)
|
_ = view.SetOriginY(newOriginY)
|
||||||
|
|
||||||
view.SetCursorY(state.GetSelectedLineIdx() - 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 {
|
func (self *PatchExplorerContext) GetContentToRender(isFocused bool) string {
|
||||||
|
@ -56,6 +56,18 @@ func (self *PatchExplorerController) GetKeybindings(opts types.KeybindingsOpts)
|
|||||||
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
||||||
Handler: self.withRenderAndFocus(self.HandleNextLine),
|
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),
|
Key: opts.GetKey(opts.Config.Universal.PrevBlock),
|
||||||
Handler: self.withRenderAndFocus(self.HandlePrevHunk),
|
Handler: self.withRenderAndFocus(self.HandlePrevHunk),
|
||||||
@ -177,6 +189,22 @@ func (self *PatchExplorerController) HandleNextLine() error {
|
|||||||
return nil
|
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 {
|
func (self *PatchExplorerController) HandlePrevHunk() error {
|
||||||
self.context.GetState().CycleHunk(false)
|
self.context.GetState().CycleHunk(false)
|
||||||
|
|
||||||
@ -190,7 +218,7 @@ func (self *PatchExplorerController) HandleNextHunk() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *PatchExplorerController) HandleToggleSelectRange() error {
|
func (self *PatchExplorerController) HandleToggleSelectRange() error {
|
||||||
self.context.GetState().ToggleSelectRange()
|
self.context.GetState().ToggleStickySelectRange()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,12 @@ import (
|
|||||||
type State struct {
|
type State struct {
|
||||||
selectedLineIdx int
|
selectedLineIdx int
|
||||||
rangeStartLineIdx int
|
rangeStartLineIdx int
|
||||||
diff string
|
// If a range is sticky, it means we expand the range when we move up or down.
|
||||||
patch *patch.Patch
|
// Otherwise, we cancel the range when we move up or down.
|
||||||
selectMode selectMode
|
rangeIsSticky bool
|
||||||
|
diff string
|
||||||
|
patch *patch.Patch
|
||||||
|
selectMode selectMode
|
||||||
}
|
}
|
||||||
|
|
||||||
// these represent what select mode we're in
|
// 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
|
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 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 {
|
if selectedLineIdx >= 0 {
|
||||||
selectMode = RANGE
|
selectMode = RANGE
|
||||||
rangeStartLineIdx = selectedLineIdx
|
rangeStartLineIdx = selectedLineIdx
|
||||||
|
rangeIsSticky = true
|
||||||
} else if oldState != nil {
|
} else if oldState != nil {
|
||||||
// if we previously had a selectMode of RANGE, we want that to now be line again
|
// if we previously had a selectMode of RANGE, we want that to now be line again
|
||||||
if oldState.selectMode == HUNK {
|
if oldState.selectMode == HUNK {
|
||||||
@ -65,6 +70,7 @@ func NewState(diff string, selectedLineIdx int, oldState *State, log *logrus.Ent
|
|||||||
selectedLineIdx: selectedLineIdx,
|
selectedLineIdx: selectedLineIdx,
|
||||||
selectMode: selectMode,
|
selectMode: selectMode,
|
||||||
rangeStartLineIdx: rangeStartLineIdx,
|
rangeStartLineIdx: rangeStartLineIdx,
|
||||||
|
rangeIsSticky: rangeIsSticky,
|
||||||
diff: diff,
|
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 {
|
if s.selectMode == RANGE {
|
||||||
s.selectMode = LINE
|
s.selectMode = LINE
|
||||||
} else {
|
} else {
|
||||||
s.selectMode = RANGE
|
s.selectMode = RANGE
|
||||||
s.rangeStartLineIdx = s.selectedLineIdx
|
s.rangeStartLineIdx = s.selectedLineIdx
|
||||||
|
s.rangeIsSticky = sticky
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *State) SetRangeIsSticky(value bool) {
|
||||||
|
s.rangeIsSticky = value
|
||||||
|
}
|
||||||
|
|
||||||
func (s *State) SelectingHunk() bool {
|
func (s *State) SelectingHunk() bool {
|
||||||
return s.selectMode == HUNK
|
return s.selectMode == HUNK
|
||||||
}
|
}
|
||||||
@ -110,7 +125,18 @@ func (s *State) SetLineSelectMode() {
|
|||||||
s.selectMode = LINE
|
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) {
|
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 {
|
if newSelectedLineIdx < 0 {
|
||||||
newSelectedLineIdx = 0
|
newSelectedLineIdx = 0
|
||||||
} else if newSelectedLineIdx > s.patch.LineCount()-1 {
|
} else if newSelectedLineIdx > s.patch.LineCount()-1 {
|
||||||
@ -124,8 +150,9 @@ func (s *State) SelectNewLineForRange(newSelectedLineIdx int) {
|
|||||||
s.rangeStartLineIdx = newSelectedLineIdx
|
s.rangeStartLineIdx = newSelectedLineIdx
|
||||||
|
|
||||||
s.selectMode = RANGE
|
s.selectMode = RANGE
|
||||||
|
s.rangeIsSticky = true
|
||||||
|
|
||||||
s.SelectLine(newSelectedLineIdx)
|
s.selectLineWithoutRangeCheck(newSelectedLineIdx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) CycleSelection(forward bool) {
|
func (s *State) CycleSelection(forward bool) {
|
||||||
@ -161,6 +188,23 @@ func (s *State) CycleLine(forward bool) {
|
|||||||
s.SelectLine(s.selectedLineIdx + change)
|
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
|
// returns first and last patch line index of current hunk
|
||||||
func (s *State) CurrentHunkBounds() (int, int) {
|
func (s *State) CurrentHunkBounds() (int, int) {
|
||||||
hunkIdx := s.patch.HunkContainingLine(s.selectedLineIdx)
|
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)
|
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
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user