diff --git a/pkg/commands/models/status_line_node.go b/pkg/commands/models/status_line_node.go index b33e9e731..1ac8bcdd7 100644 --- a/pkg/commands/models/status_line_node.go +++ b/pkg/commands/models/status_line_node.go @@ -59,24 +59,26 @@ func (s *StatusLineNode) GetHasStagedChanges() bool { return false } -func (s *StatusLineNode) GetNodeAtIndex(index int) *StatusLineNode { - node, _ := s.getNodeAtIndexAux(index) +func (s *StatusLineNode) GetNodeAtIndex(index int, collapsedPaths map[string]bool) *StatusLineNode { + node, _ := s.getNodeAtIndexAux(index, collapsedPaths) return node } -func (s *StatusLineNode) getNodeAtIndexAux(index int) (*StatusLineNode, int) { +func (s *StatusLineNode) getNodeAtIndexAux(index int, collapsedPaths map[string]bool) (*StatusLineNode, int) { offset := 1 if index == 0 { return s, offset } - for _, child := range s.Children { - node, offsetChange := child.getNodeAtIndexAux(index - offset) - offset += offsetChange - if node != nil { - return node, offset + if !collapsedPaths[s.GetPath()] { + for _, child := range s.Children { + node, offsetChange := child.getNodeAtIndexAux(index-offset, collapsedPaths) + offset += offsetChange + if node != nil { + return node, offset + } } } @@ -87,21 +89,25 @@ func (s *StatusLineNode) IsLeaf() bool { return len(s.Children) == 0 } -func (s *StatusLineNode) Size() int { +func (s *StatusLineNode) Size(collapsedPaths map[string]bool) int { output := 1 - for _, child := range s.Children { - output += child.Size() + if !collapsedPaths[s.GetPath()] { + for _, child := range s.Children { + output += child.Size(collapsedPaths) + } } return output } -func (s *StatusLineNode) Flatten() []*StatusLineNode { +func (s *StatusLineNode) Flatten(collapsedPaths map[string]bool) []*StatusLineNode { arr := []*StatusLineNode{s} - for _, child := range s.Children { - arr = append(arr, child.Flatten()...) + if !collapsedPaths[s.GetPath()] { + for _, child := range s.Children { + arr = append(arr, child.Flatten(collapsedPaths)...) + } } return arr diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go index 28c9667da..d443a7a8f 100644 --- a/pkg/gui/files_panel.go +++ b/pkg/gui/files_panel.go @@ -182,11 +182,17 @@ func (gui *Gui) handleEnterFile(g *gocui.Gui, v *gocui.View) error { } func (gui *Gui) enterFile(forceSecondaryFocused bool, selectedLineIdx int) error { - file := gui.getSelectedFile() - if file == nil { + node := gui.getSelectedStatusNode() + if node == nil { return nil } + if node.File == nil { + return gui.handleToggleDirCollapsed() + } + + file := node.File + submoduleConfigs := gui.State.Submodules if file.IsSubmodule(submoduleConfigs) { submoduleConfig := file.SubmoduleConfig(submoduleConfigs) @@ -742,3 +748,18 @@ func (gui *Gui) handleStashChanges(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleCreateResetToUpstreamMenu(g *gocui.Gui, v *gocui.View) error { return gui.createResetMenu("@{upstream}") } + +func (gui *Gui) handleToggleDirCollapsed() error { + node := gui.getSelectedStatusNode() + if node == nil { + return nil + } + + gui.State.StatusLineManager.ToggleCollapsed(node) + + if err := gui.postRefreshUpdate(gui.Contexts.Files.Context); err != nil { + gui.Log.Error(err) + } + + return nil +} diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 8f6badb6e..7c0606652 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -378,7 +378,7 @@ func (gui *Gui) resetState() { } gui.State = &guiState{ - StatusLineManager: &StatusLineManager{Files: make([]*models.File, 0), Log: gui.Log, TreeMode: true}, + StatusLineManager: NewStatusLineManager(make([]*models.File, 0), gui.Log), Commits: make([]*models.Commit, 0), FilteredReflogCommits: make([]*models.Commit, 0), ReflogCommits: make([]*models.Commit, 0), diff --git a/pkg/gui/status_line_manager.go b/pkg/gui/status_line_manager.go index 1f4f2494e..3da07ac5d 100644 --- a/pkg/gui/status_line_manager.go +++ b/pkg/gui/status_line_manager.go @@ -13,16 +13,26 @@ const EXPANDED_ARROW = "▼" const COLLAPSED_ARROW = "►" type StatusLineManager struct { - Files []*models.File - Tree *models.StatusLineNode - TreeMode bool - Log *logrus.Entry + Files []*models.File + Tree *models.StatusLineNode + TreeMode bool + Log *logrus.Entry + CollapsedPaths map[string]bool +} + +func NewStatusLineManager(files []*models.File, log *logrus.Entry) *StatusLineManager { + return &StatusLineManager{ + Files: files, + Log: log, + TreeMode: true, // always true for now + CollapsedPaths: map[string]bool{}, + } } func (m *StatusLineManager) GetItemAtIndex(index int) *models.StatusLineNode { if m.TreeMode { // need to traverse the three depth first until we get to the index. - return m.Tree.GetNodeAtIndex(index + 1) // ignoring root + return m.Tree.GetNodeAtIndex(index+1, m.CollapsedPaths) // ignoring root } m.Log.Warn(index) @@ -34,11 +44,11 @@ func (m *StatusLineManager) GetItemAtIndex(index int) *models.StatusLineNode { } func (m *StatusLineManager) GetAllItems() []*models.StatusLineNode { - return m.Tree.Flatten()[1:] // ignoring root + return m.Tree.Flatten(m.CollapsedPaths)[1:] // ignoring root } func (m *StatusLineManager) GetItemsLength() int { - return m.Tree.Size() - 1 // ignoring root + return m.Tree.Size(m.CollapsedPaths) - 1 // ignoring root } func (m *StatusLineManager) GetAllFiles() []*models.File { @@ -59,6 +69,14 @@ const LAST_ITEM = "└─ " const NESTED = "│ " const NOTHING = " " +func (m *StatusLineManager) IsCollapsed(s *models.StatusLineNode) bool { + return m.CollapsedPaths[s.GetPath()] +} + +func (m *StatusLineManager) ToggleCollapsed(s *models.StatusLineNode) { + m.CollapsedPaths[s.GetPath()] = !m.CollapsedPaths[s.GetPath()] +} + func (m *StatusLineManager) renderAux(s *models.StatusLineNode, prefix string, depth int, diffName string, submoduleConfigs []*models.SubmoduleConfig) []string { isRoot := depth == -1 if s == nil { @@ -76,7 +94,7 @@ func (m *StatusLineManager) renderAux(s *models.StatusLineNode, prefix string, d return []string{getLine()} } - if s.Collapsed { + if m.IsCollapsed(s) { return []string{fmt.Sprintf("%s %s", getLine(), COLLAPSED_ARROW)} } diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index a363fcb9a..e240489b8 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -862,7 +862,7 @@ func englishTranslationSet() TranslationSet { ViewPatchOptions: "view custom patch options", PatchOptionsTitle: "Patch Options", NoPatchError: "No patch created yet. To start building a patch, use 'space' on a commit file or enter to add specific lines", - LcEnterFile: "enter file to add selected lines to the patch", + LcEnterFile: "enter file to add selected lines to the patch (or toggle directory collapsed)", ExitLineByLineMode: `exit line-by-line mode`, EnterUpstream: `Enter upstream as ' '`, EnterUpstreamWithSlash: `Enter upstream as '/'`,