diff --git a/docs/Config.md b/docs/Config.md index 9931fda61fe..b6749775302 100644 --- a/docs/Config.md +++ b/docs/Config.md @@ -246,6 +246,9 @@ gui: # If true, show jump-to-window keybindings in window titles. showPanelJumps: true + # If true, show separate Unstaged/Staged tabs in the Files window. + showFileChangeTabs: false + # Nerd fonts version to use. # One of: '2' | '3' | empty string (default) # If empty, do not show icons. diff --git a/pkg/config/user_config.go b/pkg/config/user_config.go index ddb0c087666..ceab1661168 100644 --- a/pkg/config/user_config.go +++ b/pkg/config/user_config.go @@ -151,6 +151,8 @@ type GuiConfig struct { ShowBottomLine bool `yaml:"showBottomLine"` // If true, show jump-to-window keybindings in window titles. ShowPanelJumps bool `yaml:"showPanelJumps"` + // If true, show separate Unstaged/Staged tabs in the Files window. + ShowFileChangeTabs bool `yaml:"showFileChangeTabs"` // Deprecated: use nerdFontsVersion instead ShowIcons bool `yaml:"showIcons" jsonschema:"deprecated"` // Nerd fonts version to use. @@ -817,6 +819,7 @@ func GetDefaultConfigForPlatform(platform string) *UserConfig { ShowCommandLog: true, ShowBottomLine: true, ShowPanelJumps: true, + ShowFileChangeTabs: false, ShowFileTree: true, ShowRootItemInFileTree: true, FileTreeSortOrder: "mixed", diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 458e338046f..c1af24d9f07 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -834,6 +834,35 @@ func (gui *Gui) initGocui(headless bool, test integrationTypes.IntegrationTest) } func (gui *Gui) viewTabMap() map[string][]context.TabView { + filesTabs := []context.TabView{ + { + Tab: gui.c.Tr.FilesTitle, + ViewName: "files", + }, + } + if gui.c.UserConfig().Gui.ShowFileChangeTabs { + filesTabs = append(filesTabs, + context.TabView{ + Tab: gui.c.Tr.UnstagedChanges, + ViewName: "files", + }, + context.TabView{ + Tab: gui.c.Tr.StagedChanges, + ViewName: "files", + }, + ) + } + filesTabs = append(filesTabs, + context.TabView{ + Tab: gui.c.Tr.WorktreesTitle, + ViewName: "worktrees", + }, + context.TabView{ + Tab: gui.c.Tr.SubmodulesTitle, + ViewName: "submodules", + }, + ) + result := map[string][]context.TabView{ "branches": { { @@ -859,20 +888,7 @@ func (gui *Gui) viewTabMap() map[string][]context.TabView { ViewName: "reflogCommits", }, }, - "files": { - { - Tab: gui.c.Tr.FilesTitle, - ViewName: "files", - }, - context.TabView{ - Tab: gui.c.Tr.WorktreesTitle, - ViewName: "worktrees", - }, - { - Tab: gui.c.Tr.SubmodulesTitle, - ViewName: "submodules", - }, - }, + "files": filesTabs, } return result diff --git a/pkg/gui/view_helpers.go b/pkg/gui/view_helpers.go index 453ccd6c932..e08d182e3f3 100644 --- a/pkg/gui/view_helpers.go +++ b/pkg/gui/view_helpers.go @@ -5,6 +5,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/gocui" "github.com/jesseduffield/lazygit/pkg/gui/context" + "github.com/jesseduffield/lazygit/pkg/gui/filetree" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/tasks" "github.com/jesseduffield/lazygit/pkg/utils" @@ -63,6 +64,12 @@ func (gui *Gui) onViewTabClick(windowName string, tabIndex int) error { return nil } + if windowName == "files" { + if err := gui.applyFilesTab(tabs[tabIndex].Tab); err != nil { + return err + } + } + viewName := tabs[tabIndex].ViewName context, ok := gui.helpers.View.ContextForView(viewName) @@ -114,9 +121,61 @@ func getTabbedView(gui *Gui) *gocui.View { // It safe assumption that only static contexts have tabs context := gui.c.Context().CurrentStatic() view, _ := gui.g.View(context.GetViewName()) + if view != nil && view.Name() == "files" { + view.TabIndex = gui.filesTabIndex() + } return view } +func (gui *Gui) filesTabIndex() int { + if gui.State == nil || gui.State.Contexts == nil || gui.State.Contexts.Files == nil { + return 0 + } + if !gui.c.UserConfig().Gui.ShowFileChangeTabs { + return 0 + } + + filter := gui.State.Contexts.Files.GetStatusFilter() + switch filter { + case filetree.DisplayUnstaged: + return 1 + case filetree.DisplayStaged: + return 2 + default: + return 0 + } +} + +func (gui *Gui) applyFilesTab(tabName string) error { + if gui.State == nil || gui.State.Contexts == nil || gui.State.Contexts.Files == nil { + return nil + } + + if !gui.c.UserConfig().Gui.ShowFileChangeTabs { + return nil + } + + filesContext := gui.State.Contexts.Files + desiredFilter := filetree.DisplayAll + + switch tabName { + case gui.c.Tr.UnstagedChanges: + desiredFilter = filetree.DisplayUnstaged + case gui.c.Tr.StagedChanges: + desiredFilter = filetree.DisplayStaged + case gui.c.Tr.FilesTitle: + desiredFilter = filetree.DisplayAll + default: + return nil + } + + filesContext.FileTreeViewModel.SetStatusFilter(desiredFilter) + filesContext.GetView().Subtitle = "" + filesContext.GetView().TabIndex = gui.filesTabIndex() + gui.postRefreshUpdate(filesContext) + return nil +} + func (gui *Gui) render() { gui.c.OnUIThread(func() error { return nil }) } diff --git a/pkg/gui/views.go b/pkg/gui/views.go index 09325799893..702d2b8d1a4 100644 --- a/pkg/gui/views.go +++ b/pkg/gui/views.go @@ -271,4 +271,8 @@ func (gui *Gui) configureViewProperties() { } } } + + if gui.Views.Files != nil { + gui.Views.Files.TabIndex = gui.filesTabIndex() + } }