Skip to content

Commit

Permalink
docs: use more tree terminology
Browse files Browse the repository at this point in the history
  • Loading branch information
maaslalani committed May 30, 2024
1 parent 7aafa50 commit e86617e
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 191 deletions.
4 changes: 2 additions & 2 deletions list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,9 @@ func (l *List) ItemStyleFunc(f StyleFunc) *List {
func (l *List) Item(item any) *List {
switch item := item.(type) {
case *List:
l.tree.Item(item.tree)
l.tree.Child(item.tree)
default:
l.tree.Item(item)
l.tree.Child(item)
}
return l
}
Expand Down
18 changes: 9 additions & 9 deletions list/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,18 @@ func TestComplexSublist(t *testing.T) {

tree.New().
EnumeratorStyle(style2).
Item("another\nmultine\nstring").
Item("something").
Item("a subtree").
Item(
Child("another\nmultine\nstring").
Child("something").
Child("a subtree").
Child(
tree.New().
EnumeratorStyle(style2).
Item("yup").
Item("many itens").
Item("another"),
Child("yup").
Child("many itens").
Child("another"),
).
Item("hallo").
Item("wunderbar!"),
Child("hallo").
Child("wunderbar!"),
).
Item("this is a tree\nand other obvious statements"),
),
Expand Down
2 changes: 1 addition & 1 deletion tree/children.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (n NodeChildren) At(i int) Node {
func NewStringData(data ...string) Children {
result := make([]Node, 0, len(data))
for _, d := range data {
s := StringNode(d)
s := Leaf{value: d}
result = append(result, &s)
}
return NodeChildren(result)
Expand Down
4 changes: 2 additions & 2 deletions tree/renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ func (r *renderer) render(node Node, root bool, prefix string) string {
renderer := r
switch child := child.(type) {
case *Tree:
if child.renderer != nil {
renderer = child.renderer
if child.r != nil {
renderer = child.r
}
}
if s := renderer.render(
Expand Down
182 changes: 94 additions & 88 deletions tree/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,47 +44,51 @@ type Node interface {
Hidden() bool
}

// StringNode is a node without children and with a string describing it.
type StringNode string
// Leaf is a node without children.
type Leaf struct {
value string
hidden bool
}

// Children conforms with Node.
//
// Always returns no children.
func (StringNode) Children() Children { return NodeChildren(nil) }
// Children of a Leaf node are always empty.
func (Leaf) Children() Children {
return NodeChildren(nil)
}

// Value conforms with Node.
//
// Returns the value of the string itself.
func (s StringNode) Value() string { return string(s) }
// Value of a leaf node returns its value.
func (s Leaf) Value() string {
return s.value
}

// Hidden conforms with Node.
//
// Always returns false.
func (s StringNode) Hidden() bool { return false }
// Hidden returns whether a Leaf node is hidden.
func (s Leaf) Hidden() bool {
return s.hidden
}

// String returns conforms with Stringer.
func (s StringNode) String() string { return s.Value() }
// String returns the string representation of a Leaf node.
func (s Leaf) String() string {
return s.Value()
}

// Tree implements the Node interface.
// It has a name and, optionally, children.
// Tree implements a Node.
type Tree struct { //nolint:revive
value string
renderer *renderer
rendererOnce sync.Once
children Children
hide bool
offset [2]int
value string
hidden bool
offset [2]int
children Children

r *renderer
ronce sync.Once
}

// Returns true if this node is hidden.
// Hidden returns whether this node is hidden.
func (t *Tree) Hidden() bool {
return t.hide
return t.hidden
}

// Hide sets whether or not to hide the tree.
// This is useful for collapsing or hiding sub-trees.
// Hide sets whether to hide the tree node.
func (t *Tree) Hide(hide bool) *Tree {
t.hide = hide
t.hidden = hide
return t
}

Expand Down Expand Up @@ -113,12 +117,12 @@ func (t *Tree) Value() string {
return t.value
}

// String conforms with Stringer.
// String returns the string representation of the tree node.
func (t *Tree) String() string {
return t.ensureRenderer().render(t, true, "")
}

// Item appends an item to a list.
// Child appends an item to a list.
//
// If the tree being added is a new TreeNode without a name, we add its
// children to the previous string node.
Expand All @@ -127,8 +131,8 @@ func (t *Tree) String() string {
//
// Both of these should result in the same thing:
//
// New().Root("foo").Items("bar", New().Item("zaz"), "qux")
// New().Root("foo").Items(New().Root("bar").Item("zaz"), "qux")
// New().Root("foo").Items("bar", New().Child("zaz"), "qux")
// New().Root("foo").Items(New().Root("bar").Child("zaz"), "qux")
//
// The resulting tree would be:
//
Expand All @@ -138,54 +142,44 @@ func (t *Tree) String() string {
// └── qux
//
// You may also change the tree style using Enumerator.
func (t *Tree) Item(item any) *Tree {
switch item := item.(type) {
case *Tree:
newItem, rm := ensureParent(t.children, item)
if rm >= 0 {
t.children = t.children.(NodeChildren).Remove(rm)
}
t.children = t.children.(NodeChildren).Append(newItem)
case Children:
for i := 0; i < item.Length(); i++ {
t.children = t.children.(NodeChildren).Append(item.At(i))
}
case Node:
t.children = t.children.(NodeChildren).Append(item)
case fmt.Stringer:
s := StringNode(item.String())
t.children = t.children.(NodeChildren).Append(s)
case string:
s := StringNode(item)
t.children = t.children.(NodeChildren).Append(&s)
// XXX: passing []any and []string would be the most common errors it
// seems, this fixes it, but doesn't handle other types of slices...
// Maybe it's best to not handle any of these?
case []any:
return t.Items(item...)
case []string:
ss := make([]any, 0, len(item))
for _, s := range item {
ss = append(ss, s)
func (t *Tree) Child(children ...any) *Tree {
for _, child := range children {
switch item := child.(type) {
case *Tree:
newItem, rm := ensureParent(t.children, item)
if rm >= 0 {
t.children = t.children.(NodeChildren).Remove(rm)
}
t.children = t.children.(NodeChildren).Append(newItem)
case Children:
for i := 0; i < item.Length(); i++ {
t.children = t.children.(NodeChildren).Append(item.At(i))
}
case Node:
t.children = t.children.(NodeChildren).Append(item)
case fmt.Stringer:
s := Leaf{value: item.String()}
t.children = t.children.(NodeChildren).Append(s)
case string:
s := Leaf{value: item}
t.children = t.children.(NodeChildren).Append(&s)
// XXX: passing []any and []string would be the most common errors it
// seems, this fixes it, but doesn't handle other types of slices...
// Maybe it's best to not handle any of these?
case []any:
return t.Child(item...)
case []string:
ss := make([]any, 0, len(item))
for _, s := range item {
ss = append(ss, s)
}
return t.Child(ss...)
case nil:
continue
default:
// optimistically try to convert to a string...
return t.Child(fmt.Sprintf("%v", item))
}
return t.Items(ss...)
case nil:
return t
default:
// optimistically try to convert to a string...
return t.Item(fmt.Sprintf("%v", item))
}
return t
}

// Items add multiple items to the tree.
//
// t := tree.New().
// Root("Nyx").
// Items("Qux", "Quux").
func (t *Tree) Items(items ...any) *Tree {
for _, item := range items {
t.Item(item)
}
return t
}
Expand All @@ -205,13 +199,13 @@ func ensureParent(nodes Children, item *Tree) (*Tree, int) {
switch parent := parent.(type) {
case *Tree:
for i := 0; i < item.Children().Length(); i++ {
parent.Item(item.children.At(i))
parent.Child(item.children.At(i))
}
return parent, j
case StringNode:
case Leaf:
item.value = parent.Value()
return item, j
case *StringNode:
case *Leaf:
item.value = parent.Value()
return item, j
}
Expand All @@ -220,10 +214,10 @@ func ensureParent(nodes Children, item *Tree) (*Tree, int) {

// Ensure the tree node has a renderer.
func (t *Tree) ensureRenderer() *renderer {
t.rendererOnce.Do(func() {
t.renderer = newRenderer()
t.ronce.Do(func() {
t.r = newRenderer()
})
return t.renderer
return t.r
}

// EnumeratorStyle sets the enumeration style.
Expand Down Expand Up @@ -261,7 +255,7 @@ func (t *Tree) EnumeratorStyleFunc(fn StyleFunc) *Tree {
// ItemStyle sets the item style.
//
// t := tree.New("Duck", "Duck", "Duck", "Goose", "Duck").
// ItemStyle(lipgloss.NewStyle().Foreground(lipgloss.Color(255)))
// ItemStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("255")))
func (t *Tree) ItemStyle(style lipgloss.Style) *Tree {
t.ensureRenderer().style.itemFunc = func(Children, int) lipgloss.Style { return style }
return t
Expand Down Expand Up @@ -297,6 +291,7 @@ func (t *Tree) Enumerator(enum Enumerator) *Tree {
return t
}

// Indenter sets the indenter implementation.
func (t *Tree) Indenter(indenter Indenter) *Tree {
t.ensureRenderer().indenter = indenter
return t
Expand All @@ -311,7 +306,18 @@ func (t *Tree) Children() Children {
return NodeChildren(data)
}

// Root sets the tree node root name.
// Root returns a new tree with the root set.
//
// tree.Root(root)
//
// It is a shorthand for:
//
// tree.New().Root(root)
func Root(root string) *Tree {
return New().Root(root)
}

// Root sets the root value of this tree.
func (t *Tree) Root(root string) *Tree {
t.value = root
return t
Expand Down
Loading

0 comments on commit e86617e

Please sign in to comment.