diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2022-07-31 19:10:16 +1000 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2022-07-31 19:43:14 +1000 |
commit | 682be18507ecf202116100547cb5049f471af664 (patch) | |
tree | 27c93b614f10f682ae952c1e39390e253afc83b4 | |
parent | 2ca2acaca55711a63e48e5d0c8f0c0678218b81c (diff) |
refactor to use generics for file nodes
use less generic names
-rw-r--r-- | pkg/gui/controllers/commits_files_controller.go | 5 | ||||
-rw-r--r-- | pkg/gui/controllers/files_controller.go | 2 | ||||
-rw-r--r-- | pkg/gui/filetree/build_tree.go | 24 | ||||
-rw-r--r-- | pkg/gui/filetree/build_tree_test.go | 92 | ||||
-rw-r--r-- | pkg/gui/filetree/commit_file_node.go | 161 | ||||
-rw-r--r-- | pkg/gui/filetree/commit_file_tree.go | 17 | ||||
-rw-r--r-- | pkg/gui/filetree/file_node.go | 194 | ||||
-rw-r--r-- | pkg/gui/filetree/file_node_test.go | 34 | ||||
-rw-r--r-- | pkg/gui/filetree/file_tree.go | 22 | ||||
-rw-r--r-- | pkg/gui/filetree/inode.go | 206 | ||||
-rw-r--r-- | pkg/gui/filetree/node.go | 301 | ||||
-rw-r--r-- | pkg/gui/presentation/files.go | 77 |
12 files changed, 488 insertions, 647 deletions
diff --git a/pkg/gui/controllers/commits_files_controller.go b/pkg/gui/controllers/commits_files_controller.go index 20e78997e..5beecba02 100644 --- a/pkg/gui/controllers/commits_files_controller.go +++ b/pkg/gui/controllers/commits_files_controller.go @@ -165,7 +165,7 @@ func (self *CommitFilesController) toggleForPatch(node *filetree.CommitFileNode) // if there is any file that hasn't been fully added we'll fully add everything, // otherwise we'll remove everything - adding := node.AnyFile(func(file *models.CommitFile) bool { + adding := node.SomeFile(func(file *models.CommitFile) bool { return self.git.Patch.PatchManager.GetFileStatus(file.Name, self.context().GetRef().RefName()) != patch.WHOLE }) @@ -203,8 +203,7 @@ func (self *CommitFilesController) toggleForPatch(node *filetree.CommitFileNode) } func (self *CommitFilesController) toggleAllForPatch(_ *filetree.CommitFileNode) error { - // not a fan of type assertions but this will be fixed very soon thanks to generics - root := self.context().CommitFileTreeViewModel.Tree().(*filetree.CommitFileNode) + root := self.context().CommitFileTreeViewModel.GetRoot() return self.toggleForPatch(root) } diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 220891a4d..5304d0d81 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -247,7 +247,7 @@ func (self *FilesController) pressWithLock(node *filetree.FileNode) error { self.mutexes.RefreshingFilesMutex.Lock() defer self.mutexes.RefreshingFilesMutex.Unlock() - if node.IsLeaf() { + if node.IsFile() { file := node.File if file.HasInlineMergeConflicts { diff --git a/pkg/gui/filetree/build_tree.go b/pkg/gui/filetree/build_tree.go index 36034d02d..c7c465e28 100644 --- a/pkg/gui/filetree/build_tree.go +++ b/pkg/gui/filetree/build_tree.go @@ -7,10 +7,10 @@ import ( "github.com/jesseduffield/lazygit/pkg/commands/models" ) -func BuildTreeFromFiles(files []*models.File) *FileNode { - root := &FileNode{} +func BuildTreeFromFiles(files []*models.File) *Node[models.File] { + root := &Node[models.File]{} - var curr *FileNode + var curr *Node[models.File] for _, file := range files { splitPath := split(file.Name) curr = root @@ -30,7 +30,7 @@ func BuildTreeFromFiles(files []*models.File) *FileNode { } } - newChild := &FileNode{ + newChild := &Node[models.File]{ Path: path, File: setFile, } @@ -46,17 +46,17 @@ func BuildTreeFromFiles(files []*models.File) *FileNode { return root } -func BuildFlatTreeFromCommitFiles(files []*models.CommitFile) *CommitFileNode { +func BuildFlatTreeFromCommitFiles(files []*models.CommitFile) *Node[models.CommitFile] { rootAux := BuildTreeFromCommitFiles(files) sortedFiles := rootAux.GetLeaves() - return &CommitFileNode{Children: sortedFiles} + return &Node[models.CommitFile]{Children: sortedFiles} } -func BuildTreeFromCommitFiles(files []*models.CommitFile) *CommitFileNode { - root := &CommitFileNode{} +func BuildTreeFromCommitFiles(files []*models.CommitFile) *Node[models.CommitFile] { + root := &Node[models.CommitFile]{} - var curr *CommitFileNode + var curr *Node[models.CommitFile] for _, file := range files { splitPath := split(file.Name) curr = root @@ -77,7 +77,7 @@ func BuildTreeFromCommitFiles(files []*models.CommitFile) *CommitFileNode { } } - newChild := &CommitFileNode{ + newChild := &Node[models.CommitFile]{ Path: path, File: setFile, } @@ -93,7 +93,7 @@ func BuildTreeFromCommitFiles(files []*models.CommitFile) *CommitFileNode { return root } -func BuildFlatTreeFromFiles(files []*models.File) *FileNode { +func BuildFlatTreeFromFiles(files []*models.File) *Node[models.File] { rootAux := BuildTreeFromFiles(files) sortedFiles := rootAux.GetLeaves() @@ -128,7 +128,7 @@ func BuildFlatTreeFromFiles(files []*models.File) *FileNode { return false }) - return &FileNode{Children: sortedFiles} + return &Node[models.File]{Children: sortedFiles} } func split(str string) []string { diff --git a/pkg/gui/filetree/build_tree_test.go b/pkg/gui/filetree/build_tree_test.go index c486ddfa5..ac36be9af 100644 --- a/pkg/gui/filetree/build_tree_test.go +++ b/pkg/gui/filetree/build_tree_test.go @@ -11,14 +11,14 @@ func TestBuildTreeFromFiles(t *testing.T) { scenarios := []struct { name string files []*models.File - expected *FileNode + expected *Node[models.File] }{ { name: "no files", files: []*models.File{}, - expected: &FileNode{ + expected: &Node[models.File]{ Path: "", - Children: []*FileNode{}, + Children: nil, }, }, { @@ -31,12 +31,12 @@ func TestBuildTreeFromFiles(t *testing.T) { Name: "dir1/b", }, }, - expected: &FileNode{ + expected: &Node[models.File]{ Path: "", - Children: []*FileNode{ + Children: []*Node[models.File]{ { Path: "dir1", - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "dir1/a"}, Path: "dir1/a", @@ -60,12 +60,12 @@ func TestBuildTreeFromFiles(t *testing.T) { Name: "dir2/dir4/b", }, }, - expected: &FileNode{ + expected: &Node[models.File]{ Path: "", - Children: []*FileNode{ + Children: []*Node[models.File]{ { Path: "dir1/dir3", - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "dir1/dir3/a"}, Path: "dir1/dir3/a", @@ -75,7 +75,7 @@ func TestBuildTreeFromFiles(t *testing.T) { }, { Path: "dir2/dir4", - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "dir2/dir4/b"}, Path: "dir2/dir4/b", @@ -96,9 +96,9 @@ func TestBuildTreeFromFiles(t *testing.T) { Name: "a", }, }, - expected: &FileNode{ + expected: &Node[models.File]{ Path: "", - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "a"}, Path: "a", @@ -124,11 +124,11 @@ func TestBuildTreeFromFiles(t *testing.T) { Name: "a", }, }, - expected: &FileNode{ + expected: &Node[models.File]{ Path: "", // it is a little strange that we're not bubbling up our merge conflict // here but we are technically still in in tree mode and that's the rule - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "a"}, Path: "a", @@ -159,14 +159,14 @@ func TestBuildFlatTreeFromFiles(t *testing.T) { scenarios := []struct { name string files []*models.File - expected *FileNode + expected *Node[models.File] }{ { name: "no files", files: []*models.File{}, - expected: &FileNode{ + expected: &Node[models.File]{ Path: "", - Children: []*FileNode{}, + Children: []*Node[models.File]{}, }, }, { @@ -179,9 +179,9 @@ func TestBuildFlatTreeFromFiles(t *testing.T) { Name: "dir1/b", }, }, - expected: &FileNode{ + expected: &Node[models.File]{ Path: "", - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "dir1/a"}, Path: "dir1/a", @@ -205,9 +205,9 @@ func TestBuildFlatTreeFromFiles(t *testing.T) { Name: "dir2/b", }, }, - expected: &FileNode{ + expected: &Node[models.File]{ Path: "", - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "dir1/a"}, Path: "dir1/a", @@ -231,9 +231,9 @@ func TestBuildFlatTreeFromFiles(t *testing.T) { Name: "a", }, }, - expected: &FileNode{ + expected: &Node[models.File]{ Path: "", - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "a"}, Path: "a", @@ -273,9 +273,9 @@ func TestBuildFlatTreeFromFiles(t *testing.T) { Tracked: true, }, }, - expected: &FileNode{ + expected: &Node[models.File]{ Path: "", - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "c1", HasMergeConflicts: true}, Path: "c1", @@ -318,14 +318,14 @@ func TestBuildTreeFromCommitFiles(t *testing.T) { scenarios := []struct { name string files []*models.CommitFile - expected *CommitFileNode + expected *Node[models.CommitFile] }{ { name: "no files", files: []*models.CommitFile{}, - expected: &CommitFileNode{ + expected: &Node[models.CommitFile]{ Path: "", - Children: []*CommitFileNode{}, + Children: nil, }, }, { @@ -338,12 +338,12 @@ func TestBuildTreeFromCommitFiles(t *testing.T) { Name: "dir1/b", }, }, - expected: &CommitFileNode{ + expected: &Node[models.CommitFile]{ Path: "", - Children: []*CommitFileNode{ + Children: []*Node[models.CommitFile]{ { Path: "dir1", - Children: []*CommitFileNode{ + Children: []*Node[models.CommitFile]{ { File: &models.CommitFile{Name: "dir1/a"}, Path: "dir1/a", @@ -367,12 +367,12 @@ func TestBuildTreeFromCommitFiles(t *testing.T) { Name: "dir2/dir4/b", }, }, - expected: &CommitFileNode{ + expected: &Node[models.CommitFile]{ Path: "", - Children: []*CommitFileNode{ + Children: []*Node[models.CommitFile]{ { Path: "dir1/dir3", - Children: []*CommitFileNode{ + Children: []*Node[models.CommitFile]{ { File: &models.CommitFile{Name: "dir1/dir3/a"}, Path: "dir1/dir3/a", @@ -382,7 +382,7 @@ func TestBuildTreeFromCommitFiles(t *testing.T) { }, { Path: "dir2/dir4", - Children: []*CommitFileNode{ + Children: []*Node[models.CommitFile]{ { File: &models.CommitFile{Name: "dir2/dir4/b"}, Path: "dir2/dir4/b", @@ -403,9 +403,9 @@ func TestBuildTreeFromCommitFiles(t *testing.T) { Name: "a", }, }, - expected: &CommitFileNode{ + expected: &Node[models.CommitFile]{ Path: "", - Children: []*CommitFileNode{ + Children: []*Node[models.CommitFile]{ { File: &models.CommitFile{Name: "a"}, Path: "a", @@ -432,14 +432,14 @@ func TestBuildFlatTreeFromCommitFiles(t *testing.T) { scenarios := []struct { name string files []*models.CommitFile - expected *CommitFileNode + expected *Node[models.CommitFile] }{ { name: "no files", files: []*models.CommitFile{}, - expected: &CommitFileNode{ + expected: &Node[models.CommitFile]{ Path: "", - Children: []*CommitFileNode{}, + Children: []*Node[models.CommitFile]{}, }, }, { @@ -452,9 +452,9 @@ func TestBuildFlatTreeFromCommitFiles(t *testing.T) { Name: "dir1/b", }, }, - expected: &CommitFileNode{ + expected: &Node[models.CommitFile]{ Path: "", - Children: []*CommitFileNode{ + Children: []*Node[models.CommitFile]{ { File: &models.CommitFile{Name: "dir1/a"}, Path: "dir1/a", @@ -478,9 +478,9 @@ func TestBuildFlatTreeFromCommitFiles(t *testing.T) { Name: "dir2/b", }, }, - expected: &CommitFileNode{ + expected: &Node[models.CommitFile]{ Path: "", - Children: []*CommitFileNode{ + Children: []*Node[models.CommitFile]{ { File: &models.CommitFile{Name: "dir1/a"}, Path: "dir1/a", @@ -504,9 +504,9 @@ func TestBuildFlatTreeFromCommitFiles(t *testing.T) { Name: "a", }, }, - expected: &CommitFileNode{ + expected: &Node[models.CommitFile]{ Path: "", - Children: []*CommitFileNode{ + Children: []*Node[models.CommitFile]{ { File: &models.CommitFile{Name: "a"}, Path: "a", diff --git a/pkg/gui/filetree/commit_file_node.go b/pkg/gui/filetree/commit_file_node.go index ad794c0c2..067eee682 100644 --- a/pkg/gui/filetree/commit_file_node.go +++ b/pkg/gui/filetree/commit_file_node.go @@ -1,166 +1,21 @@ package filetree -import ( - "github.com/jesseduffield/generics/slices" - "github.com/jesseduffield/lazygit/pkg/commands/models" - "github.com/jesseduffield/lazygit/pkg/gui/types" -) +import "github.com/jesseduffield/lazygit/pkg/commands/models" +// CommitFileNode wraps a node and provides some commit-file-specific methods for it. type CommitFileNode struct { - Children []*CommitFileNode - File *models.CommitFile - Path string // e.g. '/path/to/mydir' - CompressionLevel int // equal to the number of forward slashes you'll see in the path when it's rendered in tree mode + *Node[models.CommitFile] } -var ( - _ INode = &CommitFileNode{} - _ types.ListItem = &CommitFileNode{} -) - -func (s *CommitFileNode) ID() string { - return s.GetPath() -} - -func (s *CommitFileNode) Description() string { - return s.GetPath() -} - -// methods satisfying INode interface - -func (s *CommitFileNode) IsNil() bool { - return s == nil -} - -func (s *CommitFileNode) IsLeaf() bool { - return s.File != nil -} - -func (s *CommitFileNode) GetPath() string { - return s.Path -} - -func (s *CommitFileNode) GetChildren() []INode { - return slices.Map(s.Children, func(child *CommitFileNode) INode { - return child - }) -} - -func (s *CommitFileNode) SetChildren(children []INode) { - castChildren := slices.Map(children, func(child INode) *CommitFileNode { - return child.(*CommitFileNode) - }) - - s.Children = castChildren -} - -func (s *CommitFileNode) GetCompressionLevel() int { - return s.CompressionLevel -} - -func (s *CommitFileNode) SetCompressionLevel(level int) { - s.CompressionLevel = level -} - -// methods utilising generic functions for INodes - -func (s *CommitFileNode) Sort() { - sortNode(s) -} - -func (s *CommitFileNode) ForEachFile(cb func(*models.CommitFile) error) error { - return forEachLeaf(s, func(n INode) error { - castNode := n.(*CommitFileNode) - return cb(castNode.File) - }) -} - -func (s *CommitFileNode) Any(test func(node *CommitFileNode) bool) bool { - return any(s, func(n INode) bool { - castNode := n.(*CommitFileNode) - return test(castNode) - }) -} - -func (s *CommitFileNode) Every(test func(node *CommitFileNode) bool) bool { - return every(s, func(n INode) bool { - castNode := n.(*CommitFileNode) - return test(castNode) - }) -} - -func (s *CommitFileNode) EveryFile(test func(file *models.CommitFile) bool) bool { - return every(s, func(n INode) bool { - castNode := n.(*CommitFileNode) - - return castNode.File == nil || test(castNode.File) - }) -} - -func (n *CommitFileNode) Flatten(collapsedPaths *CollapsedPaths) []*CommitFileNode { - results := flatten(n, collapsedPaths) - - return slices.Map(results, func(result INode) *CommitFileNode { - return result.(*CommitFileNode) - }) -} - -func (node *CommitFileNode) GetNodeAtIndex(index int, collapsedPaths *CollapsedPaths) *CommitFileNode { +func NewCommitFileNode(node *Node[models.CommitFile]) *CommitFileNode { if node == nil { return nil } - result := getNodeAtIndex(node, index, collapsedPaths) - if result == nil { - // not sure how this can be nil: we probably are missing a mutex somewhere - return nil - } - - return result.(*CommitFileNode) -} - -func (node *CommitFileNode) GetIndexForPath(path string, collapsedPaths *CollapsedPaths) (int, bool) { - return getIndexForPath(node, path, collapsedPaths) -} - -func (node *CommitFileNode) Size(collapsedPaths *CollapsedPaths) int { - if node == nil { - return 0 - } - - return size(node, collapsedPaths) -} - -func (s *CommitFileNode) Compress() { - // with these functions I try to only have type conversion code on the actual struct, - // but comparing interface values to nil is fraught with danger so I'm duplicating - // that code here. - if s == nil { - return - } - - compressAux(s) + return &CommitFileNode{Node: node} } -func (s *CommitFileNode) GetLeaves() []*CommitFileNode { - leaves := getLeaves(s) - - return slices.Map(leaves, func(leaf INode) *CommitFileNode { - return leaf.(*CommitFileNode) - }) -} - -// extra methods - -func (s *CommitFileNode) AnyFile(test func(file *models.CommitFile) bool) bool { - return s.Any(func(node *CommitFileNode) bool { - return node.IsLeaf() && test(node.File) - }) -} - -func (s *CommitFileNode) NameAtDepth(depth int) string { - splitName := split(s.Path) - name := join(splitName[depth:]) - - return name +// returns the underlying node, without any commit-file-specific methods attached +func (self *CommitFileNode) Raw() *Node[models.CommitFile] { + return self.Node } diff --git a/pkg/gui/filetree/commit_file_tree.go b/pkg/gui/filetree/commit_file_tree.go index e539c9dea..862db26f1 100644 --- a/pkg/gui/filetree/commit_file_tree.go +++ b/pkg/gui/filetree/commit_file_tree.go @@ -1,22 +1,24 @@ package filetree import ( + "github.com/jesseduffield/generics/slices" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/sirupsen/logrus" ) type ICommitFileTree interface { - ITree + ITree[models.CommitFile] Get(index int) *CommitFileNode GetFile(path string) *models.CommitFile GetAllItems() []*CommitFileNode GetAllFiles() []*models.CommitFile + GetRoot() *CommitFileNode } type CommitFileTree struct { getFiles func() []*models.CommitFile - tree *CommitFileNode + tree *Node[models.CommitFile] showTree bool log *logrus.Entry collapsedPaths *CollapsedPaths @@ -44,7 +46,7 @@ func (self *CommitFileTree) ToggleShowTree() { func (self *CommitFileTree) Get(index int) *CommitFileNode { // need to traverse the three depth first until we get to the index. - return self.tree.GetNodeAtIndex(index+1, self.collapsedPaths) // ignoring root + return NewCommitFileNode(self.tree.GetNodeAtIndex(index+1, self.collapsedPaths)) // ignoring root } func (self *CommitFileTree) GetIndexForPath(path string) (int, bool) { @@ -57,7 +59,10 @@ func (self *CommitFileTree) GetAllItems() []*CommitFileNode { return nil } - return self.tree.Flatten(self.collapsedPaths)[1:] // ignoring root + // ignoring root + return slices.Map(self.tree.Flatten(self.collapsedPaths)[1:], func(node *Node[models.CommitFile]) *CommitFileNode { + return NewCommitFileNode(node) + }) } func (self *CommitFileTree) Len() int { @@ -84,8 +89,8 @@ func (self *CommitFileTree) ToggleCollapsed(path string) { self.collapsedPaths.ToggleCollapsed(path) } -func (self *CommitFileTree) Tree() INode { - return self.tree +func (self *CommitFileTree) GetRoot() *CommitFileNode { + return NewCommitFileNode(self.tree) } func (self *CommitFileTree) CollapsedPaths() *CollapsedPaths { diff --git a/pkg/gui/filetree/file_node.go b/pkg/gui/filetree/file_node.go index 53f87c71b..092841b52 100644 --- a/pkg/gui/filetree/file_node.go +++ b/pkg/gui/filetree/file_node.go @@ -1,199 +1,47 @@ package filetree -import ( - "github.com/jesseduffield/generics/slices" - "github.com/jesseduffield/lazygit/pkg/commands/models" - "github.com/jesseduffield/lazygit/pkg/gui/types" -) +import "github.com/jesseduffield/lazygit/pkg/commands/models" +// FileNode wraps a node and provides some file-specific methods for it. type FileNode struct { - Children []*FileNode - File *models.File - Path string // e.g. '/path/to/mydir' - CompressionLevel int // equal to the number of forward slashes you'll see in the path when it's rendered in tree mode + *Node[models.File] } -var ( - _ INode = &FileNode{} - _ types.ListItem = &FileNode{} -) +var _ models.IFile = &FileNode{} -func (s *FileNode) ID() string { - return s.GetPath() -} - -func (s *FileNode) Description() string { - return s.GetPath() -} - -// methods satisfying INode interface - -// interfaces values whose concrete value is nil are not themselves nil -// hence the existence of this method -func (s *FileNode) IsNil() bool { - return s == nil -} - -func (s *FileNode) IsLeaf() bool { - return s.File != nil -} - -func (s *FileNode) GetPath() string { - return s.Path -} - -func (s *FileNode) GetPreviousPath() string { - if s.File != nil { - return s.File.GetPreviousPath() - } - return "" -} - -func (s *FileNode) GetChildren() []INode { - return slices.Map(s.Children, func(child *FileNode) INode { - return child - }) -} - -func (s *FileNode) SetChildren(children []INode) { - castChildren := slices.Map(children, func(child INode) *FileNode { - return child.(*FileNode) - }) - - s.Children = castChildren -} - -func (s *FileNode) GetCompressionLevel() int { - return s.CompressionLevel -} - -func (s *FileNode) SetCompressionLevel(level int) { - s.CompressionLevel = level -} - -// methods utilising generic functions for INodes - -func (s *FileNode) Sort() { - sortNode(s) -} - -func (s *FileNode) ForEachFile(cb func(*models.File) error) error { - return forEachLeaf(s, func(n INode) error { - castNode := n.(*FileNode) - return cb(castNode.File) - }) -} - -func (s *FileNode) Any(test func(node *FileNode) bool) bool { - return any(s, func(n INode) bool { - castNode := n.(*FileNode) - return test(castNode) - }) -} - -func (n *FileNode) Flatten(collapsedPaths *CollapsedPaths) []*FileNode { - results := flatten(n, collapsedPaths) - return slices.Map(results, func(result INode) *FileNode { - return result.(*FileNode) - }) -} - -func (node *FileNode) GetNodeAtIndex(index int, collapsedPaths *CollapsedPaths) *FileNode { +func NewFileNode(node *Node[models.File]) *FileNode { if node == nil { return nil } - result := getNodeAtIndex(node, index, collapsedPaths) - if result == nil { - // not sure how this can be nil: we probably are missing a mutex somewhere - return nil - } - - return result.(*FileNode) + return &FileNode{Node: node} } -func (node *FileNode) GetIndexForPath(path string, collapsedPaths *CollapsedPaths) (int, bool) { - return getIndexForPath(node, path, collapsedPaths) +// returns the underlying node, without any file-specific methods attached +func (self *FileNode) Raw() *Node[models.File] { + return self.Node } -func (node *FileNode) Size(collapsedPaths *CollapsedPaths) int { - if node == nil { - return 0 - } - - return size(node, collapsedPaths) +func (self *FileNode) GetHasUnstagedChanges() bool { + return self.SomeFile(func(file *models.File) bool { return file.HasUnstagedChanges }) } -func (s *FileNode) Compress() { - // with these functions I try to only have type conversion code on the actual struct, - // but comparing interface values to nil is fraught with danger so I'm duplicating - // that code here. - if s == nil { - return - } - - compressAux(s) +func (self *FileNode) GetHasStagedChanges() bool { + return self.SomeFile(func(file *models.File) bool { return file.HasStagedChanges }) } -func (node *FileNode) GetFilePathsMatching(test func(*models.File) bool) []string { - return getPathsMatching(node, func(n INode) bool { - castNode := n.(*FileNode) - if castNode.File == nil { - return false - } - return test(castNode.File) - }) +func (self *FileNode) GetHasInlineMergeConflicts() bool { + return self.SomeFile(func(file *models.File) bool { return file.HasInlineMergeConflicts }) } -func (s *FileNode) GetLeaves() []*FileNode { - leaves := getLeaves(s) - - return slices.Map(leaves, func(leaf INode) *FileNode { - return leaf.(*FileNode) - }) +func (self *FileNode) GetIsTracked() bool { + return self.SomeFile(func(file *models.File) bool { return file.Tracked }) } -// extra methods - -func (s *FileNode) GetHasUnstagedChanges() bool { - return s.AnyFile(func(file *models.File) bool { return file.HasUnstagedChanges }) -} - -func (s *FileNode) GetHasStagedChanges() bool { - return s.AnyFile(func(file *models.File) bool { return file.HasStagedChanges }) -} - -func (s *FileNode) GetHasInlineMergeConflicts() bool { - return s.AnyFile(func(file *models.File) bool { return file.HasInlineMergeConflicts }) -} - -func (s *FileNode) GetIsTracked() bool { - return s.AnyFile(func(file *models.File) bool { return file.Tracked }) -} - -func (s *FileNode) AnyFile(test func(file *models.File) bool) bool { - return s.Any(func(node *FileNode) bool { - return node.IsLeaf() && test(node.File) - }) -} - -func (s *FileNode) NameAtDepth(depth int) string { - splitName := split(s.Path) - name := join(splitName[depth:]) - - if s.File != nil && s.File.IsRename() { - splitPrevName := split(s.File.PreviousName) - - prevName := s.File.PreviousName - // if the file has just been renamed inside the same directory, we can shave off - // the prefix for the previous path too. Otherwise we'll keep it unchanged - sameParentDir := len(splitName) == len(splitPrevName) && join(splitName[0:depth]) == join(splitPrevName[0:depth]) - if sameParentDir { - prevName = join(splitPrevName[depth:]) - } - - return prevName + " → " + name +func (self *FileNode) GetPreviousPath() string { + if self.File == nil { + return "" } - return name + return self.File.PreviousName } diff --git a/pkg/gui/filetree/file_node_test.go b/pkg/gui/filetree/file_node_test.go index c7649bd16..a3b2b9aee 100644 --- a/pkg/gui/filetree/file_node_test.go +++ b/pkg/gui/filetree/file_node_test.go @@ -10,8 +10,8 @@ import ( func TestCompress(t *testing.T) { scenarios := []struct { name string - root *FileNode - expected *FileNode + root *Node[models.File] + expected *Node[models.File] }{ { name: "nil node", @@ -20,27 +20,27 @@ func TestCompress(t *testing.T) { }, { name: "leaf node", - root: &FileNode{ + root: &Node[models.File]{ Path: "", - Children: []*FileNode{ + Children: []*Node[models.File]{ {File: &models.File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Path: "test"}, }, }, - expected: &FileNode{ + expected: &Node[models.File]{ Path: "", - Children: []*FileNode{ + Children: []*Node[models.File]{ {File: &models.File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Path: "test"}, }, }, }, { name: "big example", - root: &FileNode{ + root: &Node[models.File]{ Path: "", - Children: []*FileNode{ + Children: []*Node[models.File]{ { Path: "dir1", - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "file2", ShortStatus: "M ", HasUnstagedChanges: true}, Path: "dir1/file2", @@ -49,7 +49,7 @@ func TestCompress(t *testing.T) { }, { Path: "dir2", - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "file3", ShortStatus: " M", HasStagedChanges: true}, Path: "dir2/file3", @@ -62,10 +62,10 @@ func TestCompress(t *testing.T) { }, { Path: "dir3", - Children: []*FileNode{ + Children: []*Node[models.File]{ { Path: "dir3/dir3-1", - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "file5", ShortStatus: "M ", HasUnstagedChanges: true}, Path: "dir3/dir3-1/file5", @@ -80,12 +80,12 @@ func TestCompress(t *testing.T) { }, }, }, - expected: &FileNode{ + expected: &Node[models.File]{ Path: "", - Children: []*FileNode{ + Children: []*Node[models.File]{ { Path: "dir1", - Children: []*FileNode{ + Children: []*Node[models.File]{ { File: &models.File{Name: "file2", ShortStatus: "M ", HasUnstagedChanges: true}, Path: "dir1/file2", @@ -94,7 +94,7 @@ func TestCompress(t *testing.T) { }, { Path: "dir2", |