mirror of
				https://github.com/jesseduffield/lazygit.git
				synced 2025-10-30 23:57:43 +02:00 
			
		
		
		
	support toggling collapsed
This commit is contained in:
		| @@ -59,26 +59,28 @@ func (s *StatusLineNode) GetHasStagedChanges() bool { | |||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *StatusLineNode) GetNodeAtIndex(index int) *StatusLineNode { | func (s *StatusLineNode) GetNodeAtIndex(index int, collapsedPaths map[string]bool) *StatusLineNode { | ||||||
| 	node, _ := s.getNodeAtIndexAux(index) | 	node, _ := s.getNodeAtIndexAux(index, collapsedPaths) | ||||||
|  |  | ||||||
| 	return node | 	return node | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *StatusLineNode) getNodeAtIndexAux(index int) (*StatusLineNode, int) { | func (s *StatusLineNode) getNodeAtIndexAux(index int, collapsedPaths map[string]bool) (*StatusLineNode, int) { | ||||||
| 	offset := 1 | 	offset := 1 | ||||||
|  |  | ||||||
| 	if index == 0 { | 	if index == 0 { | ||||||
| 		return s, offset | 		return s, offset | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if !collapsedPaths[s.GetPath()] { | ||||||
| 		for _, child := range s.Children { | 		for _, child := range s.Children { | ||||||
| 		node, offsetChange := child.getNodeAtIndexAux(index - offset) | 			node, offsetChange := child.getNodeAtIndexAux(index-offset, collapsedPaths) | ||||||
| 			offset += offsetChange | 			offset += offsetChange | ||||||
| 			if node != nil { | 			if node != nil { | ||||||
| 				return node, offset | 				return node, offset | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil, offset | 	return nil, offset | ||||||
| } | } | ||||||
| @@ -87,21 +89,25 @@ func (s *StatusLineNode) IsLeaf() bool { | |||||||
| 	return len(s.Children) == 0 | 	return len(s.Children) == 0 | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *StatusLineNode) Size() int { | func (s *StatusLineNode) Size(collapsedPaths map[string]bool) int { | ||||||
| 	output := 1 | 	output := 1 | ||||||
|  |  | ||||||
|  | 	if !collapsedPaths[s.GetPath()] { | ||||||
| 		for _, child := range s.Children { | 		for _, child := range s.Children { | ||||||
| 		output += child.Size() | 			output += child.Size(collapsedPaths) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return output | 	return output | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *StatusLineNode) Flatten() []*StatusLineNode { | func (s *StatusLineNode) Flatten(collapsedPaths map[string]bool) []*StatusLineNode { | ||||||
| 	arr := []*StatusLineNode{s} | 	arr := []*StatusLineNode{s} | ||||||
|  |  | ||||||
|  | 	if !collapsedPaths[s.GetPath()] { | ||||||
| 		for _, child := range s.Children { | 		for _, child := range s.Children { | ||||||
| 		arr = append(arr, child.Flatten()...) | 			arr = append(arr, child.Flatten(collapsedPaths)...) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return arr | 	return arr | ||||||
|   | |||||||
| @@ -182,11 +182,17 @@ func (gui *Gui) handleEnterFile(g *gocui.Gui, v *gocui.View) error { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (gui *Gui) enterFile(forceSecondaryFocused bool, selectedLineIdx int) error { | func (gui *Gui) enterFile(forceSecondaryFocused bool, selectedLineIdx int) error { | ||||||
| 	file := gui.getSelectedFile() | 	node := gui.getSelectedStatusNode() | ||||||
| 	if file == nil { | 	if node == nil { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if node.File == nil { | ||||||
|  | 		return gui.handleToggleDirCollapsed() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	file := node.File | ||||||
|  |  | ||||||
| 	submoduleConfigs := gui.State.Submodules | 	submoduleConfigs := gui.State.Submodules | ||||||
| 	if file.IsSubmodule(submoduleConfigs) { | 	if file.IsSubmodule(submoduleConfigs) { | ||||||
| 		submoduleConfig := file.SubmoduleConfig(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 { | func (gui *Gui) handleCreateResetToUpstreamMenu(g *gocui.Gui, v *gocui.View) error { | ||||||
| 	return gui.createResetMenu("@{upstream}") | 	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 | ||||||
|  | } | ||||||
|   | |||||||
| @@ -378,7 +378,7 @@ func (gui *Gui) resetState() { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	gui.State = &guiState{ | 	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), | 		Commits:               make([]*models.Commit, 0), | ||||||
| 		FilteredReflogCommits: make([]*models.Commit, 0), | 		FilteredReflogCommits: make([]*models.Commit, 0), | ||||||
| 		ReflogCommits:         make([]*models.Commit, 0), | 		ReflogCommits:         make([]*models.Commit, 0), | ||||||
|   | |||||||
| @@ -17,12 +17,22 @@ type StatusLineManager struct { | |||||||
| 	Tree           *models.StatusLineNode | 	Tree           *models.StatusLineNode | ||||||
| 	TreeMode       bool | 	TreeMode       bool | ||||||
| 	Log            *logrus.Entry | 	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 { | func (m *StatusLineManager) GetItemAtIndex(index int) *models.StatusLineNode { | ||||||
| 	if m.TreeMode { | 	if m.TreeMode { | ||||||
| 		// need to traverse the three depth first until we get to the index. | 		// 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) | 	m.Log.Warn(index) | ||||||
| @@ -34,11 +44,11 @@ func (m *StatusLineManager) GetItemAtIndex(index int) *models.StatusLineNode { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (m *StatusLineManager) GetAllItems() []*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 { | 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 { | func (m *StatusLineManager) GetAllFiles() []*models.File { | ||||||
| @@ -59,6 +69,14 @@ const LAST_ITEM = "└─ " | |||||||
| const NESTED = "│  " | const NESTED = "│  " | ||||||
| const NOTHING = "   " | 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 { | func (m *StatusLineManager) renderAux(s *models.StatusLineNode, prefix string, depth int, diffName string, submoduleConfigs []*models.SubmoduleConfig) []string { | ||||||
| 	isRoot := depth == -1 | 	isRoot := depth == -1 | ||||||
| 	if s == nil { | 	if s == nil { | ||||||
| @@ -76,7 +94,7 @@ func (m *StatusLineManager) renderAux(s *models.StatusLineNode, prefix string, d | |||||||
| 		return []string{getLine()} | 		return []string{getLine()} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if s.Collapsed { | 	if m.IsCollapsed(s) { | ||||||
| 		return []string{fmt.Sprintf("%s %s", getLine(), COLLAPSED_ARROW)} | 		return []string{fmt.Sprintf("%s %s", getLine(), COLLAPSED_ARROW)} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -862,7 +862,7 @@ func englishTranslationSet() TranslationSet { | |||||||
| 		ViewPatchOptions:                    "view custom patch options", | 		ViewPatchOptions:                    "view custom patch options", | ||||||
| 		PatchOptionsTitle:                   "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", | 		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`, | 		ExitLineByLineMode:                  `exit line-by-line mode`, | ||||||
| 		EnterUpstream:                       `Enter upstream as '<remote> <branchname>'`, | 		EnterUpstream:                       `Enter upstream as '<remote> <branchname>'`, | ||||||
| 		EnterUpstreamWithSlash:              `Enter upstream as '<remote>/<branchname>'`, | 		EnterUpstreamWithSlash:              `Enter upstream as '<remote>/<branchname>'`, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user