diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2020-11-15 10:45:55 +1100 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2021-03-30 21:57:00 +1100 |
commit | 45939171ea6537562270975348fe2919c9c60b95 (patch) | |
tree | b9c4138c32b54577a3d6f17acdc0f4132c2ebc9e /pkg/commands/models | |
parent | 049849264e561d2867d0d94940b1f66dcac77e6b (diff) |
WIP
start moving to new interface
WIP
WIP
WIP
WIP
WIP
Diffstat (limited to 'pkg/commands/models')
-rw-r--r-- | pkg/commands/models/status_line_node.go | 137 | ||||
-rw-r--r-- | pkg/commands/models/status_line_node_test.go | 76 |
2 files changed, 213 insertions, 0 deletions
diff --git a/pkg/commands/models/status_line_node.go b/pkg/commands/models/status_line_node.go new file mode 100644 index 000000000..042a0fceb --- /dev/null +++ b/pkg/commands/models/status_line_node.go @@ -0,0 +1,137 @@ +package models + +import ( + "sort" +) + +type StatusLineNode struct { + Children []*StatusLineNode + File *File + Name string + Collapsed bool +} + +func (s *StatusLineNode) GetShortStatus() string { + // need to see if any child has unstaged changes. + if s.IsLeaf() { + return s.File.ShortStatus + } + + firstChar := " " + secondChar := " " + if s.HasStagedChanges() { + firstChar = "M" + } + if s.HasUnstagedChanges() { + secondChar = "M" + } + + return firstChar + secondChar +} + +func (s *StatusLineNode) HasUnstagedChanges() bool { + if s.IsLeaf() { + return s.File.HasUnstagedChanges + } + + for _, child := range s.Children { + if child.HasUnstagedChanges() { + return true + } + } + + return false +} + +func (s *StatusLineNode) HasStagedChanges() bool { + if s.IsLeaf() { + return s.File.HasStagedChanges + } + + for _, child := range s.Children { + if child.HasStagedChanges() { + return true + } + } + + return false +} + +func (s *StatusLineNode) GetNodeAtIndex(index int) *StatusLineNode { + node, _ := s.getNodeAtIndexAux(index) + + return node +} + +func (s *StatusLineNode) getNodeAtIndexAux(index int) (*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 + } + } + + return nil, offset +} + +func (s *StatusLineNode) IsLeaf() bool { + return len(s.Children) == 0 +} + +func (s *StatusLineNode) Size() int { + output := 1 + + for _, child := range s.Children { + output += child.Size() + } + + return output +} + +func (s *StatusLineNode) Flatten() []*StatusLineNode { + arr := []*StatusLineNode{s} + + for _, child := range s.Children { + arr = append(arr, child.Flatten()...) + } + + return arr +} + +func (s *StatusLineNode) SortTree() { + s.sortChildren() + + for _, child := range s.Children { + child.SortTree() + } +} + +func (s *StatusLineNode) sortChildren() { + if s.IsLeaf() { + return + } + + sortedChildren := make([]*StatusLineNode, len(s.Children)) + copy(sortedChildren, s.Children) + + sort.Slice(sortedChildren, func(i, j int) bool { + if !sortedChildren[i].IsLeaf() && sortedChildren[j].IsLeaf() { + return true + } + if sortedChildren[i].IsLeaf() && !sortedChildren[j].IsLeaf() { + return false + } + + return sortedChildren[i].Name < sortedChildren[j].Name + }) + + // TODO: think about making this in-place + s.Children = sortedChildren +} diff --git a/pkg/commands/models/status_line_node_test.go b/pkg/commands/models/status_line_node_test.go new file mode 100644 index 000000000..f8114fcf1 --- /dev/null +++ b/pkg/commands/models/status_line_node_test.go @@ -0,0 +1,76 @@ +package models + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRender(t *testing.T) { + scenarios := []struct { + name string + root *StatusLineNode + expected []string + }{ + { + name: "nil node", + root: nil, + expected: []string{}, + }, + { + name: "leaf node", + root: &StatusLineNode{ + Name: "", + Children: []*StatusLineNode{ + {File: &File{Name: "test", ShortStatus: " M", HasStagedChanges: true}, Name: "test"}, + }, + }, + expected: []string{" M test"}, + }, + { + name: "big example", + root: &StatusLineNode{ + Name: "", + Children: []*StatusLineNode{ + { + Name: "dir1", + Collapsed: true, + Children: []*StatusLineNode{ + { + File: &File{Name: "file2", ShortStatus: "M ", HasUnstagedChanges: true}, + Name: "file2", + }, + }, + }, + { + Name: "dir2", + Children: []*StatusLineNode{ + { + File: &File{Name: "file3", ShortStatus: " M", HasStagedChanges: true}, + Name: "file3", + }, + { + File: &File{Name: "file4", ShortStatus: "M ", HasUnstagedChanges: true}, + Name: "file4", + }, + }, + }, + { + File: &File{Name: "file1", ShortStatus: "M ", HasUnstagedChanges: true}, + Name: "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) + }) + } +} |