mirror of
				https://github.com/jesseduffield/lazygit.git
				synced 2025-10-30 23:57:43 +02:00 
			
		
		
		
	combining nodes when only one child exists
This commit is contained in:
		| @@ -1,6 +1,7 @@ | ||||
| package models | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"sort" | ||||
| ) | ||||
|  | ||||
| @@ -106,11 +107,11 @@ func (s *StatusLineNode) Flatten() []*StatusLineNode { | ||||
| 	return arr | ||||
| } | ||||
|  | ||||
| func (s *StatusLineNode) SortTree() { | ||||
| func (s *StatusLineNode) Sort() { | ||||
| 	s.sortChildren() | ||||
|  | ||||
| 	for _, child := range s.Children { | ||||
| 		child.SortTree() | ||||
| 		child.Sort() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -149,3 +150,35 @@ func (s *StatusLineNode) GetIsTracked() bool { | ||||
| func (s *StatusLineNode) GetPath() string { | ||||
| 	return s.Path | ||||
| } | ||||
|  | ||||
| func (s *StatusLineNode) HasExactlyOneChild() bool { | ||||
| 	return len(s.Children) == 1 | ||||
| } | ||||
|  | ||||
| func (s *StatusLineNode) Compress() { | ||||
| 	if s == nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	s.compressAux() | ||||
| } | ||||
|  | ||||
| func (s *StatusLineNode) compressAux() *StatusLineNode { | ||||
| 	if s.IsLeaf() { | ||||
| 		return s | ||||
| 	} | ||||
|  | ||||
| 	for i, child := range s.Children { | ||||
| 		if child.HasExactlyOneChild() { | ||||
| 			grandchild := child.Children[0] | ||||
| 			grandchild.Name = fmt.Sprintf("%s/%s", child.Name, grandchild.Name) | ||||
| 			s.Children[i] = grandchild | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for i, child := range s.Children { | ||||
| 		s.Children[i] = child.compressAux() | ||||
| 	} | ||||
|  | ||||
| 	return s | ||||
| } | ||||
|   | ||||
| @@ -6,16 +6,16 @@ import ( | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestRender(t *testing.T) { | ||||
| func TestCompress(t *testing.T) { | ||||
| 	scenarios := []struct { | ||||
| 		name     string | ||||
| 		root     *StatusLineNode | ||||
| 		expected []string | ||||
| 		expected *StatusLineNode | ||||
| 	}{ | ||||
| 		{ | ||||
| 			name:     "nil node", | ||||
| 			root:     nil, | ||||
| 			expected: []string{}, | ||||
| 			expected: nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "leaf node", | ||||
| @@ -25,7 +25,12 @@ func TestRender(t *testing.T) { | ||||
| 					{File: &File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Name: "test"}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: []string{" M test"}, | ||||
| 			expected: &StatusLineNode{ | ||||
| 				Name: "", | ||||
| 				Children: []*StatusLineNode{ | ||||
| 					{File: &File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Name: "test"}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "big example", | ||||
| @@ -33,44 +38,78 @@ func TestRender(t *testing.T) { | ||||
| 				Name: "", | ||||
| 				Children: []*StatusLineNode{ | ||||
| 					{ | ||||
| 						Name:      "dir1", | ||||
| 						Collapsed: true, | ||||
| 						Name: "dir1", | ||||
| 						Path: "dir1", | ||||
| 						Children: []*StatusLineNode{ | ||||
| 							{ | ||||
| 								File: &File{Name: "file2", ShortStatus: "M ", HasUnstagedChanges: true}, | ||||
| 								Name: "file2", | ||||
| 								Path: "dir1/file2", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name: "dir2", | ||||
| 						Path: "dir2", | ||||
| 						Children: []*StatusLineNode{ | ||||
| 							{ | ||||
| 								File: &File{Name: "file3", ShortStatus: " M", HasStagedChanges: true}, | ||||
| 								Name: "file3", | ||||
| 								Path: "dir2/file3", | ||||
| 							}, | ||||
| 							{ | ||||
| 								File: &File{Name: "file4", ShortStatus: "M ", HasUnstagedChanges: true}, | ||||
| 								Name: "file4", | ||||
| 								Path: "dir2/file4", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						File: &File{Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, | ||||
| 						Name: "file1", | ||||
| 						Path: "file1", | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: &StatusLineNode{ | ||||
| 				Name: "", | ||||
| 				Children: []*StatusLineNode{ | ||||
| 					{ | ||||
| 						Name: "dir1/file2", | ||||
| 						File: &File{Name: "file2", ShortStatus: "M ", HasUnstagedChanges: true}, | ||||
| 						Path: "dir1/file2", | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name: "dir2", | ||||
| 						Path: "dir2", | ||||
| 						Children: []*StatusLineNode{ | ||||
| 							{ | ||||
| 								File: &File{Name: "file3", ShortStatus: " M", HasStagedChanges: true}, | ||||
| 								Name: "file3", | ||||
| 								Path: "dir2/file3", | ||||
| 							}, | ||||
| 							{ | ||||
| 								File: &File{Name: "file4", ShortStatus: "M ", HasUnstagedChanges: true}, | ||||
| 								Name: "file4", | ||||
| 								Path: "dir2/file4", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						File: &File{Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, | ||||
| 						Name: "file1", | ||||
| 						Path: "file1", | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
|  | ||||
| 			expected: []string{"M  dir1 ►", "MM dir2 ▼", "   M file3", "  M  file4", "M  file1"}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, s := range scenarios { | ||||
| 		s := s | ||||
| 		t.Run(s.name, func(t *testing.T) { | ||||
| 			result := s.root.Render()[1:] | ||||
| 			assert.EqualValues(t, s.expected, result) | ||||
| 			s.root.Compress() | ||||
| 			assert.EqualValues(t, s.expected, s.root) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										87
									
								
								pkg/gui/status_line_manager_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								pkg/gui/status_line_manager_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| package gui | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/jesseduffield/lazygit/pkg/commands/models" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestRender(t *testing.T) { | ||||
| 	scenarios := []struct { | ||||
| 		name     string | ||||
| 		root     *models.StatusLineNode | ||||
| 		expected []string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			name:     "nil node", | ||||
| 			root:     nil, | ||||
| 			expected: []string{}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "leaf node", | ||||
| 			root: &models.StatusLineNode{ | ||||
| 				Name: "", | ||||
| 				Children: []*models.StatusLineNode{ | ||||
| 					{File: &models.File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Name: "test"}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expected: []string{" M test"}, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name: "big example", | ||||
| 			root: &models.StatusLineNode{ | ||||
| 				Name: "", | ||||
| 				Children: []*models.StatusLineNode{ | ||||
| 					{ | ||||
| 						Name:      "dir1", | ||||
| 						Collapsed: true, | ||||
| 						Children: []*models.StatusLineNode{ | ||||
| 							{ | ||||
| 								File: &models.File{Name: "file2", ShortStatus: "M ", HasUnstagedChanges: true}, | ||||
| 								Name: "file2", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name: "dir2", | ||||
| 						Children: []*models.StatusLineNode{ | ||||
| 							{ | ||||
| 								Name: "dir2", | ||||
| 								Children: []*models.StatusLineNode{ | ||||
| 									{ | ||||
| 										File: &models.File{Name: "file3", ShortStatus: " M", HasStagedChanges: true}, | ||||
| 										Name: "file3", | ||||
| 									}, | ||||
| 									{ | ||||
| 										File: &models.File{Name: "file4", ShortStatus: "M ", HasUnstagedChanges: true}, | ||||
| 										Name: "file4", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							{ | ||||
| 								File: &models.File{Name: "file5", ShortStatus: "M ", HasUnstagedChanges: true}, | ||||
| 								Name: "file5", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						File: &models.File{Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, | ||||
| 						Name: "file1", | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
|  | ||||
| 			expected: []string{" M dir1 ►", "MM dir2 ▼", "├─ MM dir2 ▼", "│   ├─  M file3", "│   └─ M  file4", "└─ M  file5", "M  file1"}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, s := range scenarios { | ||||
| 		s := s | ||||
| 		t.Run(s.name, func(t *testing.T) { | ||||
| 			mngr := &StatusLineManager{Tree: s.root} | ||||
| 			result := mngr.Render("", nil) | ||||
| 			assert.EqualValues(t, s.expected, result) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| @@ -43,7 +43,8 @@ func GetTreeFromStatusFiles(files []*models.File) *models.StatusLineNode { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	root.SortTree() | ||||
| 	root.Sort() | ||||
| 	root.Compress() | ||||
|  | ||||
| 	return root | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user