Repository: jesseduffield/lazygit (language: go)

Issue:
Range select with more than just up/down arrows
**Is your feature request related to a problem? Please describe.**
I can't seem to select a range of text in the Unstaged Changes box without selecting one line at a time by pressing or holding down the up/down arrows. This is very slow and tedious.

**Describe the solution you'd like**
Ideally, I'd be able to select text using vim-like shortcuts, but I understand that the shortcut space is already quite crowded. But it would be super cool to be able to hit `v` and then have lazygit change keymaps and support all of the standard `vim`-like shortcuts (`ctrl-d` /`ctrl-u`, `gg`/`G`, etc).  But, short of  that, hitting `v` to toggle range selection and then using either `<`/`>` or `,`/`.` to select a range would be sufficient.




Discussion / hints:
I'm skeptical about vim-like shortcuts, for reasons that have been discussed here a few times (I'm too lazy to dig up references, sorry). But using `<`/`>` and `,`/`.` should totally work in range mode, and I'd call it a bug that they don't. Actually, they do in list views (e.g. in the commits panel), just not in the staging view.

Fix patch:
diff --git a/pkg/gui/controllers/patch_explorer_controller.go b/pkg/gui/controllers/patch_explorer_controller.go
index 6d3290f0411..999dc15e97e 100644
--- a/pkg/gui/controllers/patch_explorer_controller.go
+++ b/pkg/gui/controllers/patch_explorer_controller.go
@@ -244,14 +244,12 @@ func (self *PatchExplorerController) HandleScrollRight() error {
 }
 
 func (self *PatchExplorerController) HandlePrevPage() error {
-	self.context.GetState().SetLineSelectMode()
 	self.context.GetState().AdjustSelectedLineIdx(-self.context.GetViewTrait().PageDelta())
 
 	return nil
 }
 
 func (self *PatchExplorerController) HandleNextPage() error {
-	self.context.GetState().SetLineSelectMode()
 	self.context.GetState().AdjustSelectedLineIdx(self.context.GetViewTrait().PageDelta())
 
 	return nil
diff --git a/pkg/gui/patch_exploring/state.go b/pkg/gui/patch_exploring/state.go
index 03c933c7e28..40a28e7f7e8 100644
--- a/pkg/gui/patch_exploring/state.go
+++ b/pkg/gui/patch_exploring/state.go
@@ -123,6 +123,12 @@ func (s *State) SetLineSelectMode() {
 	s.selectMode = LINE
 }
 
+func (s *State) DismissHunkSelectMode() {
+	if s.SelectingHunk() {
+		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) {
@@ -239,6 +245,7 @@ func (s *State) CurrentLineNumber() int {
 }
 
 func (s *State) AdjustSelectedLineIdx(change int) {
+	s.DismissHunkSelectMode()
 	s.SelectLine(s.selectedLineIdx + change)
 }
 
@@ -255,12 +262,12 @@ func (s *State) PlainRenderSelected() string {
 }
 
 func (s *State) SelectBottom() {
-	s.SetLineSelectMode()
+	s.DismissHunkSelectMode()
 	s.SelectLine(s.patch.LineCount() - 1)
 }
 
 func (s *State) SelectTop() {
-	s.SetLineSelectMode()
+	s.DismissHunkSelectMode()
 	s.SelectLine(0)
 }
 


Test patch:
diff --git a/pkg/integration/tests/ui/range_select.go b/pkg/integration/tests/ui/range_select.go
index 4885c7cb41a..abc0186daf1 100644
--- a/pkg/integration/tests/ui/range_select.go
+++ b/pkg/integration/tests/ui/range_select.go
@@ -14,6 +14,7 @@ import (
 // (sticky range, press 'v') -> no range
 // (sticky range, press 'escape') -> no range
 // (sticky range, press arrow) -> sticky range
+// (sticky range, press `<`/`>` or `,`/`.`) -> sticky range
 // (sticky range, press shift+arrow) -> nonsticky range
 // (nonsticky range, press 'v') -> no range
 // (nonsticky range, press 'escape') -> no range
@@ -138,19 +139,18 @@ var RangeSelect = NewIntegrationTest(NewIntegrationTestArgs{
 				SelectedLines(
 					Contains("line 8"),
 				).
+				// (sticky range, press '>') -> sticky range
 				Press(keys.Universal.ToggleRangeSelect).
-				SelectedLines(
-					Contains("line 8"),
-				).
-				SelectNextItem().
+				Press(keys.Universal.GotoBottom).
 				SelectedLines(
 					Contains("line 8"),
 					Contains("line 9"),
+					Contains("line 10"),
 				).
 				// (sticky range, press 'escape') -> no range
 				PressEscape().
 				SelectedLines(
-					Contains("line 9"),
+					Contains("line 10"),
 				)
 		}