From 6c0ee7df2b7865837a11bb82fb53a05cc8084868 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 21 Apr 2025 18:03:11 +0200 Subject: [PATCH 01/16] Bump gocui --- go.mod | 2 +- go.sum | 4 ++-- vendor/github.com/jesseduffield/gocui/view.go | 4 ++-- vendor/modules.txt | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index d854d07c92a..ae9990519bb 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/integrii/flaggy v1.4.0 github.com/jesseduffield/generics v0.0.0-20250406224309-4f541cb84918 github.com/jesseduffield/go-git/v5 v5.14.1-0.20250407170251-e1a013310ccd - github.com/jesseduffield/gocui v0.3.1-0.20250408140206-7f1bb9232647 + github.com/jesseduffield/gocui v0.3.1-0.20250421160159-82c9aaeba2b9 github.com/jesseduffield/kill v0.0.0-20250101124109-e216ddbe133a github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e diff --git a/go.sum b/go.sum index e62940c3fe2..98389ca8175 100644 --- a/go.sum +++ b/go.sum @@ -194,8 +194,8 @@ github.com/jesseduffield/generics v0.0.0-20250406224309-4f541cb84918 h1:meoUDZGF github.com/jesseduffield/generics v0.0.0-20250406224309-4f541cb84918/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk= github.com/jesseduffield/go-git/v5 v5.14.1-0.20250407170251-e1a013310ccd h1:ViKj6qth8FgcIWizn9KiACWwPemWSymx62OPN0tHT+Q= github.com/jesseduffield/go-git/v5 v5.14.1-0.20250407170251-e1a013310ccd/go.mod h1:lRhCiBr6XjQrvcQVa+UYsy/99d3wMXn/a0nSQlhnhlA= -github.com/jesseduffield/gocui v0.3.1-0.20250408140206-7f1bb9232647 h1:XpoXCyLGCB4mczPc1q/8dJefr6OB1xa7jyhH5a5eJqY= -github.com/jesseduffield/gocui v0.3.1-0.20250408140206-7f1bb9232647/go.mod h1:sLIyZ2J42R6idGdtemZzsiR3xY5EF0KsvYEGh3dQv3s= +github.com/jesseduffield/gocui v0.3.1-0.20250421160159-82c9aaeba2b9 h1:k23sCKHCNpAvwJP8Yr16CBUItuarmUHBGH7FaAm2glc= +github.com/jesseduffield/gocui v0.3.1-0.20250421160159-82c9aaeba2b9/go.mod h1:sLIyZ2J42R6idGdtemZzsiR3xY5EF0KsvYEGh3dQv3s= github.com/jesseduffield/kill v0.0.0-20250101124109-e216ddbe133a h1:UDeJ3EBk04bXDLOPvuqM3on8HvyJfISw0+UMqW+0a4g= github.com/jesseduffield/kill v0.0.0-20250101124109-e216ddbe133a/go.mod h1:FSWDLKT0NQpntbDd1H3lbz51fhCVlMzy/J0S6nM727Q= github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY= diff --git a/vendor/github.com/jesseduffield/gocui/view.go b/vendor/github.com/jesseduffield/gocui/view.go index 2662ae6aceb..8c95bbe351c 100644 --- a/vendor/github.com/jesseduffield/gocui/view.go +++ b/vendor/github.com/jesseduffield/gocui/view.go @@ -519,9 +519,9 @@ func (v *View) setRune(x, y int, ch rune, fgColor, bgColor Attribute) { } fgColor = fgColor | AttrBold if v.HighlightInactive { - bgColor = bgColor | v.InactiveViewSelBgColor + bgColor = (bgColor & AttrStyleBits) | v.InactiveViewSelBgColor } else { - bgColor = bgColor | v.SelBgColor + bgColor = (bgColor & AttrStyleBits) | v.SelBgColor } } } diff --git a/vendor/modules.txt b/vendor/modules.txt index cc9c61b1adf..e2ec62f924f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -226,7 +226,7 @@ github.com/jesseduffield/go-git/v5/utils/merkletrie/internal/frame github.com/jesseduffield/go-git/v5/utils/merkletrie/noder github.com/jesseduffield/go-git/v5/utils/sync github.com/jesseduffield/go-git/v5/utils/trace -# github.com/jesseduffield/gocui v0.3.1-0.20250408140206-7f1bb9232647 +# github.com/jesseduffield/gocui v0.3.1-0.20250421160159-82c9aaeba2b9 ## explicit; go 1.12 github.com/jesseduffield/gocui # github.com/jesseduffield/kill v0.0.0-20250101124109-e216ddbe133a From b97dd6bc3f7c8bfc7725e1cf50b26ff27bb9b403 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 15 Oct 2024 15:28:33 +0200 Subject: [PATCH 02/16] Remove utils.Clamp, use lo.Clamp instead --- pkg/commands/patch/patch.go | 7 +++---- pkg/gui/context/list_renderer.go | 2 +- pkg/gui/context/traits/list_cursor.go | 3 ++- pkg/gui/mergeconflicts/state.go | 5 +++-- pkg/utils/utils.go | 9 --------- 5 files changed, 9 insertions(+), 17 deletions(-) diff --git a/pkg/commands/patch/patch.go b/pkg/commands/patch/patch.go index d785fe49e27..5e4f9a84665 100644 --- a/pkg/commands/patch/patch.go +++ b/pkg/commands/patch/patch.go @@ -1,7 +1,6 @@ package patch import ( - "github.com/jesseduffield/lazygit/pkg/utils" "github.com/samber/lo" ) @@ -54,7 +53,7 @@ func (self *Patch) Lines() []*PatchLine { // Returns the patch line index of the first line in the given hunk func (self *Patch) HunkStartIdx(hunkIndex int) int { - hunkIndex = utils.Clamp(hunkIndex, 0, len(self.hunks)-1) + hunkIndex = lo.Clamp(hunkIndex, 0, len(self.hunks)-1) result := len(self.header) for i := 0; i < hunkIndex; i++ { @@ -65,7 +64,7 @@ func (self *Patch) HunkStartIdx(hunkIndex int) int { // Returns the patch line index of the last line in the given hunk func (self *Patch) HunkEndIdx(hunkIndex int) int { - hunkIndex = utils.Clamp(hunkIndex, 0, len(self.hunks)-1) + hunkIndex = lo.Clamp(hunkIndex, 0, len(self.hunks)-1) return self.HunkStartIdx(hunkIndex) + self.hunks[hunkIndex].lineCount() - 1 } @@ -118,7 +117,7 @@ func (self *Patch) HunkContainingLine(idx int) int { // Returns the patch line index of the next change (i.e. addition or deletion). func (self *Patch) GetNextChangeIdx(idx int) int { - idx = utils.Clamp(idx, 0, self.LineCount()-1) + idx = lo.Clamp(idx, 0, self.LineCount()-1) lines := self.Lines() diff --git a/pkg/gui/context/list_renderer.go b/pkg/gui/context/list_renderer.go index 06fc69b0c0e..9bde5fb4b22 100644 --- a/pkg/gui/context/list_renderer.go +++ b/pkg/gui/context/list_renderer.go @@ -52,7 +52,7 @@ func (self *ListRenderer) ModelIndexToViewIndex(modelIndex int) int { } func (self *ListRenderer) ViewIndexToModelIndex(viewIndex int) int { - viewIndex = utils.Clamp(viewIndex, 0, self.list.Len()+self.numNonModelItems) + viewIndex = lo.Clamp(viewIndex, 0, self.list.Len()+self.numNonModelItems) if self.modelIndicesByViewIndex != nil { return self.modelIndicesByViewIndex[viewIndex] } diff --git a/pkg/gui/context/traits/list_cursor.go b/pkg/gui/context/traits/list_cursor.go index 31f3de7a40f..a8ff8971638 100644 --- a/pkg/gui/context/traits/list_cursor.go +++ b/pkg/gui/context/traits/list_cursor.go @@ -3,6 +3,7 @@ package traits import ( "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" + "github.com/samber/lo" ) type RangeSelectMode int @@ -85,7 +86,7 @@ func (self *ListCursor) clampValue(value int) int { clampedValue := -1 length := self.getLength() if length > 0 { - clampedValue = utils.Clamp(value, 0, length-1) + clampedValue = lo.Clamp(value, 0, length-1) } return clampedValue diff --git a/pkg/gui/mergeconflicts/state.go b/pkg/gui/mergeconflicts/state.go index a3dbcff3abd..047241353e4 100644 --- a/pkg/gui/mergeconflicts/state.go +++ b/pkg/gui/mergeconflicts/state.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/jesseduffield/lazygit/pkg/utils" + "github.com/samber/lo" ) // State represents the selection state of the merge conflict context. @@ -37,14 +38,14 @@ func (s *State) setConflictIndex(index int) { if len(s.conflicts) == 0 { s.conflictIndex = 0 } else { - s.conflictIndex = utils.Clamp(index, 0, len(s.conflicts)-1) + s.conflictIndex = lo.Clamp(index, 0, len(s.conflicts)-1) } s.setSelectionIndex(s.selectionIndex) } func (s *State) setSelectionIndex(index int) { if selections := s.availableSelections(); len(selections) != 0 { - s.selectionIndex = utils.Clamp(index, 0, len(selections)-1) + s.selectionIndex = lo.Clamp(index, 0, len(selections)-1) } } diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index ceb8f0dacd4..c7118ff5c20 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -39,15 +39,6 @@ func SortRange(x int, y int) (int, int) { return y, x } -func Clamp(x int, min int, max int) int { - if x < min { - return min - } else if x > max { - return max - } - return x -} - func AsJson(i interface{}) string { bytes, _ := json.MarshalIndent(i, "", " ") return string(bytes) From 7b96615792ab976dd625fc96fd00505ae8c44f25 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 3 Apr 2025 18:00:13 +0200 Subject: [PATCH 03/16] Add IGuiCommon.GetViewBufferManagerForView So that we don't have to pass the map to controllers. --- pkg/gui/controllers.go | 2 +- .../controllers/vertical_scroll_controller.go | 21 +++++++------------ pkg/gui/global_handlers.go | 2 +- pkg/gui/gui.go | 9 ++++++++ pkg/gui/gui_common.go | 5 +++++ pkg/gui/layout.go | 4 ++-- pkg/gui/types/common.go | 4 ++++ 7 files changed, 30 insertions(+), 17 deletions(-) diff --git a/pkg/gui/controllers.go b/pkg/gui/controllers.go index a808d368f51..a6391c6ab9a 100644 --- a/pkg/gui/controllers.go +++ b/pkg/gui/controllers.go @@ -180,7 +180,7 @@ func (gui *Gui) resetHelpersAndControllers() { globalController := controllers.NewGlobalController(common) contextLinesController := controllers.NewContextLinesController(common) renameSimilarityThresholdController := controllers.NewRenameSimilarityThresholdController(common) - verticalScrollControllerFactory := controllers.NewVerticalScrollControllerFactory(common, &gui.viewBufferManagerMap) + verticalScrollControllerFactory := controllers.NewVerticalScrollControllerFactory(common) branchesController := controllers.NewBranchesController(common) gitFlowController := controllers.NewGitFlowController(common) diff --git a/pkg/gui/controllers/vertical_scroll_controller.go b/pkg/gui/controllers/vertical_scroll_controller.go index b168e86a8b9..b88574451cb 100644 --- a/pkg/gui/controllers/vertical_scroll_controller.go +++ b/pkg/gui/controllers/vertical_scroll_controller.go @@ -3,29 +3,25 @@ package controllers import ( "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/gui/types" - "github.com/jesseduffield/lazygit/pkg/tasks" ) // given we have no fields here, arguably we shouldn't even need this factory // struct, but we're maintaining consistency with the other files. type VerticalScrollControllerFactory struct { - c *ControllerCommon - viewBufferManagerMap *map[string]*tasks.ViewBufferManager + c *ControllerCommon } -func NewVerticalScrollControllerFactory(c *ControllerCommon, viewBufferManagerMap *map[string]*tasks.ViewBufferManager) *VerticalScrollControllerFactory { +func NewVerticalScrollControllerFactory(c *ControllerCommon) *VerticalScrollControllerFactory { return &VerticalScrollControllerFactory{ - c: c, - viewBufferManagerMap: viewBufferManagerMap, + c: c, } } func (self *VerticalScrollControllerFactory) Create(context types.Context) types.IController { return &VerticalScrollController{ - baseController: baseController{}, - c: self.c, - context: context, - viewBufferManagerMap: self.viewBufferManagerMap, + baseController: baseController{}, + c: self.c, + context: context, } } @@ -33,8 +29,7 @@ type VerticalScrollController struct { baseController c *ControllerCommon - context types.Context - viewBufferManagerMap *map[string]*tasks.ViewBufferManager + context types.Context } func (self *VerticalScrollController) Context() types.Context { @@ -74,7 +69,7 @@ func (self *VerticalScrollController) HandleScrollDown() error { scrollHeight := self.c.UserConfig().Gui.ScrollHeight self.context.GetViewTrait().ScrollDown(scrollHeight) - if manager, ok := (*self.viewBufferManagerMap)[self.context.GetViewName()]; ok { + if manager := self.c.GetViewBufferManagerForView(self.context.GetView()); manager != nil { manager.ReadLines(scrollHeight) } diff --git a/pkg/gui/global_handlers.go b/pkg/gui/global_handlers.go index 0301cf63edb..a5aabb3610e 100644 --- a/pkg/gui/global_handlers.go +++ b/pkg/gui/global_handlers.go @@ -20,7 +20,7 @@ func (gui *Gui) scrollDownView(view *gocui.View) { scrollHeight := gui.c.UserConfig().Gui.ScrollHeight view.ScrollDown(scrollHeight) - if manager, ok := gui.viewBufferManagerMap[view.Name()]; ok { + if manager := gui.getViewBufferManagerForView(view); manager != nil { manager.ReadLines(scrollHeight) } } diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 42922611a42..90a2a64d48f 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -578,6 +578,15 @@ func (gui *Gui) resetState(startArgs appTypes.StartArgs) types.Context { return initialContext(contextTree, startArgs) } +func (self *Gui) getViewBufferManagerForView(view *gocui.View) *tasks.ViewBufferManager { + manager, ok := self.viewBufferManagerMap[view.Name()] + if !ok { + return nil + } + + return manager +} + func initialWindowViewNameMap(contextTree *context.ContextTree) *utils.ThreadSafeMap[string, string] { result := utils.NewThreadSafeMap[string, string]() diff --git a/pkg/gui/gui_common.go b/pkg/gui/gui_common.go index dfa4be52f3d..1465a1ce301 100644 --- a/pkg/gui/gui_common.go +++ b/pkg/gui/gui_common.go @@ -7,6 +7,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/types" + "github.com/jesseduffield/lazygit/pkg/tasks" ) // hacking this by including the gui struct for now until we split more things out @@ -128,6 +129,10 @@ func (self *guiCommon) MainViewPairs() types.MainViewPairs { } } +func (self *guiCommon) GetViewBufferManagerForView(view *gocui.View) *tasks.ViewBufferManager { + return self.gui.getViewBufferManagerForView(view) +} + func (self *guiCommon) State() types.IStateAccessor { return self.gui.stateAccessor } diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index f2e48c674d1..53e8247783c 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -32,10 +32,10 @@ func (gui *Gui) layout(g *gocui.Gui) error { newMainHeight := viewDimensions["main"].Y1 - viewDimensions["main"].Y0 + 1 heightDiff := newMainHeight - prevMainHeight if heightDiff > 0 { - if manager, ok := gui.viewBufferManagerMap["main"]; ok { + if manager := gui.getViewBufferManagerForView(gui.Views.Main); manager != nil { manager.ReadLines(heightDiff) } - if manager, ok := gui.viewBufferManagerMap["secondary"]; ok { + if manager := gui.getViewBufferManagerForView(gui.Views.Secondary); manager != nil { manager.ReadLines(heightDiff) } } diff --git a/pkg/gui/types/common.go b/pkg/gui/types/common.go index e01c664230b..863d7c2004e 100644 --- a/pkg/gui/types/common.go +++ b/pkg/gui/types/common.go @@ -8,6 +8,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/common" "github.com/jesseduffield/lazygit/pkg/config" + "github.com/jesseduffield/lazygit/pkg/tasks" "github.com/jesseduffield/lazygit/pkg/utils" "github.com/sasha-s/go-deadlock" "gopkg.in/ozeidan/fuzzy-patricia.v3/patricia" @@ -48,6 +49,9 @@ type IGuiCommon interface { // used purely for the sake of RenderToMainViews to provide the pair of main views we want to render to MainViewPairs() MainViewPairs + // return the view buffer manager for the given view, or nil if it doesn't have one + GetViewBufferManagerForView(view *gocui.View) *tasks.ViewBufferManager + // returns true if command completed successfully RunSubprocess(cmdObj oscommands.ICmdObj) (bool, error) RunSubprocessAndRefresh(oscommands.ICmdObj) error From 2a2705dcc3eb8a0734200110862f672b53ef156e Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 25 Mar 2025 12:30:08 +0100 Subject: [PATCH 04/16] Always render diffs to the main/secondary context pair, even for files Previously we would render the diff for a directory to the main/secondary pair, but a diff for a file to the staging/stagingSecondary pair. (And similar for commit files: main/secondary for directories, but patchBuilding/patchBuildingSecondary for files.) I always found this confusing and couldn't really understand why we are doing this; but now it gets in my way because I want to attach a controller to main/secondary so that they can be focused. So change it to always use the main context pair for everything we render from a side panel. --- .../controllers/commits_files_controller.go | 9 ++------- pkg/gui/controllers/files_controller.go | 19 +------------------ pkg/integration/tests/patch_building/apply.go | 2 +- .../tests/patch_building/apply_in_reverse.go | 2 +- .../apply_in_reverse_with_conflict.go | 4 ++-- .../patch_building/move_range_to_index.go | 4 ++-- .../tests/patch_building/move_to_index.go | 2 +- .../patch_building/move_to_index_partial.go | 2 +- ..._to_index_works_even_if_noprefix_is_set.go | 2 +- .../patch_building/remove_from_commit.go | 2 +- .../tests/stash/stash_staged_partial_file.go | 3 ++- 11 files changed, 15 insertions(+), 36 deletions(-) diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index 77037513e1a..6f28f85e08a 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -138,7 +138,7 @@ func (self *CommitFilesController) GetKeybindings(opts types.KeybindingsOpts) [] func (self *CommitFilesController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding { return []*gocui.ViewMouseBinding{ { - ViewName: "patchBuilding", + ViewName: "main", Key: gocui.MouseLeft, Handler: self.onClickMain, FocusedView: self.context().GetViewName(), @@ -163,13 +163,8 @@ func (self *CommitFilesController) GetOnRenderToMain() func() { cmdObj := self.c.Git().WorkingTree.ShowFileDiffCmdObj(from, to, reverse, node.GetPath(), false) task := types.NewRunPtyTask(cmdObj.GetCmd()) - pair := self.c.MainViewPairs().Normal - if node.File != nil { - pair = self.c.MainViewPairs().PatchBuilding - } - self.c.RenderToMainViews(types.RefreshMainOpts{ - Pair: pair, + Pair: self.c.MainViewPairs().Normal, Main: &types.ViewUpdateOpts{ Title: self.c.Tr.Patch, SubTitle: self.c.Helpers().Diff.IgnoringWhitespaceSubTitle(), diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 3614e232e86..2d551d6ec9d 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -214,12 +214,6 @@ func (self *FilesController) GetMouseKeybindings(opts types.KeybindingsOpts) []* Handler: self.onClickMain, FocusedView: self.context().GetViewName(), }, - { - ViewName: "patchBuilding", - Key: gocui.MouseLeft, - Handler: self.onClickMain, - FocusedView: self.context().GetViewName(), - }, { ViewName: "mergeConflicts", Key: gocui.MouseLeft, @@ -232,12 +226,6 @@ func (self *FilesController) GetMouseKeybindings(opts types.KeybindingsOpts) []* Handler: self.onClickSecondary, FocusedView: self.context().GetViewName(), }, - { - ViewName: "patchBuildingSecondary", - Key: gocui.MouseLeft, - Handler: self.onClickSecondary, - FocusedView: self.context().GetViewName(), - }, } } @@ -304,11 +292,6 @@ func (self *FilesController) GetOnRenderToMain() func() { self.c.Helpers().MergeConflicts.ResetMergeState() - pair := self.c.MainViewPairs().Normal - if node.File != nil { - pair = self.c.MainViewPairs().Staging - } - split := self.c.UserConfig().Gui.SplitDiff == "always" || (node.GetHasUnstagedChanges() && node.GetHasStagedChanges()) mainShowsStaged := !split && node.GetHasStagedChanges() @@ -318,7 +301,7 @@ func (self *FilesController) GetOnRenderToMain() func() { title = self.c.Tr.StagedChanges } refreshOpts := types.RefreshMainOpts{ - Pair: pair, + Pair: self.c.MainViewPairs().Normal, Main: &types.ViewUpdateOpts{ Task: types.NewRunPtyTask(cmdObj.GetCmd()), SubTitle: self.c.Helpers().Diff.IgnoringWhitespaceSubTitle(), diff --git a/pkg/integration/tests/patch_building/apply.go b/pkg/integration/tests/patch_building/apply.go index 8774f07d71f..533ad1e23a0 100644 --- a/pkg/integration/tests/patch_building/apply.go +++ b/pkg/integration/tests/patch_building/apply.go @@ -48,7 +48,7 @@ var Apply = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Information().Content(Contains("Building patch")) - t.Views().PatchBuildingSecondary().Content(Contains("second line")) + t.Views().Secondary().Content(Contains("second line")) t.Common().SelectPatchOption(MatchesRegexp(`Apply patch$`)) diff --git a/pkg/integration/tests/patch_building/apply_in_reverse.go b/pkg/integration/tests/patch_building/apply_in_reverse.go index f15d4c35c0d..f2aa6b3a83f 100644 --- a/pkg/integration/tests/patch_building/apply_in_reverse.go +++ b/pkg/integration/tests/patch_building/apply_in_reverse.go @@ -35,7 +35,7 @@ var ApplyInReverse = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Information().Content(Contains("Building patch")) - t.Views().PatchBuildingSecondary().Content(Contains("+file1 content")) + t.Views().Secondary().Content(Contains("+file1 content")) t.Common().SelectPatchOption(Contains("Apply patch in reverse")) diff --git a/pkg/integration/tests/patch_building/apply_in_reverse_with_conflict.go b/pkg/integration/tests/patch_building/apply_in_reverse_with_conflict.go index 78367cc84bc..1a09cea7af9 100644 --- a/pkg/integration/tests/patch_building/apply_in_reverse_with_conflict.go +++ b/pkg/integration/tests/patch_building/apply_in_reverse_with_conflict.go @@ -44,13 +44,13 @@ var ApplyInReverseWithConflict = NewIntegrationTest(NewIntegrationTestArgs{ Tap(func() { t.Views().Information().Content(Contains("Building patch")) - t.Views().PatchBuildingSecondary().Content( + t.Views().Secondary().Content( Contains("+more file1 content")) }). SelectNextItem(). PressPrimaryAction() - t.Views().PatchBuildingSecondary().Content( + t.Views().Secondary().Content( Contains("+more file1 content").Contains("+more file2 content")) t.Common().SelectPatchOption(Contains("Apply patch in reverse")) diff --git a/pkg/integration/tests/patch_building/move_range_to_index.go b/pkg/integration/tests/patch_building/move_range_to_index.go index fbacb50a51a..c8d379c97dc 100644 --- a/pkg/integration/tests/patch_building/move_range_to_index.go +++ b/pkg/integration/tests/patch_building/move_range_to_index.go @@ -43,8 +43,8 @@ var MoveRangeToIndex = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Information().Content(Contains("Building patch")) - t.Views().PatchBuildingSecondary().Content(Contains("second line")) - t.Views().PatchBuildingSecondary().Content(Contains("file two content")) + t.Views().Secondary().Content(Contains("second line")) + t.Views().Secondary().Content(Contains("file two content")) t.Common().SelectPatchOption(MatchesRegexp(`Move patch out into index$`)) diff --git a/pkg/integration/tests/patch_building/move_to_index.go b/pkg/integration/tests/patch_building/move_to_index.go index af2e867c7dd..6eca8865f55 100644 --- a/pkg/integration/tests/patch_building/move_to_index.go +++ b/pkg/integration/tests/patch_building/move_to_index.go @@ -35,7 +35,7 @@ var MoveToIndex = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Information().Content(Contains("Building patch")) - t.Views().PatchBuildingSecondary().Content(Contains("+file1 content")) + t.Views().Secondary().Content(Contains("+file1 content")) t.Common().SelectPatchOption(Contains("Move patch out into index")) diff --git a/pkg/integration/tests/patch_building/move_to_index_partial.go b/pkg/integration/tests/patch_building/move_to_index_partial.go index f3515520260..827a3aedb84 100644 --- a/pkg/integration/tests/patch_building/move_to_index_partial.go +++ b/pkg/integration/tests/patch_building/move_to_index_partial.go @@ -53,7 +53,7 @@ var MoveToIndexPartial = NewIntegrationTest(NewIntegrationTestArgs{ Tap(func() { t.Views().Information().Content(Contains("Building patch")) - t.Views().PatchBuildingSecondary(). + t.Views().Secondary(). ContainsLines( Contains(`-first line`), Contains(`+first line2`), diff --git a/pkg/integration/tests/patch_building/move_to_index_works_even_if_noprefix_is_set.go b/pkg/integration/tests/patch_building/move_to_index_works_even_if_noprefix_is_set.go index 391223c6099..8c2ba84b019 100644 --- a/pkg/integration/tests/patch_building/move_to_index_works_even_if_noprefix_is_set.go +++ b/pkg/integration/tests/patch_building/move_to_index_works_even_if_noprefix_is_set.go @@ -33,7 +33,7 @@ var MoveToIndexWorksEvenIfNoprefixIsSet = NewIntegrationTest(NewIntegrationTestA ). PressPrimaryAction() - t.Views().PatchBuildingSecondary().Content(Contains("+file1 content")) + t.Views().Secondary().Content(Contains("+file1 content")) t.Common().SelectPatchOption(Contains("Move patch out into index")) diff --git a/pkg/integration/tests/patch_building/remove_from_commit.go b/pkg/integration/tests/patch_building/remove_from_commit.go index bfa0925d6ba..fbd78fcf76d 100644 --- a/pkg/integration/tests/patch_building/remove_from_commit.go +++ b/pkg/integration/tests/patch_building/remove_from_commit.go @@ -35,7 +35,7 @@ var RemoveFromCommit = NewIntegrationTest(NewIntegrationTestArgs{ t.Views().Information().Content(Contains("Building patch")) - t.Views().PatchBuildingSecondary().Content(Contains("+file1 content")) + t.Views().Secondary().Content(Contains("+file1 content")) t.Common().SelectPatchOption(Contains("Remove patch from original commit")) diff --git a/pkg/integration/tests/stash/stash_staged_partial_file.go b/pkg/integration/tests/stash/stash_staged_partial_file.go index 8219b55d335..5337eaee2fe 100644 --- a/pkg/integration/tests/stash/stash_staged_partial_file.go +++ b/pkg/integration/tests/stash/stash_staged_partial_file.go @@ -58,11 +58,12 @@ var StashStagedPartialFile = NewIntegrationTest(NewIntegrationTestArgs{ ) t.Views().Files(). + Focus(). Lines( Contains("file-staged"), ) - t.Views().Staging(). + t.Views().Main(). Content( Contains(" line1\n line2\n line3\n-line4\n+line4 mod"), ) From b7b7c65999373e9a95198c038f042cf84dd08147 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 25 Mar 2025 14:31:03 +0100 Subject: [PATCH 05/16] Add class MainContext In this state of the code it isn't worth much because it's not any more than a SimpleContext, but we'll add things to it later in the branch. --- pkg/gui/context/context.go | 4 +-- pkg/gui/context/main_context.go | 29 ++++++++++++++++++++ pkg/gui/context/setup.go | 48 +++++++++++---------------------- 3 files changed, 47 insertions(+), 34 deletions(-) create mode 100644 pkg/gui/context/main_context.go diff --git a/pkg/gui/context/context.go b/pkg/gui/context/context.go index e3584a8af11..a993cf253bc 100644 --- a/pkg/gui/context/context.go +++ b/pkg/gui/context/context.go @@ -98,8 +98,8 @@ type ContextTree struct { SubCommits *SubCommitsContext Stash *StashContext Suggestions *SuggestionsContext - Normal types.Context - NormalSecondary types.Context + Normal *MainContext + NormalSecondary *MainContext Staging *PatchExplorerContext StagingSecondary *PatchExplorerContext CustomPatchBuilder *PatchExplorerContext diff --git a/pkg/gui/context/main_context.go b/pkg/gui/context/main_context.go new file mode 100644 index 00000000000..3749d1d1a8c --- /dev/null +++ b/pkg/gui/context/main_context.go @@ -0,0 +1,29 @@ +package context + +import ( + "github.com/jesseduffield/gocui" + "github.com/jesseduffield/lazygit/pkg/gui/types" +) + +type MainContext struct { + *SimpleContext +} + +func NewMainContext( + view *gocui.View, + windowName string, + key types.ContextKey, +) *MainContext { + ctx := &MainContext{ + SimpleContext: NewSimpleContext( + NewBaseContext(NewBaseContextOpts{ + Kind: types.MAIN_CONTEXT, + View: view, + WindowName: windowName, + Key: key, + Focusable: false, + })), + } + + return ctx +} diff --git a/pkg/gui/context/setup.go b/pkg/gui/context/setup.go index ec14a502898..33e67fda555 100644 --- a/pkg/gui/context/setup.go +++ b/pkg/gui/context/setup.go @@ -25,38 +25,22 @@ func NewContextTree(c *ContextCommon) *ContextTree { Focusable: true, }), ), - Files: NewWorkingTreeContext(c), - Submodules: NewSubmodulesContext(c), - Menu: NewMenuContext(c), - Remotes: NewRemotesContext(c), - Worktrees: NewWorktreesContext(c), - RemoteBranches: NewRemoteBranchesContext(c), - LocalCommits: NewLocalCommitsContext(c), - CommitFiles: commitFilesContext, - ReflogCommits: NewReflogCommitsContext(c), - SubCommits: NewSubCommitsContext(c), - Branches: NewBranchesContext(c), - Tags: NewTagsContext(c), - Stash: NewStashContext(c), - Suggestions: NewSuggestionsContext(c), - Normal: NewSimpleContext( - NewBaseContext(NewBaseContextOpts{ - Kind: types.MAIN_CONTEXT, - View: c.Views().Main, - WindowName: "main", - Key: NORMAL_MAIN_CONTEXT_KEY, - Focusable: false, - }), - ), - NormalSecondary: NewSimpleContext( - NewBaseContext(NewBaseContextOpts{ - Kind: types.MAIN_CONTEXT, - View: c.Views().Secondary, - WindowName: "secondary", - Key: NORMAL_SECONDARY_CONTEXT_KEY, - Focusable: false, - }), - ), + Files: NewWorkingTreeContext(c), + Submodules: NewSubmodulesContext(c), + Menu: NewMenuContext(c), + Remotes: NewRemotesContext(c), + Worktrees: NewWorktreesContext(c), + RemoteBranches: NewRemoteBranchesContext(c), + LocalCommits: NewLocalCommitsContext(c), + CommitFiles: commitFilesContext, + ReflogCommits: NewReflogCommitsContext(c), + SubCommits: NewSubCommitsContext(c), + Branches: NewBranchesContext(c), + Tags: NewTagsContext(c), + Stash: NewStashContext(c), + Suggestions: NewSuggestionsContext(c), + Normal: NewMainContext(c.Views().Main, "main", NORMAL_MAIN_CONTEXT_KEY), + NormalSecondary: NewMainContext(c.Views().Secondary, "secondary", NORMAL_SECONDARY_CONTEXT_KEY), Staging: NewPatchExplorerContext( c.Views().Staging, "main", From 1a93b2324b5da9a7884406a3a2aa0bdb95398515 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 25 Mar 2025 14:11:52 +0100 Subject: [PATCH 06/16] Allow focussing the main view In this commit this is only possible by pressing '0' in a side panel; we'll add mouse clicking later in the branch. Also, you can't really do anything in the focused view except press escape to leave it again. We'll add some more functionality in a following commit. --- pkg/config/user_config.go | 2 + pkg/gui/context/main_context.go | 11 ++-- pkg/gui/controllers.go | 28 +++++++++ pkg/gui/controllers/main_view_controller.go | 63 +++++++++++++++++++ .../switch_to_focused_main_view_controller.go | 49 +++++++++++++++ pkg/i18n/english.go | 4 ++ 6 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 pkg/gui/controllers/main_view_controller.go create mode 100644 pkg/gui/controllers/switch_to_focused_main_view_controller.go diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index 165de3e3427..49e8e13c8e2 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -395,6 +395,7 @@ type KeybindingUniversalConfig struct { NextBlockAlt2 string `yaml:"nextBlock-alt2"` PrevBlockAlt2 string `yaml:"prevBlock-alt2"` JumpToBlock []string `yaml:"jumpToBlock"` + FocusMainView string `yaml:"focusMainView"` NextMatch string `yaml:"nextMatch"` PrevMatch string `yaml:"prevMatch"` StartSearch string `yaml:"startSearch"` @@ -876,6 +877,7 @@ func GetDefaultConfig() *UserConfig { PrevBlockAlt2: "", NextBlockAlt2: "", JumpToBlock: []string{"1", "2", "3", "4", "5"}, + FocusMainView: "0", NextMatch: "n", PrevMatch: "N", StartSearch: "/", diff --git a/pkg/gui/context/main_context.go b/pkg/gui/context/main_context.go index 3749d1d1a8c..7ca6ffdd154 100644 --- a/pkg/gui/context/main_context.go +++ b/pkg/gui/context/main_context.go @@ -17,11 +17,12 @@ func NewMainContext( ctx := &MainContext{ SimpleContext: NewSimpleContext( NewBaseContext(NewBaseContextOpts{ - Kind: types.MAIN_CONTEXT, - View: view, - WindowName: windowName, - Key: key, - Focusable: false, + Kind: types.MAIN_CONTEXT, + View: view, + WindowName: windowName, + Key: key, + Focusable: true, + HighlightOnFocus: false, })), } diff --git a/pkg/gui/controllers.go b/pkg/gui/controllers.go index a6391c6ab9a..6abd93406d1 100644 --- a/pkg/gui/controllers.go +++ b/pkg/gui/controllers.go @@ -189,6 +189,8 @@ func (gui *Gui) resetHelpersAndControllers() { patchExplorerControllerFactory := controllers.NewPatchExplorerControllerFactory(common) stagingController := controllers.NewStagingController(common, gui.State.Contexts.Staging, gui.State.Contexts.StagingSecondary, false) stagingSecondaryController := controllers.NewStagingController(common, gui.State.Contexts.StagingSecondary, gui.State.Contexts.Staging, true) + mainViewController := controllers.NewMainViewController(common, gui.State.Contexts.Normal, gui.State.Contexts.NormalSecondary) + secondaryViewController := controllers.NewMainViewController(common, gui.State.Contexts.NormalSecondary, gui.State.Contexts.Normal) patchBuildingController := controllers.NewPatchBuildingController(common) snakeController := controllers.NewSnakeController(common) reflogCommitsController := controllers.NewReflogCommitsController(common) @@ -263,6 +265,22 @@ func (gui *Gui) resetHelpersAndControllers() { )) } + for _, context := range []types.Context{ + gui.State.Contexts.Files, + gui.State.Contexts.Branches, + gui.State.Contexts.RemoteBranches, + gui.State.Contexts.Tags, + gui.State.Contexts.LocalCommits, + gui.State.Contexts.ReflogCommits, + gui.State.Contexts.SubCommits, + gui.State.Contexts.CommitFiles, + gui.State.Contexts.Stash, + } { + controllers.AttachControllers(context, controllers.NewSwitchToFocusedMainViewController( + common, context, + )) + } + for _, context := range []controllers.ContainsCommits{ gui.State.Contexts.LocalCommits, gui.State.Contexts.ReflogCommits, @@ -306,6 +324,16 @@ func (gui *Gui) resetHelpersAndControllers() { mergeConflictsController, ) + controllers.AttachControllers(gui.State.Contexts.Normal, + mainViewController, + verticalScrollControllerFactory.Create(gui.State.Contexts.Normal), + ) + + controllers.AttachControllers(gui.State.Contexts.NormalSecondary, + secondaryViewController, + verticalScrollControllerFactory.Create(gui.State.Contexts.NormalSecondary), + ) + controllers.AttachControllers(gui.State.Contexts.Files, filesController, ) diff --git a/pkg/gui/controllers/main_view_controller.go b/pkg/gui/controllers/main_view_controller.go new file mode 100644 index 00000000000..e09cb27c070 --- /dev/null +++ b/pkg/gui/controllers/main_view_controller.go @@ -0,0 +1,63 @@ +package controllers + +import ( + "github.com/jesseduffield/lazygit/pkg/gui/types" +) + +type MainViewController struct { + baseController + c *ControllerCommon + + context types.Context + otherContext types.Context +} + +var _ types.IController = &MainViewController{} + +func NewMainViewController( + c *ControllerCommon, + context types.Context, + otherContext types.Context, +) *MainViewController { + return &MainViewController{ + baseController: baseController{}, + c: c, + context: context, + otherContext: otherContext, + } +} + +func (self *MainViewController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding { + return []*types.Binding{ + { + Key: opts.GetKey(opts.Config.Universal.TogglePanel), + Handler: self.togglePanel, + Description: self.c.Tr.ToggleStagingView, + Tooltip: self.c.Tr.ToggleStagingViewTooltip, + DisplayOnScreen: true, + }, + { + Key: opts.GetKey(opts.Config.Universal.Return), + Handler: self.escape, + Description: self.c.Tr.ExitFocusedMainView, + }, + } +} + +func (self *MainViewController) Context() types.Context { + return self.context +} + +func (self *MainViewController) togglePanel() error { + if self.otherContext.GetView().Visible { + self.otherContext.SetParentContext(self.context.GetParentContext()) + self.c.Context().Push(self.otherContext, types.OnFocusOpts{}) + } + + return nil +} + +func (self *MainViewController) escape() error { + self.c.Context().Pop() + return nil +} diff --git a/pkg/gui/controllers/switch_to_focused_main_view_controller.go b/pkg/gui/controllers/switch_to_focused_main_view_controller.go new file mode 100644 index 00000000000..f2d48448f06 --- /dev/null +++ b/pkg/gui/controllers/switch_to_focused_main_view_controller.go @@ -0,0 +1,49 @@ +package controllers + +import ( + "github.com/jesseduffield/lazygit/pkg/gui/types" +) + +// This controller is for all contexts that can focus their main view. + +var _ types.IController = &SwitchToFocusedMainViewController{} + +type SwitchToFocusedMainViewController struct { + baseController + c *ControllerCommon + context types.Context +} + +func NewSwitchToFocusedMainViewController( + c *ControllerCommon, + context types.Context, +) *SwitchToFocusedMainViewController { + return &SwitchToFocusedMainViewController{ + baseController: baseController{}, + c: c, + context: context, + } +} + +func (self *SwitchToFocusedMainViewController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding { + bindings := []*types.Binding{ + { + Key: opts.GetKey(opts.Config.Universal.FocusMainView), + Handler: self.handleFocusMainView, + Description: self.c.Tr.FocusMainView, + }, + } + + return bindings +} + +func (self *SwitchToFocusedMainViewController) Context() types.Context { + return self.context +} + +func (self *SwitchToFocusedMainViewController) handleFocusMainView() error { + mainViewContext := self.c.Helpers().Window.GetContextForWindow("main") + mainViewContext.SetParentContext(self.context) + self.c.Context().Push(mainViewContext, types.OnFocusOpts{}) + return nil +} diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index ab9f7cdf4cb..53c376293e5 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -264,6 +264,7 @@ type TranslationSet struct { IgnoreFile string ExcludeFile string RefreshFiles string + FocusMainView string Merge string RegularMerge string MergeBranchTooltip string @@ -508,6 +509,7 @@ type TranslationSet struct { EnterCommitFile string EnterCommitFileTooltip string ExitCustomPatchBuilder string + ExitFocusedMainView string EnterUpstream string InvalidUpstream string ReturnToRemotesList string @@ -1328,6 +1330,7 @@ func EnglishTranslationSet() *TranslationSet { IgnoreFile: `Add to .gitignore`, ExcludeFile: `Add to .git/info/exclude`, RefreshFiles: `Refresh files`, + FocusMainView: "Focus main view", Merge: `Merge`, RegularMerge: "Regular merge", MergeBranchTooltip: "View options for merging the selected item into the current branch (regular merge, squash merge)", @@ -1581,6 +1584,7 @@ func EnglishTranslationSet() *TranslationSet { EnterCommitFile: "Enter file / Toggle directory collapsed", EnterCommitFileTooltip: "If a file is selected, enter the file so that you can add/remove individual lines to the custom patch. If a directory is selected, toggle the directory.", ExitCustomPatchBuilder: `Exit custom patch builder`, + ExitFocusedMainView: "Exit back to side panel", EnterUpstream: `Enter upstream as ' '`, InvalidUpstream: "Invalid upstream. Must be in the format ' '", ReturnToRemotesList: `Return to remotes list`, From fa35f661d999182b0a1ae17f8d5e3fe4da8d24ce Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 26 Mar 2025 16:21:50 +0100 Subject: [PATCH 07/16] Update keybindings, config docs, and schema --- docs/Config.md | 1 + docs/keybindings/Keybindings_en.md | 18 ++++++++++++++++++ docs/keybindings/Keybindings_ja.md | 18 ++++++++++++++++++ docs/keybindings/Keybindings_ko.md | 18 ++++++++++++++++++ docs/keybindings/Keybindings_nl.md | 18 ++++++++++++++++++ docs/keybindings/Keybindings_pl.md | 18 ++++++++++++++++++ docs/keybindings/Keybindings_pt.md | 18 ++++++++++++++++++ docs/keybindings/Keybindings_ru.md | 18 ++++++++++++++++++ docs/keybindings/Keybindings_zh-CN.md | 18 ++++++++++++++++++ docs/keybindings/Keybindings_zh-TW.md | 18 ++++++++++++++++++ schema/config.json | 4 ++++ 11 files changed, 167 insertions(+) diff --git a/docs/Config.md b/docs/Config.md index a569418e8f4..9eb146d922f 100644 --- a/docs/Config.md +++ b/docs/Config.md @@ -501,6 +501,7 @@ keybinding: - "3" - "4" - "5" + focusMainView: "0" nextMatch: "n" prevMatch: "N" startSearch: / diff --git a/docs/keybindings/Keybindings_en.md b/docs/keybindings/Keybindings_en.md index 0c328580a27..843c1c89858 100644 --- a/docs/keybindings/Keybindings_en.md +++ b/docs/keybindings/Keybindings_en.md @@ -68,6 +68,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` ` `` | Toggle file tree view | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | Search the current view by text | | ## Commit summary @@ -112,6 +113,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` C `` | Copy (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `` to cancel the selection. | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | View files | | | `` w `` | View worktree options | | | `` / `` | Search the current view by text | | @@ -153,6 +155,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` f `` | Fetch | Fetch changes from remote. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | Search the current view by text | | ## Local branches @@ -178,6 +181,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` R `` | Rename branch | | | `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | View commits | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -204,6 +208,8 @@ If you would instead like to start an interactive rebase from the selected commi |-----|--------|-------------| | `` mouse wheel down (fn+up) `` | Scroll down | | | `` mouse wheel up (fn+down) `` | Scroll up | | +| `` `` | Switch view | Switch to other view (staged/unstaged changes). | +| `` `` | Exit back to side panel | | ## Main panel (patch building) @@ -264,6 +270,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` `` | Reset copied (cherry-picked) commits selection | | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | View commits | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -282,6 +289,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` s `` | Sort order | | | `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | View commits | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -297,6 +305,13 @@ If you would instead like to start an interactive rebase from the selected commi | `` f `` | Fetch | Fetch updates from the remote repository. This retrieves new commits and branches without merging them into your local branches. | | `` / `` | Filter the current view by text | | +## Secondary + +| Key | Action | Info | +|-----|--------|-------------| +| `` `` | Switch view | Switch to other view (staged/unstaged changes). | +| `` `` | Exit back to side panel | | + ## Stash | Key | Action | Info | @@ -306,6 +321,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` d `` | Drop | Remove the stash entry from the stash list. | | `` n `` | New branch | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. | | `` r `` | Rename stash | | +| `` 0 `` | Focus main view | | | `` `` | View files | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -334,6 +350,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` `` | Reset copied (cherry-picked) commits selection | | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | View files | | | `` w `` | View worktree options | | | `` / `` | Search the current view by text | | @@ -363,6 +380,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` P `` | Push tag | Push the selected tag to a remote. You'll be prompted to select a remote. | | `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | View commits | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | diff --git a/docs/keybindings/Keybindings_ja.md b/docs/keybindings/Keybindings_ja.md index 612fd18183a..f02d933d3d6 100644 --- a/docs/keybindings/Keybindings_ja.md +++ b/docs/keybindings/Keybindings_ja.md @@ -51,6 +51,13 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` ] `` | 次のタブ | | | `` [ `` | 前のタブ | | +## Secondary + +| Key | Action | Info | +|-----|--------|-------------| +| `` `` | パネルを切り替え | Switch to other view (staged/unstaged changes). | +| `` `` | Exit back to side panel | | + ## Stash | Key | Action | Info | @@ -60,6 +67,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` d `` | Drop | Remove the stash entry from the stash list. | | `` n `` | 新しいブランチを作成 | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. | | `` r `` | Stashを変更 | | +| `` 0 `` | Focus main view | | | `` `` | View files | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -78,6 +86,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` `` | Reset copied (cherry-picked) commits selection | | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | View files | | | `` w `` | View worktree options | | | `` / `` | 検索を開始 | | @@ -127,6 +136,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` C `` | コミットをコピー (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `` to cancel the selection. | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | View files | | | `` w `` | View worktree options | | | `` / `` | 検索を開始 | | @@ -148,6 +158,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` ` `` | ファイルツリーの表示を切り替え | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | 検索を開始 | | ## コミットメッセージ @@ -192,6 +203,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` P `` | タグをpush | Push the selected tag to a remote. You'll be prompted to select a remote. | | `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | コミットを閲覧 | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -226,6 +238,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` f `` | Fetch | Fetch changes from remote. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | 検索を開始 | | ## ブランチ @@ -251,6 +264,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` R `` | ブランチ名を変更 | | | `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | コミットを閲覧 | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -277,6 +291,8 @@ If you would instead like to start an interactive rebase from the selected commi |-----|--------|-------------| | `` mouse wheel down (fn+up) `` | 下にスクロール | | | `` mouse wheel up (fn+down) `` | 上にスクロール | | +| `` `` | パネルを切り替え | Switch to other view (staged/unstaged changes). | +| `` `` | Exit back to side panel | | ## メインパネル (Patch Building) @@ -348,6 +364,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` s `` | 並び替え | | | `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | コミットを閲覧 | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -366,6 +383,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` `` | Reset copied (cherry-picked) commits selection | | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | コミットを閲覧 | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | diff --git a/docs/keybindings/Keybindings_ko.md b/docs/keybindings/Keybindings_ko.md index 8b2f1c01687..8223e0bc550 100644 --- a/docs/keybindings/Keybindings_ko.md +++ b/docs/keybindings/Keybindings_ko.md @@ -65,10 +65,18 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` `` | Reset cherry-picked (copied) commits selection | | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | 커밋 보기 | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | +## Secondary + +| Key | Action | Info | +|-----|--------|-------------| +| `` `` | 패널 전환 | Switch to other view (staged/unstaged changes). | +| `` `` | Exit back to side panel | | + ## Stash | Key | Action | Info | @@ -78,6 +86,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` d `` | Drop | Remove the stash entry from the stash list. | | `` n `` | 새 브랜치 생성 | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. | | `` r `` | Rename stash | | +| `` 0 `` | Focus main view | | | `` `` | View selected item's files | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -96,6 +105,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` `` | Reset cherry-picked (copied) commits selection | | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | View selected item's files | | | `` w `` | View worktree options | | | `` / `` | 검색 시작 | | @@ -140,6 +150,8 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ |-----|--------|-------------| | `` mouse wheel down (fn+up) `` | 아래로 스크롤 | | | `` mouse wheel up (fn+down) `` | 위로 스크롤 | | +| `` `` | 패널 전환 | Switch to other view (staged/unstaged changes). | +| `` `` | Exit back to side panel | | ## 메인 패널 (Patch Building) @@ -201,6 +213,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` R `` | 브랜치 이름 변경 | | | `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | 커밋 보기 | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -254,6 +267,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` s `` | Sort order | | | `` g `` | View reset options | View reset options (soft/mixed/hard) for resetting onto selected item. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | 커밋 보기 | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -293,6 +307,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` C `` | 커밋을 복사 (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `` to cancel the selection. | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | View selected item's files | | | `` w `` | View worktree options | | | `` / `` | 검색 시작 | | @@ -314,6 +329,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` ` `` | 파일 트리뷰로 전환 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | 검색 시작 | | ## 커밋메시지 @@ -334,6 +350,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` P `` | 태그를 push | Push the selected tag to a remote. You'll be prompted to select a remote. | | `` g `` | 초기화 | View reset options (soft/mixed/hard) for resetting onto selected item. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | 커밋 보기 | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -368,6 +385,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` f `` | Fetch | Fetch changes from remote. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | 검색 시작 | | ## 확인 패널 diff --git a/docs/keybindings/Keybindings_nl.md b/docs/keybindings/Keybindings_nl.md index 469ac8db8e7..c1fa4588765 100644 --- a/docs/keybindings/Keybindings_nl.md +++ b/docs/keybindings/Keybindings_nl.md @@ -81,6 +81,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` f `` | Fetch | Fetch changes from remote. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | Start met zoeken | | ## Bevestigingspaneel @@ -113,6 +114,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` R `` | Hernoem branch | | | `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | Bekijk commits | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -141,6 +143,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` ` `` | Toggle bestandsboom weergave | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | Start met zoeken | | ## Commits @@ -178,6 +181,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` C `` | Kopieer commit (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `` to cancel the selection. | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | Bekijk gecommite bestanden | | | `` w `` | View worktree options | | | `` / `` | Start met zoeken | | @@ -212,6 +216,8 @@ If you would instead like to start an interactive rebase from the selected commi |-----|--------|-------------| | `` mouse wheel down (fn+up) `` | Scroll omlaag | | | `` mouse wheel up (fn+down) `` | Scroll omhoog | | +| `` `` | Ga naar een ander paneel | Switch to other view (staged/unstaged changes). | +| `` `` | Exit back to side panel | | ## Patch bouwen @@ -242,6 +248,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` `` | Reset cherry-picked (gekopieerde) commits selectie | | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | Bekijk commits | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -260,6 +267,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` s `` | Sort order | | | `` g `` | Bekijk reset opties | View reset options (soft/mixed/hard) for resetting onto selected item. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | Bekijk commits | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -275,6 +283,13 @@ If you would instead like to start an interactive rebase from the selected commi | `` f `` | Fetch | Fetch remote | | `` / `` | Filter the current view by text | | +## Secondary + +| Key | Action | Info | +|-----|--------|-------------| +| `` `` | Ga naar een ander paneel | Switch to other view (staged/unstaged changes). | +| `` `` | Exit back to side panel | | + ## Staging | Key | Action | Info | @@ -306,6 +321,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` d `` | Laten vallen | Remove the stash entry from the stash list. | | `` n `` | Nieuwe branch | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. | | `` r `` | Rename stash | | +| `` 0 `` | Focus main view | | | `` `` | Bekijk gecommite bestanden | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -334,6 +350,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` `` | Reset cherry-picked (gekopieerde) commits selectie | | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | Bekijk gecommite bestanden | | | `` w `` | View worktree options | | | `` / `` | Start met zoeken | | @@ -363,6 +380,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` P `` | Push tag | Push the selected tag to a remote. You'll be prompted to select a remote. | | `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | Bekijk commits | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | diff --git a/docs/keybindings/Keybindings_pl.md b/docs/keybindings/Keybindings_pl.md index f940f5ad47c..7c6b26921d0 100644 --- a/docs/keybindings/Keybindings_pl.md +++ b/docs/keybindings/Keybindings_pl.md @@ -86,10 +86,18 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, | `` C `` | Kopiuj (cherry-pick) | Oznacz commit jako skopiowany. Następnie, w widoku lokalnych commitów, możesz nacisnąć `V`, aby wkleić (cherry-pick) skopiowane commity do sprawdzonej gałęzi. W dowolnym momencie możesz nacisnąć ``, aby anulować zaznaczenie. | | `` `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | Wyświetl pliki | | | `` w `` | Zobacz opcje drzewa pracy | | | `` / `` | Szukaj w bieżącym widoku po tekście | | +## Dodatkowy + +| Key | Action | Info | +|-----|--------|-------------| +| `` `` | Przełącz widok | Przełącz na inny widok (zatwierdzone/niezatwierdzone zmiany). | +| `` `` | Exit back to side panel | | + ## Drzewa pracy | Key | Action | Info | @@ -138,6 +146,7 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, | `` R `` | Zmień nazwę gałęzi | | | `` u `` | Pokaż opcje upstream | Pokaż opcje dotyczące upstream gałęzi, np. ustawianie/usuwanie upstream i resetowanie do upstream. | | `` `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | Pokaż commity | | | `` w `` | Zobacz opcje drzewa pracy | | | `` / `` | Filtruj bieżący widok po tekście | | @@ -156,6 +165,8 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, |-----|--------|-------------| | `` mouse wheel down (fn+up) `` | Przewiń w dół | | | `` mouse wheel up (fn+down) `` | Przewiń w górę | | +| `` `` | Przełącz widok | Przełącz na inny widok (zatwierdzone/niezatwierdzone zmiany). | +| `` `` | Exit back to side panel | | ## Panel główny (scalanie) @@ -232,6 +243,7 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, | `` f `` | Pobierz | Pobierz zmiany ze zdalnego serwera. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | Szukaj w bieżącym widoku po tekście | | ## Pliki commita @@ -251,6 +263,7 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, | `` ` `` | Przełącz widok drzewa plików | Przełącz widok plików między płaskim a drzewem. Płaski układ pokazuje wszystkie ścieżki plików na jednej liście, układ drzewa grupuje pliki według katalogów. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | Szukaj w bieżącym widoku po tekście | | ## Podsumowanie commita @@ -274,6 +287,7 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, | `` `` | Resetuj wybrane (cherry-picked) commity | | | `` `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | Pokaż commity | | | `` w `` | Zobacz opcje drzewa pracy | | | `` / `` | Filtruj bieżący widok po tekście | | @@ -287,6 +301,7 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, | `` d `` | Usuń | Usuń wpis schowka z listy schowka. | | `` n `` | Nowa gałąź | Utwórz nową gałąź z wybranego wpisu schowka. Działa poprzez przełączenie git na commit, na którym wpis schowka został utworzony, tworzenie nowej gałęzi z tego commita, a następnie zastosowanie wpisu schowka do nowej gałęzi jako dodatkowego commita. | | `` r `` | Zmień nazwę schowka | | +| `` 0 `` | Focus main view | | | `` `` | Wyświetl pliki | | | `` w `` | Zobacz opcje drzewa pracy | | | `` / `` | Filtruj bieżący widok po tekście | | @@ -315,6 +330,7 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, | `` `` | Resetuj wybrane (cherry-picked) commity | | | `` `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | Wyświetl pliki | | | `` w `` | Zobacz opcje drzewa pracy | | | `` / `` | Szukaj w bieżącym widoku po tekście | | @@ -344,6 +360,7 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, | `` P `` | Wyślij tag | Wyślij wybrany tag do zdalnego. Zostaniesz poproszony o wybranie zdalnego. | | `` g `` | Reset | Wyświetl opcje resetu (miękki/mieszany/twardy) do wybranego elementu. | | `` `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | Pokaż commity | | | `` w `` | Zobacz opcje drzewa pracy | | | `` / `` | Filtruj bieżący widok po tekście | | @@ -373,6 +390,7 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, | `` s `` | Kolejność sortowania | | | `` g `` | Reset | Wyświetl opcje resetu (miękki/mieszany/twardy) do wybranego elementu. | | `` `` | Otwórz zewnętrzne narzędzie różnic (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | Pokaż commity | | | `` w `` | Zobacz opcje drzewa pracy | | | `` / `` | Filtruj bieżący widok po tekście | | diff --git a/docs/keybindings/Keybindings_pt.md b/docs/keybindings/Keybindings_pt.md index 6ea4cb215a5..8cb2d3319dc 100644 --- a/docs/keybindings/Keybindings_pt.md +++ b/docs/keybindings/Keybindings_pt.md @@ -83,6 +83,7 @@ Veja a documentação: | `` f `` | Buscar | Buscar alterações do controle remoto. | | `` - `` | Recolher todos os arquivos | Recolher todos os diretórios na árvore de arquivos | | `` = `` | Expandir todos os arquivos | Expandir todos os diretórios na árvore do arquivo | +| `` 0 `` | Focus main view | | | `` / `` | Search the current view by text | | ## Branches locais @@ -108,6 +109,7 @@ Veja a documentação: | `` R `` | Rename branch | | | `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. | | `` `` | Abrir ferramenta de diff externa (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | View commits | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -126,6 +128,7 @@ Veja a documentação: | `` s `` | Sort order | | | `` g `` | Restaurar | Ver opções de redefinição (soft/mixed/hard) para redefinir para o item selecionado. | | `` `` | Abrir ferramenta de diff externa (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | View commits | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -147,6 +150,7 @@ Veja a documentação: | `` ` `` | Alternar exibição de árvore de arquivo | Alternar a visualização de arquivo entre layout plano e layout de árvore. Layout plano mostra todos os caminhos de arquivo em uma única lista, layout de árvore agrupa arquivos por diretório. | | `` - `` | Recolher todos os arquivos | Recolher todos os diretórios na árvore de arquivos | | `` = `` | Expandir todos os arquivos | Expandir todos os diretórios na árvore do arquivo | +| `` 0 `` | Focus main view | | | `` / `` | Search the current view by text | | ## Commits @@ -184,6 +188,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` C `` | Copiar (cherry-pick) | Marcar commit como copiado. Então, dentro da visualização local de commits, você pode pressionar `V` para colar (cherry-pick) o(s) commit(s) copiado(s) em seu branch de check-out. A qualquer momento você pode pressionar `` para cancelar a seleção. | | `` `` | Abrir ferramenta de diff externa (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | Ver arquivos | | | `` w `` | View worktree options | | | `` / `` | Search the current view by text | | @@ -206,6 +211,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` P `` | Push tag | Push the selected tag to a remote. You'll be prompted to select a remote. | | `` g `` | Restaurar | Ver opções de redefinição (soft/mixed/hard) para redefinir para o item selecionado. | | `` `` | Abrir ferramenta de diff externa (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | View commits | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -224,6 +230,8 @@ If you would instead like to start an interactive rebase from the selected commi |-----|--------|-------------| | `` mouse wheel down (fn+up) `` | Rolar para baixo | | | `` mouse wheel up (fn+down) `` | Rolar para cima | | +| `` `` | Mudar de visão | Alternar para outra visão (staged/não processadas alterações). | +| `` `` | Exit back to side panel | | ## Painel Principal (preparação) @@ -294,6 +302,7 @@ Veja a documentação: | `` `` | Reset copied (cherry-picked) commits selection | | | `` `` | Abrir ferramenta de diff externa (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | View commits | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -309,6 +318,13 @@ Veja a documentação: | `` f `` | Buscar | Fetch updates from the remote repository. This retrieves new commits and branches without merging them into your local branches. | | `` / `` | Filter the current view by text | | +## Secundário + +| Key | Action | Info | +|-----|--------|-------------| +| `` `` | Mudar de visão | Alternar para outra visão (staged/não processadas alterações). | +| `` `` | Exit back to side panel | | + ## Stash | Key | Action | Info | @@ -318,6 +334,7 @@ Veja a documentação: | `` d `` | Descartar | Remova a entrada do stash da lista de armazenamento. | | `` n `` | Nova branch | Criar um novo ramo a partir da entrada de lixo selecionada. Isso funciona verificando o commit do qual a entrada de lixo foi criada, criar um novo branch a partir desse commit e, em seguida, aplicar a entrada de lixo ao novo branch como um commit adicional. | | `` r `` | Renomear o stasj | | +| `` 0 `` | Focus main view | | | `` `` | Ver arquivos | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -346,6 +363,7 @@ Veja a documentação: | `` `` | Reset copied (cherry-picked) commits selection | | | `` `` | Abrir ferramenta de diff externa (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | Ver arquivos | | | `` w `` | View worktree options | | | `` / `` | Search the current view by text | | diff --git a/docs/keybindings/Keybindings_ru.md b/docs/keybindings/Keybindings_ru.md index 28c6a087256..6febfe80b5d 100644 --- a/docs/keybindings/Keybindings_ru.md +++ b/docs/keybindings/Keybindings_ru.md @@ -61,6 +61,13 @@ _Связки клавиш_ | `` d `` | Remove | Remove the selected worktree. This will both delete the worktree's directory, as well as metadata about the worktree in the .git directory. | | `` / `` | Filter the current view by text | | +## Вторичный + +| Key | Action | Info | +|-----|--------|-------------| +| `` `` | Переключиться на другую панель (проиндексированные/непроиндексированные изменения) | Switch to other view (staged/unstaged changes). | +| `` `` | Exit back to side panel | | + ## Главная панель (Индексирование) | Key | Action | Info | @@ -89,6 +96,8 @@ _Связки клавиш_ |-----|--------|-------------| | `` mouse wheel down (fn+up) `` | Прокрутить вниз | | | `` mouse wheel up (fn+down) `` | Прокрутить вверх | | +| `` `` | Переключиться на другую панель (проиндексированные/непроиндексированные изменения) | Switch to other view (staged/unstaged changes). | +| `` `` | Exit back to side panel | | ## Главная панель (Слияние) @@ -135,6 +144,7 @@ _Связки клавиш_ | `` `` | Сбросить отобранную (скопированную | cherry-picked) выборку коммитов | | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | Просмотреть коммиты | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -174,6 +184,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` C `` | Скопировать отобранные коммит (cherry-pick) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `` to cancel the selection. | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | Просмотреть файлы выбранного элемента | | | `` w `` | View worktree options | | | `` / `` | Найти | | @@ -201,6 +212,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` R `` | Переименовать ветку | | | `` u `` | View upstream options | View options relating to the branch's upstream e.g. setting/unsetting the upstream and resetting to the upstream. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | Просмотреть коммиты | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -234,6 +246,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` `` | Сбросить отобранную (скопированную | cherry-picked) выборку коммитов | | | `` `` | Open external diff tool (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | Просмотреть файлы выбранного элемента | | | `` w `` | View worktree options | | | `` / `` | Найти | | @@ -276,6 +289,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` ` `` | Переключить вид дерева файлов | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | Найти | | ## Статус @@ -299,6 +313,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` P `` | Отправить тег | Push the selected tag to a remote. You'll be prompted to select a remote. | | `` g `` | Reset | View reset options (soft/mixed/hard) for resetting onto selected item. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | Просмотреть коммиты | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -317,6 +332,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` s `` | Порядок сортировки | | | `` g `` | Просмотреть параметры сброса | View reset options (soft/mixed/hard) for resetting onto selected item. | | `` `` | Open external diff tool (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | Просмотреть коммиты | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | @@ -362,6 +378,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` f `` | Получить изменения | Fetch changes from remote. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | Найти | | ## Хранилище @@ -373,6 +390,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` d `` | Удалить припрятанные изменения из хранилища | Remove the stash entry from the stash list. | | `` n `` | Новая ветка | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. | | `` r `` | Переименовать хранилище | | +| `` 0 `` | Focus main view | | | `` `` | Просмотреть файлы выбранного элемента | | | `` w `` | View worktree options | | | `` / `` | Filter the current view by text | | diff --git a/docs/keybindings/Keybindings_zh-CN.md b/docs/keybindings/Keybindings_zh-CN.md index bea70be973c..def6f1632d1 100644 --- a/docs/keybindings/Keybindings_zh-CN.md +++ b/docs/keybindings/Keybindings_zh-CN.md @@ -65,6 +65,7 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` `` | 重置已拣选(复制)的提交 | | | `` `` | 使用外部差异比较工具(git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | 查看提交 | | | `` w `` | 查看工作区选项 | | | `` / `` | 通过文本过滤当前视图 | | @@ -83,6 +84,7 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` `` | 重置已拣选(复制)的提交 | | | `` `` | 使用外部差异比较工具(git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | 查看提交的文件 | | | `` w `` | 查看工作区选项 | | | `` / `` | 开始搜索 | | @@ -146,6 +148,7 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` C `` | 复制提交(拣选) | 标记提交为已复制。然后,在本地提交视图中,你可以按 `V` (Cherry-Pick) 将已复制的提交粘贴到已检出的分支中。任何时候都可以按 `` 来取消选择。 | | `` `` | 使用外部差异比较工具(git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | 查看提交的文件 | | | `` w `` | 查看工作区选项 | | | `` / `` | 开始搜索 | | @@ -174,6 +177,7 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` ` `` | 切换文件树视图 | 在平铺部署与树布局之间切换文件视图。平铺布局在一个列表中展示所有文件路径,树布局则根据目录分组展示。 | | `` - `` | 折叠全部文件 | 折叠文件树中的全部目录 | | `` = `` | 展开全部文件 | 展开文件树中的全部目录 | +| `` 0 `` | Focus main view | | | `` / `` | 开始搜索 | | ## 文件 @@ -206,6 +210,7 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` f `` | 抓取 | 从远程获取变更 | | `` - `` | 折叠全部文件 | 折叠文件树中的全部目录 | | `` = `` | 展开全部文件 | 展开文件树中的全部目录 | +| `` 0 `` | Focus main view | | | `` / `` | 开始搜索 | | ## 本地分支 @@ -231,6 +236,7 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` R `` | 重命名分支 | | | `` u `` | 查看上游选项 | 查看与分支上游相关的选项,例如设置/取消设置上游和重置为上游。 | | `` `` | 使用外部差异比较工具(git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | 查看提交 | | | `` w `` | 查看工作区选项 | | | `` / `` | 通过文本过滤当前视图 | | @@ -261,10 +267,18 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` P `` | 推送标签 | 推送选择的标签到远端。你将在弹窗中选择一个远端。 | | `` g `` | 重置 | 查看重置选项 (soft/mixed/hard) 用于重置到选择项 | | `` `` | 使用外部差异比较工具(git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | 查看提交 | | | `` w `` | 查看工作区选项 | | | `` / `` | 通过文本过滤当前视图 | | +## 次要 + +| Key | Action | Info | +|-----|--------|-------------| +| `` `` | 切换到其他面板 | 切换到其他视图(已暂存/未暂存的变更) | +| `` `` | Exit back to side panel | | + ## 正在合并 | Key | Action | Info | @@ -309,6 +323,8 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ |-----|--------|-------------| | `` mouse wheel down (fn+up) `` | 向下滚动 | | | `` mouse wheel up (fn+down) `` | 向上滚动 | | +| `` `` | 切换到其他面板 | 切换到其他视图(已暂存/未暂存的变更) | +| `` `` | Exit back to side panel | | ## 状态 @@ -344,6 +360,7 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` d `` | 删除 | 从贮藏列表中删除该贮藏项 | | `` n `` | 新分支 | 从选定的贮藏项创建一个新分支。这是通过 git 检查创建贮藏项的提交,从该提交创建一个新分支,然后将贮藏项作为附加提交应用到新分支来实现的。 | | `` r `` | 重命名贮藏 | | +| `` 0 `` | Focus main view | | | `` `` | 查看提交的文件 | | | `` w `` | 查看工作区选项 | | | `` / `` | 通过文本过滤当前视图 | | @@ -373,6 +390,7 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` s `` | 排序 | | | `` g `` | 查看重置选项 | 查看重置选项 (soft/mixed/hard) 用于重置到选择项 | | `` `` | 使用外部差异比较工具(git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | 查看提交 | | | `` w `` | 查看工作区选项 | | | `` / `` | 通过文本过滤当前视图 | | diff --git a/docs/keybindings/Keybindings_zh-TW.md b/docs/keybindings/Keybindings_zh-TW.md index 913a76a7c82..b056c92b907 100644 --- a/docs/keybindings/Keybindings_zh-TW.md +++ b/docs/keybindings/Keybindings_zh-TW.md @@ -72,6 +72,8 @@ _說明:`` 表示 Ctrl+B、`` 表示 Alt+B,`B`表示 Shift+B |-----|--------|-------------| | `` mouse wheel down (fn+up) `` | 向下捲動 | | | `` mouse wheel up (fn+down) `` | 向上捲動 | | +| `` `` | 切換至另一個面板 (已預存/未預存更改) | Switch to other view (staged/unstaged changes). | +| `` `` | Exit back to side panel | | ## 主面板(合併) @@ -133,6 +135,7 @@ _說明:`` 表示 Ctrl+B、`` 表示 Alt+B,`B`表示 Shift+B | `` `` | 重設選定的揀選 (複製) 提交 | | | `` `` | 開啟外部差異工具 (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | 檢視所選項目的檔案 | | | `` w `` | 檢視工作目錄選項 | | | `` / `` | 搜尋 | | @@ -196,6 +199,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` C `` | 複製提交 (揀選) | Mark commit as copied. Then, within the local commits view, you can press `V` to paste (cherry-pick) the copied commit(s) into your checked out branch. At any time you can press `` to cancel the selection. | | `` `` | 開啟外部差異工具 (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | 檢視所選項目的檔案 | | | `` w `` | 檢視工作目錄選項 | | | `` / `` | 搜尋 | | @@ -224,6 +228,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` ` `` | 顯示檔案樹狀視圖 | Toggle file view between flat and tree layout. Flat layout shows all file paths in a single list, tree layout groups files by directory. | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | 搜尋 | | ## 收藏 (Stash) @@ -235,6 +240,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` d `` | 捨棄 | Remove the stash entry from the stash list. | | `` n `` | 新分支 | Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit. | | `` r `` | 重新命名收藏 | | +| `` 0 `` | Focus main view | | | `` `` | 檢視所選項目的檔案 | | | `` w `` | 檢視工作目錄選項 | | | `` / `` | 搜尋 | | @@ -253,6 +259,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` `` | 重設選定的揀選 (複製) 提交 | | | `` `` | 開啟外部差異工具 (git difftool) | | | `` * `` | Select commits of current branch | | +| `` 0 `` | Focus main view | | | `` `` | 檢視提交 | | | `` w `` | 檢視工作目錄選項 | | | `` / `` | 搜尋 | | @@ -280,6 +287,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` R `` | 重新命名分支 | | | `` u `` | 檢視遠端設定 | 檢視有關遠端分支的設定(例如重設至遠端) | | `` `` | 開啟外部差異工具 (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | 檢視提交 | | | `` w `` | 檢視工作目錄選項 | | | `` / `` | 搜尋 | | @@ -295,6 +303,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` P `` | 推送標籤 | Push the selected tag to a remote. You'll be prompted to select a remote. | | `` g `` | 重設 | View reset options (soft/mixed/hard) for resetting onto selected item. | | `` `` | 開啟外部差異工具 (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | 檢視提交 | | | `` w `` | 檢視工作目錄選項 | | | `` / `` | 搜尋 | | @@ -329,8 +338,16 @@ If you would instead like to start an interactive rebase from the selected commi | `` f `` | 擷取 | 同步遠端異動 | | `` - `` | Collapse all files | Collapse all directories in the files tree | | `` = `` | Expand all files | Expand all directories in the file tree | +| `` 0 `` | Focus main view | | | `` / `` | 搜尋 | | +## 次要 + +| Key | Action | Info | +|-----|--------|-------------| +| `` `` | 切換至另一個面板 (已預存/未預存更改) | Switch to other view (staged/unstaged changes). | +| `` `` | Exit back to side panel | | + ## 狀態 | Key | Action | Info | @@ -373,6 +390,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` s `` | 排序規則 | | | `` g `` | 檢視重設選項 | View reset options (soft/mixed/hard) for resetting onto selected item. | | `` `` | 開啟外部差異工具 (git difftool) | | +| `` 0 `` | Focus main view | | | `` `` | 檢視提交 | | | `` w `` | 檢視工作目錄選項 | | | `` / `` | 搜尋 | | diff --git a/schema/config.json b/schema/config.json index 1f207af1d7b..7b912a85c9b 100644 --- a/schema/config.json +++ b/schema/config.json @@ -1259,6 +1259,10 @@ "5" ] }, + "focusMainView": { + "type": "string", + "default": "0" + }, "nextMatch": { "type": "string", "default": "n" From 7b17f33e9eae174e70e2beabe6a7eb289a42f05c Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 25 Mar 2025 14:12:21 +0100 Subject: [PATCH 08/16] Add navigation keybindings to focused main view --- pkg/gui/controllers.go | 3 + .../controllers/view_selection_controller.go | 101 ++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 pkg/gui/controllers/view_selection_controller.go diff --git a/pkg/gui/controllers.go b/pkg/gui/controllers.go index 6abd93406d1..e6f6bbb4ee7 100644 --- a/pkg/gui/controllers.go +++ b/pkg/gui/controllers.go @@ -181,6 +181,7 @@ func (gui *Gui) resetHelpersAndControllers() { contextLinesController := controllers.NewContextLinesController(common) renameSimilarityThresholdController := controllers.NewRenameSimilarityThresholdController(common) verticalScrollControllerFactory := controllers.NewVerticalScrollControllerFactory(common) + viewSelectionControllerFactory := controllers.NewViewSelectionControllerFactory(common) branchesController := controllers.NewBranchesController(common) gitFlowController := controllers.NewGitFlowController(common) @@ -327,11 +328,13 @@ func (gui *Gui) resetHelpersAndControllers() { controllers.AttachControllers(gui.State.Contexts.Normal, mainViewController, verticalScrollControllerFactory.Create(gui.State.Contexts.Normal), + viewSelectionControllerFactory.Create(gui.State.Contexts.Normal), ) controllers.AttachControllers(gui.State.Contexts.NormalSecondary, secondaryViewController, verticalScrollControllerFactory.Create(gui.State.Contexts.NormalSecondary), + viewSelectionControllerFactory.Create(gui.State.Contexts.NormalSecondary), ) controllers.AttachControllers(gui.State.Contexts.Files, diff --git a/pkg/gui/controllers/view_selection_controller.go b/pkg/gui/controllers/view_selection_controller.go new file mode 100644 index 00000000000..e961e99793e --- /dev/null +++ b/pkg/gui/controllers/view_selection_controller.go @@ -0,0 +1,101 @@ +package controllers + +import ( + "github.com/jesseduffield/gocui" + "github.com/jesseduffield/lazygit/pkg/gui/types" +) + +type ViewSelectionControllerFactory struct { + c *ControllerCommon +} + +func NewViewSelectionControllerFactory(c *ControllerCommon) *ViewSelectionControllerFactory { + return &ViewSelectionControllerFactory{ + c: c, + } +} + +func (self *ViewSelectionControllerFactory) Create(context types.Context) types.IController { + return &ViewSelectionController{ + baseController: baseController{}, + c: self.c, + context: context, + } +} + +type ViewSelectionController struct { + baseController + c *ControllerCommon + + context types.Context +} + +func (self *ViewSelectionController) Context() types.Context { + return self.context +} + +func (self *ViewSelectionController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding { + return []*types.Binding{ + {Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevItem), Handler: self.handlePrevLine}, + {Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevItemAlt), Handler: self.handlePrevLine}, + {Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextItem), Handler: self.handleNextLine}, + {Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextItemAlt), Handler: self.handleNextLine}, + {Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevPage), Handler: self.handlePrevPage, Description: self.c.Tr.PrevPage}, + {Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextPage), Handler: self.handleNextPage, Description: self.c.Tr.NextPage}, + {Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.GotoTop), Handler: self.handleGotoTop, Description: self.c.Tr.GotoTop, Alternative: ""}, + {Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.GotoBottom), Handler: self.handleGotoBottom, Description: self.c.Tr.GotoBottom, Alternative: ""}, + {Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.GotoTopAlt), Handler: self.handleGotoTop}, + {Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.GotoBottomAlt), Handler: self.handleGotoBottom}, + } +} + +func (self *ViewSelectionController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding { + return []*gocui.ViewMouseBinding{} +} + +func (self *ViewSelectionController) handleLineChange(delta int) { + if delta > 0 { + if manager := self.c.GetViewBufferManagerForView(self.context.GetView()); manager != nil { + manager.ReadLines(delta) + } + } + + v := self.Context().GetView() + if delta < 0 { + v.ScrollUp(-delta) + } else { + v.ScrollDown(delta) + } +} + +func (self *ViewSelectionController) handlePrevLine() error { + self.handleLineChange(-1) + return nil +} + +func (self *ViewSelectionController) handleNextLine() error { + self.handleLineChange(1) + return nil +} + +func (self *ViewSelectionController) handlePrevPage() error { + self.handleLineChange(-self.context.GetViewTrait().PageDelta()) + return nil +} + +func (self *ViewSelectionController) handleNextPage() error { + self.handleLineChange(self.context.GetViewTrait().PageDelta()) + return nil +} + +func (self *ViewSelectionController) handleGotoTop() error { + v := self.Context().GetView() + self.handleLineChange(-v.ViewLinesHeight()) + return nil +} + +func (self *ViewSelectionController) handleGotoBottom() error { + v := self.Context().GetView() + self.handleLineChange(v.ViewLinesHeight()) + return nil +} From 60887eddd0d8ea88aa4b9db91fbb8a561d0a59eb Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 2 Apr 2025 12:11:38 +0200 Subject: [PATCH 09/16] Use readLines channel only for command tasks And only while the task is running. This avoids accumulating lots of blocked goroutines when scrolling a view down more than 1024 times (the capacity of the readLines channel). --- pkg/tasks/tasks.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/pkg/tasks/tasks.go b/pkg/tasks/tasks.go index 9658753495a..6f6960d5f78 100644 --- a/pkg/tasks/tasks.go +++ b/pkg/tasks/tasks.go @@ -91,16 +91,18 @@ func NewViewBufferManager( beforeStart: beforeStart, refreshView: refreshView, onEndOfInput: onEndOfInput, - readLines: make(chan LinesToRead, 1024), + readLines: nil, onNewKey: onNewKey, newGocuiTask: newGocuiTask, } } func (self *ViewBufferManager) ReadLines(n int) { - go utils.Safe(func() { - self.readLines <- LinesToRead{Total: n, InitialRefreshAfter: -1} - }) + if self.readLines != nil { + go utils.Safe(func() { + self.readLines <- LinesToRead{Total: n, InitialRefreshAfter: -1} + }) + } } func (self *ViewBufferManager) NewCmdTask(start func() (*exec.Cmd, io.Reader), prefix string, linesToRead LinesToRead, onDoneFn func()) func(TaskOpts) error { @@ -166,7 +168,6 @@ func (self *ViewBufferManager) NewCmdTask(start func() (*exec.Cmd, io.Reader), p loadingMutex := deadlock.Mutex{} - // not sure if it's the right move to redefine this or not self.readLines = make(chan LinesToRead, 1024) scanner := bufio.NewScanner(r) @@ -274,6 +275,8 @@ func (self *ViewBufferManager) NewCmdTask(start func() (*exec.Cmd, io.Reader), p } } + self.readLines = nil + refreshViewIfStale() if err := cmd.Wait(); err != nil { @@ -349,6 +352,8 @@ func (self *ViewBufferManager) NewTask(f func(TaskOpts) error, key string) error go utils.Safe(func() { defer completeGocuiTask() + self.readLines = nil + self.taskIDMutex.Lock() self.newTaskID++ taskID := self.newTaskID From 2b399a3c36f8160cdf06bfcaa3464eb2ba7eab6b Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 25 Mar 2025 15:17:56 +0100 Subject: [PATCH 10/16] Read all lines from task when jumping to bottom --- .../controllers/view_selection_controller.go | 12 ++++++++-- pkg/tasks/tasks.go | 23 ++++++++++++++++++- pkg/tasks/tasks_test.go | 16 ++++++------- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/pkg/gui/controllers/view_selection_controller.go b/pkg/gui/controllers/view_selection_controller.go index e961e99793e..638c46ba608 100644 --- a/pkg/gui/controllers/view_selection_controller.go +++ b/pkg/gui/controllers/view_selection_controller.go @@ -95,7 +95,15 @@ func (self *ViewSelectionController) handleGotoTop() error { } func (self *ViewSelectionController) handleGotoBottom() error { - v := self.Context().GetView() - self.handleLineChange(v.ViewLinesHeight()) + if manager := self.c.GetViewBufferManagerForView(self.context.GetView()); manager != nil { + manager.ReadToEnd(func() { + self.c.OnUIThread(func() error { + v := self.Context().GetView() + self.handleLineChange(v.ViewLinesHeight()) + return nil + }) + }) + } + return nil } diff --git a/pkg/tasks/tasks.go b/pkg/tasks/tasks.go index 6f6960d5f78..e20e5804533 100644 --- a/pkg/tasks/tasks.go +++ b/pkg/tasks/tasks.go @@ -70,6 +70,9 @@ type LinesToRead struct { // do an initial refresh. Only set for the initial read request; -1 for // subsequent requests. InitialRefreshAfter int + + // Function to call after reading the lines is done + Then func() } func (m *ViewBufferManager) GetTaskKey() string { @@ -105,6 +108,16 @@ func (self *ViewBufferManager) ReadLines(n int) { } } +func (self *ViewBufferManager) ReadToEnd(then func()) { + if self.readLines != nil { + go utils.Safe(func() { + self.readLines <- LinesToRead{Total: -1, InitialRefreshAfter: -1, Then: then} + }) + } else if then != nil { + then() + } +} + func (self *ViewBufferManager) NewCmdTask(start func() (*exec.Cmd, io.Reader), prefix string, linesToRead LinesToRead, onDoneFn func()) func(TaskOpts) error { return func(opts TaskOpts) error { var onDoneOnce sync.Once @@ -234,11 +247,17 @@ func (self *ViewBufferManager) NewCmdTask(start func() (*exec.Cmd, io.Reader), p case <-opts.Stop: break outer case linesToRead := <-self.readLines: - for i := 0; i < linesToRead.Total; i++ { + callThen := func() { + if linesToRead.Then != nil { + linesToRead.Then() + } + } + for i := 0; linesToRead.Total == -1 || i < linesToRead.Total; i++ { var ok bool var line []byte select { case <-opts.Stop: + callThen() break outer case line, ok = <-lineChan: break @@ -258,6 +277,7 @@ func (self *ViewBufferManager) NewCmdTask(start func() (*exec.Cmd, io.Reader), p // if we're here then there's nothing left to scan from the source // so we're at the EOF and can flush the stale content self.onEndOfInput() + callThen() break outer } writeToView(append(line, '\n')) @@ -272,6 +292,7 @@ func (self *ViewBufferManager) NewCmdTask(start func() (*exec.Cmd, io.Reader), p } refreshViewIfStale() onFirstPageShown() + callThen() } } diff --git a/pkg/tasks/tasks_test.go b/pkg/tasks/tasks_test.go index 89056807fd0..72da6d83c2a 100644 --- a/pkg/tasks/tasks_test.go +++ b/pkg/tasks/tasks_test.go @@ -52,7 +52,7 @@ func TestNewCmdTaskInstantStop(t *testing.T) { return cmd, reader } - fn := manager.NewCmdTask(start, "prefix\n", LinesToRead{20, -1}, onDone) + fn := manager.NewCmdTask(start, "prefix\n", LinesToRead{20, -1, nil}, onDone) _ = fn(TaskOpts{Stop: stop, InitialContentLoaded: func() { task.Done() }}) @@ -115,7 +115,7 @@ func TestNewCmdTask(t *testing.T) { return cmd, reader } - fn := manager.NewCmdTask(start, "prefix\n", LinesToRead{20, -1}, onDone) + fn := manager.NewCmdTask(start, "prefix\n", LinesToRead{20, -1, nil}, onDone) wg := sync.WaitGroup{} wg.Add(1) go func() { @@ -184,37 +184,37 @@ func TestNewCmdTaskRefresh(t *testing.T) { { "total < initialRefreshAfter", 150, - LinesToRead{100, 120}, + LinesToRead{100, 120, nil}, []int{100}, }, { "total == initialRefreshAfter", 150, - LinesToRead{100, 100}, + LinesToRead{100, 100, nil}, []int{100}, }, { "total > initialRefreshAfter", 150, - LinesToRead{100, 50}, + LinesToRead{100, 50, nil}, []int{50, 100}, }, { "initialRefreshAfter == -1", 150, - LinesToRead{100, -1}, + LinesToRead{100, -1, nil}, []int{100}, }, { "totalTaskLines < initialRefreshAfter", 25, - LinesToRead{100, 50}, + LinesToRead{100, 50, nil}, []int{25}, }, { "totalTaskLines between total and initialRefreshAfter", 75, - LinesToRead{100, 50}, + LinesToRead{100, 50, nil}, []int{50, 75}, }, } From ec51efc82c99b7a1bd3219b056bb806cbcba6733 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 25 Mar 2025 14:33:24 +0100 Subject: [PATCH 11/16] Make the main view searchable --- docs/keybindings/Keybindings_en.md | 2 ++ docs/keybindings/Keybindings_ja.md | 2 ++ docs/keybindings/Keybindings_ko.md | 2 ++ docs/keybindings/Keybindings_nl.md | 2 ++ docs/keybindings/Keybindings_pl.md | 2 ++ docs/keybindings/Keybindings_pt.md | 2 ++ docs/keybindings/Keybindings_ru.md | 2 ++ docs/keybindings/Keybindings_zh-CN.md | 2 ++ docs/keybindings/Keybindings_zh-TW.md | 2 ++ pkg/gui/context/main_context.go | 11 +++++++++++ pkg/gui/context/setup.go | 4 ++-- .../switch_to_focused_main_view_controller.go | 3 +++ 12 files changed, 34 insertions(+), 2 deletions(-) diff --git a/docs/keybindings/Keybindings_en.md b/docs/keybindings/Keybindings_en.md index 843c1c89858..396459478d5 100644 --- a/docs/keybindings/Keybindings_en.md +++ b/docs/keybindings/Keybindings_en.md @@ -210,6 +210,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` mouse wheel up (fn+down) `` | Scroll up | | | `` `` | Switch view | Switch to other view (staged/unstaged changes). | | `` `` | Exit back to side panel | | +| `` / `` | Search the current view by text | | ## Main panel (patch building) @@ -311,6 +312,7 @@ If you would instead like to start an interactive rebase from the selected commi |-----|--------|-------------| | `` `` | Switch view | Switch to other view (staged/unstaged changes). | | `` `` | Exit back to side panel | | +| `` / `` | Search the current view by text | | ## Stash diff --git a/docs/keybindings/Keybindings_ja.md b/docs/keybindings/Keybindings_ja.md index f02d933d3d6..eff44cbb2c5 100644 --- a/docs/keybindings/Keybindings_ja.md +++ b/docs/keybindings/Keybindings_ja.md @@ -57,6 +57,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ |-----|--------|-------------| | `` `` | パネルを切り替え | Switch to other view (staged/unstaged changes). | | `` `` | Exit back to side panel | | +| `` / `` | 検索を開始 | | ## Stash @@ -293,6 +294,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` mouse wheel up (fn+down) `` | 上にスクロール | | | `` `` | パネルを切り替え | Switch to other view (staged/unstaged changes). | | `` `` | Exit back to side panel | | +| `` / `` | 検索を開始 | | ## メインパネル (Patch Building) diff --git a/docs/keybindings/Keybindings_ko.md b/docs/keybindings/Keybindings_ko.md index 8223e0bc550..c1561441b14 100644 --- a/docs/keybindings/Keybindings_ko.md +++ b/docs/keybindings/Keybindings_ko.md @@ -76,6 +76,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ |-----|--------|-------------| | `` `` | 패널 전환 | Switch to other view (staged/unstaged changes). | | `` `` | Exit back to side panel | | +| `` / `` | 검색 시작 | | ## Stash @@ -152,6 +153,7 @@ _Legend: `` means ctrl+b, `` means alt+b, `B` means shift+b_ | `` mouse wheel up (fn+down) `` | 위로 스크롤 | | | `` `` | 패널 전환 | Switch to other view (staged/unstaged changes). | | `` `` | Exit back to side panel | | +| `` / `` | 검색 시작 | | ## 메인 패널 (Patch Building) diff --git a/docs/keybindings/Keybindings_nl.md b/docs/keybindings/Keybindings_nl.md index c1fa4588765..1752329e71c 100644 --- a/docs/keybindings/Keybindings_nl.md +++ b/docs/keybindings/Keybindings_nl.md @@ -218,6 +218,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` mouse wheel up (fn+down) `` | Scroll omhoog | | | `` `` | Ga naar een ander paneel | Switch to other view (staged/unstaged changes). | | `` `` | Exit back to side panel | | +| `` / `` | Start met zoeken | | ## Patch bouwen @@ -289,6 +290,7 @@ If you would instead like to start an interactive rebase from the selected commi |-----|--------|-------------| | `` `` | Ga naar een ander paneel | Switch to other view (staged/unstaged changes). | | `` `` | Exit back to side panel | | +| `` / `` | Start met zoeken | | ## Staging diff --git a/docs/keybindings/Keybindings_pl.md b/docs/keybindings/Keybindings_pl.md index 7c6b26921d0..67a4ba27797 100644 --- a/docs/keybindings/Keybindings_pl.md +++ b/docs/keybindings/Keybindings_pl.md @@ -97,6 +97,7 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, |-----|--------|-------------| | `` `` | Przełącz widok | Przełącz na inny widok (zatwierdzone/niezatwierdzone zmiany). | | `` `` | Exit back to side panel | | +| `` / `` | Szukaj w bieżącym widoku po tekście | | ## Drzewa pracy @@ -167,6 +168,7 @@ Jeśli chcesz zamiast tego rozpocząć interaktywny rebase od wybranego commita, | `` mouse wheel up (fn+down) `` | Przewiń w górę | | | `` `` | Przełącz widok | Przełącz na inny widok (zatwierdzone/niezatwierdzone zmiany). | | `` `` | Exit back to side panel | | +| `` / `` | Szukaj w bieżącym widoku po tekście | | ## Panel główny (scalanie) diff --git a/docs/keybindings/Keybindings_pt.md b/docs/keybindings/Keybindings_pt.md index 8cb2d3319dc..ccf5524b060 100644 --- a/docs/keybindings/Keybindings_pt.md +++ b/docs/keybindings/Keybindings_pt.md @@ -232,6 +232,7 @@ If you would instead like to start an interactive rebase from the selected commi | `` mouse wheel up (fn+down) `` | Rolar para cima | | | `` `` | Mudar de visão | Alternar para outra visão (staged/não processadas alterações). | | `` `` | Exit back to side panel | | +| `` / `` | Search the current view by text | | ## Painel Principal (preparação) @@ -324,6 +325,7 @@ Veja a documentação: |-----|--------|-------------| | `` `` | Mudar de visão | Alternar para outra visão (staged/não processadas alterações). | | `` `` | Exit back to side panel | | +| `` / `` | Search the current view by text | | ## Stash diff --git a/docs/keybindings/Keybindings_ru.md b/docs/keybindings/Keybindings_ru.md index 6febfe80b5d..b75fc0d80c2 100644 --- a/docs/keybindings/Keybindings_ru.md +++ b/docs/keybindings/Keybindings_ru.md @@ -67,6 +67,7 @@ _Связки клавиш_ |-----|--------|-------------| | `` `` | Переключиться на другую панель (проиндексированные/непроиндексированные изменения) | Switch to other view (staged/unstaged changes). | | `` `` | Exit back to side panel | | +| `` / `` | Найти | | ## Главная панель (Индексирование) @@ -98,6 +99,7 @@ _Связки клавиш_ | `` mouse wheel up (fn+down) `` | Прокрутить вверх | | | `` `` | Переключиться на другую панель (проиндексированные/непроиндексированные изменения) | Switch to other view (staged/unstaged changes). | | `` `` | Exit back to side panel | | +| `` / `` | Найти | | ## Главная панель (Слияние) diff --git a/docs/keybindings/Keybindings_zh-CN.md b/docs/keybindings/Keybindings_zh-CN.md index def6f1632d1..4cdda3dd094 100644 --- a/docs/keybindings/Keybindings_zh-CN.md +++ b/docs/keybindings/Keybindings_zh-CN.md @@ -278,6 +278,7 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ |-----|--------|-------------| | `` `` | 切换到其他面板 | 切换到其他视图(已暂存/未暂存的变更) | | `` `` | Exit back to side panel | | +| `` / `` | 开始搜索 | | ## 正在合并 @@ -325,6 +326,7 @@ _图例:`` 意味着ctrl+b, `意味着Alt+b, `B` 意味着shift+b_ | `` mouse wheel up (fn+down) `` | 向上滚动 | | | `` `` | 切换到其他面板 | 切换到其他视图(已暂存/未暂存的变更) | | `` `` | Exit back to side panel | | +| `` / `` | 开始搜索 | | ## 状态 diff --git a/docs/keybindings/Keybindings_zh-TW.md b/docs/keybindings/Keybindings_zh-TW.md index b056c92b907..8312ca98bce 100644 --- a/docs/keybindings/Keybindings_zh-TW.md +++ b/docs/keybindings/Keybindings_zh-TW.md @@ -74,6 +74,7 @@ _說明:`` 表示 Ctrl+B、`` 表示 Alt+B,`B`表示 Shift+B | `` mouse wheel up (fn+down) `` | 向上捲動 | | | `` `` | 切換至另一個面板 (已預存/未預存更改) | Switch to other view (staged/unstaged changes). | | `` `` | Exit back to side panel | | +| `` / `` | 搜尋 | | ## 主面板(合併) @@ -347,6 +348,7 @@ If you would instead like to start an interactive rebase from the selected commi |-----|--------|-------------| | `` `` | 切換至另一個面板 (已預存/未預存更改) | Switch to other view (staged/unstaged changes). | | `` `` | Exit back to side panel | | +| `` / `` | 搜尋 | | ## 狀態 diff --git a/pkg/gui/context/main_context.go b/pkg/gui/context/main_context.go index 7ca6ffdd154..66babac0362 100644 --- a/pkg/gui/context/main_context.go +++ b/pkg/gui/context/main_context.go @@ -7,12 +7,16 @@ import ( type MainContext struct { *SimpleContext + *SearchTrait } +var _ types.ISearchableContext = (*MainContext)(nil) + func NewMainContext( view *gocui.View, windowName string, key types.ContextKey, + c *ContextCommon, ) *MainContext { ctx := &MainContext{ SimpleContext: NewSimpleContext( @@ -24,7 +28,14 @@ func NewMainContext( Focusable: true, HighlightOnFocus: false, })), + SearchTrait: NewSearchTrait(c), } + ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(int) error { return nil })) + return ctx } + +func (self *MainContext) ModelSearchResults(searchStr string, caseSensitive bool) []gocui.SearchPosition { + return nil +} diff --git a/pkg/gui/context/setup.go b/pkg/gui/context/setup.go index 33e67fda555..3a87c100a7e 100644 --- a/pkg/gui/context/setup.go +++ b/pkg/gui/context/setup.go @@ -39,8 +39,8 @@ func NewContextTree(c *ContextCommon) *ContextTree { Tags: NewTagsContext(c), Stash: NewStashContext(c), Suggestions: NewSuggestionsContext(c), - Normal: NewMainContext(c.Views().Main, "main", NORMAL_MAIN_CONTEXT_KEY), - NormalSecondary: NewMainContext(c.Views().Secondary, "secondary", NORMAL_SECONDARY_CONTEXT_KEY), + Normal: NewMainContext(c.Views().Main, "main", NORMAL_MAIN_CONTEXT_KEY, c), + NormalSecondary: NewMainContext(c.Views().Secondary, "secondary", NORMAL_SECONDARY_CONTEXT_KEY, c), Staging: NewPatchExplorerContext( c.Views().Staging, "main", diff --git a/pkg/gui/controllers/switch_to_focused_main_view_controller.go b/pkg/gui/controllers/switch_to_focused_main_view_controller.go index f2d48448f06..85da121bec7 100644 --- a/pkg/gui/controllers/switch_to_focused_main_view_controller.go +++ b/pkg/gui/controllers/switch_to_focused_main_view_controller.go @@ -44,6 +44,9 @@ func (self *SwitchToFocusedMainViewController) Context() types.Context { func (self *SwitchToFocusedMainViewController) handleFocusMainView() error { mainViewContext := self.c.Helpers().Window.GetContextForWindow("main") mainViewContext.SetParentContext(self.context) + if context, ok := mainViewContext.(types.ISearchableContext); ok { + context.ClearSearchString() + } self.c.Context().Push(mainViewContext, types.OnFocusOpts{}) return nil } From 338064ac2cc4b5a6dc0f5b32cd08b4baceb421af Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 3 Apr 2025 17:18:57 +0200 Subject: [PATCH 12/16] Read all lines from task when starting to search --- pkg/gui/controllers/main_view_controller.go | 28 ++++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/pkg/gui/controllers/main_view_controller.go b/pkg/gui/controllers/main_view_controller.go index e09cb27c070..b48868677c8 100644 --- a/pkg/gui/controllers/main_view_controller.go +++ b/pkg/gui/controllers/main_view_controller.go @@ -1,6 +1,7 @@ package controllers import ( + "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -8,16 +9,16 @@ type MainViewController struct { baseController c *ControllerCommon - context types.Context - otherContext types.Context + context *context.MainContext + otherContext *context.MainContext } var _ types.IController = &MainViewController{} func NewMainViewController( c *ControllerCommon, - context types.Context, - otherContext types.Context, + context *context.MainContext, + otherContext *context.MainContext, ) *MainViewController { return &MainViewController{ baseController: baseController{}, @@ -41,6 +42,13 @@ func (self *MainViewController) GetKeybindings(opts types.KeybindingsOpts) []*ty Handler: self.escape, Description: self.c.Tr.ExitFocusedMainView, }, + { + // overriding this because we want to read all of the task's output before we start searching + Key: opts.GetKey(opts.Config.Universal.StartSearch), + Handler: self.openSearch, + Description: self.c.Tr.StartSearch, + Tag: "navigation", + }, } } @@ -61,3 +69,15 @@ func (self *MainViewController) escape() error { self.c.Context().Pop() return nil } + +func (self *MainViewController) openSearch() error { + if manager := self.c.GetViewBufferManagerForView(self.context.GetView()); manager != nil { + manager.ReadToEnd(func() { + self.c.OnUIThread(func() error { + return self.c.Helpers().Search.OpenSearchPrompt(self.context) + }) + }) + } + + return nil +} From acfa0249151fac843b8f75fc5f50e4b00984cdac Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Tue, 25 Mar 2025 16:40:28 +0100 Subject: [PATCH 13/16] Allow clicking in main view to focus it --- .../controllers/commits_files_controller.go | 19 ----------- pkg/gui/controllers/files_controller.go | 16 ---------- .../switch_to_focused_main_view_controller.go | 32 ++++++++++++++++++- pkg/integration/tests/ui/range_select.go | 13 ++++---- 4 files changed, 38 insertions(+), 42 deletions(-) diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index 6f28f85e08a..1ea91669588 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -135,17 +135,6 @@ func (self *CommitFilesController) GetKeybindings(opts types.KeybindingsOpts) [] return bindings } -func (self *CommitFilesController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding { - return []*gocui.ViewMouseBinding{ - { - ViewName: "main", - Key: gocui.MouseLeft, - Handler: self.onClickMain, - FocusedView: self.context().GetViewName(), - }, - } -} - func (self *CommitFilesController) context() *context.CommitFilesContext { return self.c.Contexts().CommitFiles } @@ -175,14 +164,6 @@ func (self *CommitFilesController) GetOnRenderToMain() func() { } } -func (self *CommitFilesController) onClickMain(opts gocui.ViewMouseBindingOpts) error { - node := self.context().GetSelected() - if node == nil { - return nil - } - return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: opts.Y}) -} - func (self *CommitFilesController) copyDiffToClipboard(path string, toastMessage string) error { from, to := self.context().GetFromAndToForDiff() from, reverse := self.c.Modes().Diffing.GetFromAndReverseArgsForDiff(from) diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 2d551d6ec9d..22bccf6c6aa 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -208,24 +208,12 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types func (self *FilesController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding { return []*gocui.ViewMouseBinding{ - { - ViewName: "main", - Key: gocui.MouseLeft, - Handler: self.onClickMain, - FocusedView: self.context().GetViewName(), - }, { ViewName: "mergeConflicts", Key: gocui.MouseLeft, Handler: self.onClickMain, FocusedView: self.context().GetViewName(), }, - { - ViewName: "secondary", - Key: gocui.MouseLeft, - Handler: self.onClickSecondary, - FocusedView: self.context().GetViewName(), - }, } } @@ -1188,10 +1176,6 @@ func (self *FilesController) onClickMain(opts gocui.ViewMouseBindingOpts) error return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: opts.Y}) } -func (self *FilesController) onClickSecondary(opts gocui.ViewMouseBindingOpts) error { - return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "secondary", ClickedViewLineIdx: opts.Y}) -} - func (self *FilesController) fetch() error { return self.c.WithWaitingStatus(self.c.Tr.FetchingStatus, func(task gocui.Task) error { if err := self.fetchAux(task); err != nil { diff --git a/pkg/gui/controllers/switch_to_focused_main_view_controller.go b/pkg/gui/controllers/switch_to_focused_main_view_controller.go index 85da121bec7..cb03f5e1516 100644 --- a/pkg/gui/controllers/switch_to_focused_main_view_controller.go +++ b/pkg/gui/controllers/switch_to_focused_main_view_controller.go @@ -1,6 +1,7 @@ package controllers import ( + "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -37,12 +38,41 @@ func (self *SwitchToFocusedMainViewController) GetKeybindings(opts types.Keybind return bindings } +func (self *SwitchToFocusedMainViewController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding { + return []*gocui.ViewMouseBinding{ + { + ViewName: "main", + Key: gocui.MouseLeft, + Handler: self.onClickMain, + FocusedView: self.context.GetViewName(), + }, + { + ViewName: "secondary", + Key: gocui.MouseLeft, + Handler: self.onClickSecondary, + FocusedView: self.context.GetViewName(), + }, + } +} + func (self *SwitchToFocusedMainViewController) Context() types.Context { return self.context } +func (self *SwitchToFocusedMainViewController) onClickMain(opts gocui.ViewMouseBindingOpts) error { + return self.focusMainView("main") +} + +func (self *SwitchToFocusedMainViewController) onClickSecondary(opts gocui.ViewMouseBindingOpts) error { + return self.focusMainView("secondary") +} + func (self *SwitchToFocusedMainViewController) handleFocusMainView() error { - mainViewContext := self.c.Helpers().Window.GetContextForWindow("main") + return self.focusMainView("main") +} + +func (self *SwitchToFocusedMainViewController) focusMainView(mainViewName string) error { + mainViewContext := self.c.Helpers().Window.GetContextForWindow(mainViewName) mainViewContext.SetParentContext(self.context) if context, ok := mainViewContext.(types.ISearchableContext); ok { context.ClearSearchString() diff --git a/pkg/integration/tests/ui/range_select.go b/pkg/integration/tests/ui/range_select.go index 37c63e1d00b..f9487632a1c 100644 --- a/pkg/integration/tests/ui/range_select.go +++ b/pkg/integration/tests/ui/range_select.go @@ -39,7 +39,7 @@ var RangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ // separately) // In both views we're going to have 10 lines starting from 'line 1' going down to // 'line 10'. - fileContent := "" + fileContent := "staged\n" total := 10 for i := 1; i <= total; i++ { remaining := total - i + 1 @@ -47,10 +47,11 @@ var RangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ shell.EmptyCommit(fmt.Sprintf("line %d", remaining)) fileContent = fmt.Sprintf("%sline %d\n", fileContent, i) } - shell.CreateFile("file1", fileContent) + shell.CreateFileAndAdd("file1", "staged\n") + shell.UpdateFile("file1", fileContent) }, Run: func(t *TestDriver, keys config.KeybindingConfig) { - assertRangeSelectBehaviour := func(v *ViewDriver, otherView *ViewDriver, lineIdxOfFirstItem int) { + assertRangeSelectBehaviour := func(v *ViewDriver, focusOtherView func(), lineIdxOfFirstItem int) { v. SelectedLines( Contains("line 1"), @@ -154,7 +155,7 @@ var RangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ ) // Click in view, press shift+arrow -> nonsticky range - otherView.Focus() + focusOtherView() v.Click(1, lineIdxOfFirstItem). SelectedLines( Contains("line 1"), @@ -166,7 +167,7 @@ var RangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ ) } - assertRangeSelectBehaviour(t.Views().Commits().Focus(), t.Views().Branches(), 0) + assertRangeSelectBehaviour(t.Views().Commits().Focus(), func() { t.Views().Branches().Focus() }, 0) t.Views().Files(). Focus(). @@ -175,6 +176,6 @@ var RangeSelect = NewIntegrationTest(NewIntegrationTestArgs{ ). PressEnter() - assertRangeSelectBehaviour(t.Views().Staging().IsFocused(), t.Views().Files(), 6) + assertRangeSelectBehaviour(t.Views().Staging().IsFocused(), func() { t.Views().Staging().PressTab() }, 6) }, }) From fbb8b2e17e38d364b1a52b544ca364f2d2080f83 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 26 Mar 2025 12:39:39 +0100 Subject: [PATCH 14/16] Allow clicking in focused main view to go to staging Only works if a file is selected. --- pkg/gui/context/base_context.go | 28 +++++++++++++------ pkg/gui/controllers/attach.go | 1 + pkg/gui/controllers/base_controller.go | 4 +++ .../controllers/commits_files_controller.go | 10 +++++++ pkg/gui/controllers/files_controller.go | 13 ++++++++- pkg/gui/controllers/main_view_controller.go | 19 +++++++++++++ pkg/gui/types/context.go | 4 +++ 7 files changed, 70 insertions(+), 9 deletions(-) diff --git a/pkg/gui/context/base_context.go b/pkg/gui/context/base_context.go index 76482ad0f35..b72374392d9 100644 --- a/pkg/gui/context/base_context.go +++ b/pkg/gui/context/base_context.go @@ -13,12 +13,13 @@ type BaseContext struct { windowName string onGetOptionsMap func() map[string]string - keybindingsFns []types.KeybindingsFn - mouseKeybindingsFns []types.MouseKeybindingsFn - onClickFn func() error - onRenderToMainFn func() - onFocusFn onFocusFn - onFocusLostFn onFocusLostFn + keybindingsFns []types.KeybindingsFn + mouseKeybindingsFns []types.MouseKeybindingsFn + onClickFn func() error + onClickFocusedMainViewFn onClickFocusedMainViewFn + onRenderToMainFn func() + onFocusFn onFocusFn + onFocusLostFn onFocusLostFn focusable bool transient bool @@ -31,8 +32,9 @@ type BaseContext struct { } type ( - onFocusFn = func(types.OnFocusOpts) - onFocusLostFn = func(types.OnFocusLostOpts) + onFocusFn = func(types.OnFocusOpts) + onFocusLostFn = func(types.OnFocusLostOpts) + onClickFocusedMainViewFn = func(mainViewName string, clickedLineIdx int) error ) var _ types.IBaseContext = &BaseContext{} @@ -144,10 +146,20 @@ func (self *BaseContext) AddOnClickFn(fn func() error) { } } +func (self *BaseContext) AddOnClickFocusedMainViewFn(fn onClickFocusedMainViewFn) { + if fn != nil { + self.onClickFocusedMainViewFn = fn + } +} + func (self *BaseContext) GetOnClick() func() error { return self.onClickFn } +func (self *BaseContext) GetOnClickFocusedMainView() onClickFocusedMainViewFn { + return self.onClickFocusedMainViewFn +} + func (self *BaseContext) AddOnRenderToMainFn(fn func()) { if fn != nil { self.onRenderToMainFn = fn diff --git a/pkg/gui/controllers/attach.go b/pkg/gui/controllers/attach.go index 6a24fd7d317..8c1dbb91e75 100644 --- a/pkg/gui/controllers/attach.go +++ b/pkg/gui/controllers/attach.go @@ -7,6 +7,7 @@ func AttachControllers(context types.Context, controllers ...types.IController) context.AddKeybindingsFn(controller.GetKeybindings) context.AddMouseKeybindingsFn(controller.GetMouseKeybindings) context.AddOnClickFn(controller.GetOnClick()) + context.AddOnClickFocusedMainViewFn(controller.GetOnClickFocusedMainView()) context.AddOnRenderToMainFn(controller.GetOnRenderToMain()) context.AddOnFocusFn(controller.GetOnFocus()) context.AddOnFocusLostFn(controller.GetOnFocusLost()) diff --git a/pkg/gui/controllers/base_controller.go b/pkg/gui/controllers/base_controller.go index adff1927aa2..0e122922289 100644 --- a/pkg/gui/controllers/base_controller.go +++ b/pkg/gui/controllers/base_controller.go @@ -19,6 +19,10 @@ func (self *baseController) GetOnClick() func() error { return nil } +func (self *baseController) GetOnClickFocusedMainView() func(mainViewName string, clickedLineIdx int) error { + return nil +} + func (self *baseController) GetOnRenderToMain() func() { return nil } diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index 1ea91669588..e1818789cda 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -531,6 +531,16 @@ func (self *CommitFilesController) expandAll() error { return nil } +func (self *CommitFilesController) GetOnClickFocusedMainView() func(mainViewName string, clickedLineIdx int) error { + return func(mainViewName string, clickedLineIdx int) error { + node := self.getSelectedItem() + if node != nil && node.File != nil { + return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: mainViewName, ClickedViewLineIdx: clickedLineIdx}) + } + return nil + } +} + // NOTE: these functions are identical to those in files_controller.go (except for types) and // could also be cleaned up with some generics func normalisedSelectedCommitFileNodes(selectedNodes []*filetree.CommitFileNode) []*filetree.CommitFileNode { diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 22bccf6c6aa..1240e3cf7f7 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -323,6 +323,16 @@ func (self *FilesController) GetOnClick() func() error { }) } +func (self *FilesController) GetOnClickFocusedMainView() func(mainViewName string, clickedLineIdx int) error { + return func(mainViewName string, clickedLineIdx int) error { + node := self.getSelectedItem() + if node != nil && node.File != nil { + return self.EnterFile(types.OnFocusOpts{ClickedWindowName: mainViewName, ClickedViewLineIdx: clickedLineIdx}) + } + return nil + } +} + // if we are dealing with a status for which there is no key in this map, // then we won't optimistically render: we'll just let `git status` tell // us what the new status is. @@ -545,7 +555,8 @@ func (self *FilesController) EnterFile(opts types.OnFocusOpts) error { return self.handleNonInlineConflict(file) } - self.c.Context().Push(self.c.Contexts().Staging, opts) + context := lo.Ternary(opts.ClickedWindowName == "secondary", self.c.Contexts().StagingSecondary, self.c.Contexts().Staging) + self.c.Context().Push(context, opts) return nil } diff --git a/pkg/gui/controllers/main_view_controller.go b/pkg/gui/controllers/main_view_controller.go index b48868677c8..b5a6722a5a0 100644 --- a/pkg/gui/controllers/main_view_controller.go +++ b/pkg/gui/controllers/main_view_controller.go @@ -1,6 +1,7 @@ package controllers import ( + "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/types" ) @@ -52,6 +53,16 @@ func (self *MainViewController) GetKeybindings(opts types.KeybindingsOpts) []*ty } } +func (self *MainViewController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding { + return []*gocui.ViewMouseBinding{ + { + ViewName: self.context.GetViewName(), + Key: gocui.MouseLeft, + Handler: self.onClick, + }, + } +} + func (self *MainViewController) Context() types.Context { return self.context } @@ -70,6 +81,14 @@ func (self *MainViewController) escape() error { return nil } +func (self *MainViewController) onClick(opts gocui.ViewMouseBindingOpts) error { + parentCtx := self.context.GetParentContext() + if parentCtx.GetOnClickFocusedMainView() != nil { + return parentCtx.GetOnClickFocusedMainView()(self.context.GetViewName(), opts.Y) + } + return nil +} + func (self *MainViewController) openSearch() error { if manager := self.c.GetViewBufferManagerForView(self.context.GetView()); manager != nil { manager.ReadToEnd(func() { diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go index 8a9bbf25b4a..f76bedeb661 100644 --- a/pkg/gui/types/context.go +++ b/pkg/gui/types/context.go @@ -94,6 +94,9 @@ type IBaseContext interface { // our list controller can come along and wrap it in a list-specific click handler. // We'll need to think of a better way to do this. AddOnClickFn(func() error) + // Likewise for the focused main view: we need this to communicate between a + // side panel controller and the focused main view controller. + AddOnClickFocusedMainViewFn(func(mainViewName string, clickedLineIdx int) error) AddOnRenderToMainFn(func()) AddOnFocusFn(func(OnFocusOpts)) @@ -240,6 +243,7 @@ type HasKeybindings interface { GetKeybindings(opts KeybindingsOpts) []*Binding GetMouseKeybindings(opts KeybindingsOpts) []*gocui.ViewMouseBinding GetOnClick() func() error + GetOnClickFocusedMainView() func(mainViewName string, clickedLineIdx int) error GetOnRenderToMain() func() GetOnFocus() func(OnFocusOpts) GetOnFocusLost() func(OnFocusLostOpts) From 98e4cb733fda1c5d38c029af91079630c0c75f0d Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 26 Mar 2025 13:43:19 +0100 Subject: [PATCH 15/16] Allow clicking in the respective other main view to switch focus to it --- pkg/gui/controllers/main_view_controller.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/pkg/gui/controllers/main_view_controller.go b/pkg/gui/controllers/main_view_controller.go index b5a6722a5a0..e6b209286ba 100644 --- a/pkg/gui/controllers/main_view_controller.go +++ b/pkg/gui/controllers/main_view_controller.go @@ -58,7 +58,19 @@ func (self *MainViewController) GetMouseKeybindings(opts types.KeybindingsOpts) { ViewName: self.context.GetViewName(), Key: gocui.MouseLeft, - Handler: self.onClick, + Handler: func(opts gocui.ViewMouseBindingOpts) error { + if self.isFocused() { + return self.onClick(opts) + } + + self.context.SetParentContext(self.otherContext.GetParentContext()) + self.c.Context().Push(self.context, types.OnFocusOpts{ + ClickedWindowName: self.context.GetWindowName(), + ClickedViewLineIdx: opts.Y, + }) + + return nil + }, }, } } @@ -100,3 +112,7 @@ func (self *MainViewController) openSearch() error { return nil } + +func (self *MainViewController) isFocused() bool { + return self.c.Context().Current().GetKey() == self.context.GetKey() +} From 4e21a096b950e2840ccfd54e9ac0ad43f0d21a33 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Wed, 26 Mar 2025 14:39:44 +0100 Subject: [PATCH 16/16] Re-render focused main view on refresh if needed --- pkg/gui/view_helpers.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index bf83fd7f355..706f5863bcb 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -4,6 +4,7 @@ import ( "time" "github.com/jesseduffield/gocui" + "github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/tasks" "github.com/jesseduffield/lazygit/pkg/utils" @@ -143,5 +144,17 @@ func (gui *Gui) postRefreshUpdate(c types.Context) { // correctly, and that integration tests see the up to date selection // state. c.FocusLine() + + currentCtx := gui.State.ContextMgr.Current() + if currentCtx.GetKey() == context.NORMAL_MAIN_CONTEXT_KEY || currentCtx.GetKey() == context.NORMAL_SECONDARY_CONTEXT_KEY { + // Searching can't cope well with the view being updated while it is being searched. + // We might be able to fix the problems with this, but it doesn't seem easy, so for now + // just don't rerender the view while searching, on the assumption that users will probably + // either search or change their data, but not both at the same time. + if !currentCtx.GetView().IsSearching() { + parentCtx := currentCtx.GetParentContext() + parentCtx.HandleRenderToMain() + } + } } }