summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2022-07-31 19:10:16 +1000
committerJesse Duffield <jessedduffield@gmail.com>2022-07-31 19:43:14 +1000
commit682be18507ecf202116100547cb5049f471af664 (patch)
tree27c93b614f10f682ae952c1e39390e253afc83b4
parent2ca2acaca55711a63e48e5d0c8f0c0678218b81c (diff)
refactor to use generics for file nodes
use less generic names
-rw-r--r--pkg/gui/controllers/commits_files_controller.go5
-rw-r--r--pkg/gui/controllers/files_controller.go2
-rw-r--r--pkg/gui/filetree/build_tree.go24
-rw-r--r--pkg/gui/filetree/build_tree_test.go92
-rw-r--r--pkg/gui/filetree/commit_file_node.go161
-rw-r--r--pkg/gui/filetree/commit_file_tree.go17
-rw-r--r--pkg/gui/filetree/file_node.go194
-rw-r--r--pkg/gui/filetree/file_node_test.go34
-rw-r--r--pkg/gui/filetree/file_tree.go22
-rw-r--r--pkg/gui/filetree/inode.go206
-rw-r--r--pkg/gui/filetree/node.go301
-rw-r--r--pkg/gui/presentation/files.go77
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",