Skip to content

Commit

Permalink
fix: comments + cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Dolev Hadar committed Dec 5, 2024
1 parent cc9513a commit 021d11d
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 112 deletions.
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,3 @@ require (
golang.org/x/text v0.3.8 // indirect
)

replace github.com/charmbracelet/lipgloss v0.0.0-unpublished => ../lipgloss
71 changes: 18 additions & 53 deletions tree/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ type Node struct {
value any

opts itemOptions

// TODO: move to lipgloss.Tree?
size int
}

// IsSelected returns whether this item is selected.
Expand All @@ -44,7 +41,7 @@ func (t *Node) Depth() int {
// Size returns the number of nodes in the tree.
// Note that if a child isn't open, its size is 1
func (t *Node) Size() int {
return t.size
return len(t.AllNodes())
}

// YOffset returns the vertical offset of the Node
Expand Down Expand Up @@ -82,32 +79,31 @@ type itemOptions struct {
}

// Used to print the Node's tree
// TODO: Value is not called on the root node, so we need to repeat the open/closed character
// Should this be fixed in lipgloss?
func (t *Node) String() string {
// s := t.opts.styles.OpenIndicatorStyle
// if t.open {
// return s.Render(t.opts.openCharacter+" ") + t.tree.String()
// }
// return s.Render(t.opts.closedCharacter+" ") + t.tree.String()
return t.tree.String()
s := t.opts.styles.OpenIndicatorStyle
if t.open {
return s.Render(t.opts.openCharacter+" ") + t.tree.String()
}
return s.Render(t.opts.closedCharacter+" ") + t.tree.String()
}

// Value returns the root name of this node.
func (t *Node) Value() string {
func (t *Node) getStyle() lipgloss.Style {
s := t.opts.styles
var ns lipgloss.Style

if t.yOffset == t.opts.treeYOffset {
ns = s.selectedNodeFunc(Nodes{t}, 0)
return s.selectedNodeFunc(Nodes{t}, 0)
} else if t.yOffset == 0 {
ns = s.rootNodeFunc(Nodes{t}, 0)
return s.rootNodeFunc(Nodes{t}, 0)
} else if t.isRoot {
ns = s.parentNodeFunc(Nodes{t}, 0)
return s.parentNodeFunc(Nodes{t}, 0)
} else {
ns = s.nodeFunc(Nodes{t}, 0)
return s.nodeFunc(Nodes{t}, 0)
}
}

// Value returns the root name of this node.
func (t *Node) Value() string {
s := t.opts.styles
ns := t.getStyle()
v := ns.Render(t.tree.Value())

if t.isRoot {
Expand Down Expand Up @@ -187,12 +183,9 @@ func (t *Node) ItemStyle(s lipgloss.Style) *Node {
// }
// return lipgloss.NewStyle().Foreground(dimColor)
// })
//
// TODO: currently unused as this is set in the Styles struct.
func (t *Node) ItemStyleFunc(f StyleFunc) *Node {
t.tree.ItemStyleFunc(func(children ltree.Children, i int) lipgloss.Style {
c := make(Nodes, children.Length())
// TODO: if we expose Depth and Size in lipgloss, we can avoid this
for i := 0; i < children.Length(); i++ {
c[i] = children.At(i).(*Node)
}
Expand All @@ -201,8 +194,6 @@ func (t *Node) ItemStyleFunc(f StyleFunc) *Node {
return t
}

// TODO: support IndentStyleFunc in lipgloss so we can have a full background for the item

// Enumerator sets the enumerator implementation. This can be used to change the
// way the branches indicators look. Lipgloss includes predefined enumerators
// for a classic or rounded tree. For example, you can have a rounded tree:
Expand Down Expand Up @@ -243,7 +234,6 @@ func (t *Node) Indenter(indenter ltree.Indenter) *Node {
// EnumeratorStyle sets a static style for all enumerators.
//
// Use EnumeratorStyleFunc to conditionally set styles based on the tree node.
// TODO: currently unused as this is set in the Styles struct.
func (t *Node) EnumeratorStyle(style lipgloss.Style) *Node {
t.tree.EnumeratorStyle(style)
return t
Expand All @@ -259,8 +249,6 @@ func (t *Node) EnumeratorStyle(style lipgloss.Style) *Node {
// }
// return lipgloss.NewStyle().Foreground(dimColor)
// })
//
// TODO: currently unused as this is set in the Styles struct.
func (t *Node) EnumeratorStyleFunc(f func(children ltree.Children, i int) lipgloss.Style) *Node {
t.tree.EnumeratorStyleFunc(f)
return t
Expand All @@ -269,7 +257,6 @@ func (t *Node) EnumeratorStyleFunc(f func(children ltree.Children, i int) lipglo
// IndenterStyle sets a static style for all indenters.
//
// Use IndenterStyleFunc to conditionally set styles based on the tree node.
// TODO: currently unused as this is set in the Styles struct.
func (t *Node) IndenterStyle(style lipgloss.Style) *Node {
t.tree.IndenterStyle(style)
return t
Expand All @@ -285,8 +272,6 @@ func (t *Node) IndenterStyle(style lipgloss.Style) *Node {
// }
// return lipgloss.NewStyle().Foreground(dimColor)
// })
//
// TODO: currently unused as this is set in the Styles struct.
func (t *Node) IndenterStyleFunc(f func(children ltree.Children, i int) lipgloss.Style) *Node {
t.tree.IndenterStyleFunc(f)
return t
Expand All @@ -313,7 +298,6 @@ func (t *Node) Child(children ...any) *Node {
for _, child := range children {
switch child := child.(type) {
case *Node:
t.size = t.size + child.size
t.tree.Child(child)

// Close the node again as the number of children has changed
Expand All @@ -324,10 +308,8 @@ func (t *Node) Child(children ...any) *Node {
item := new(Node)
item.opts.styles = DefaultStyles()
item.tree = ltree.Root(child)
item.size = 1
item.open = false
item.value = child
t.size = t.size + item.size
t.tree.Child(item)

// Close the node again as the number of children has changed
Expand All @@ -344,7 +326,6 @@ func (t *Node) Child(children ...any) *Node {
func NewNode() *Node {
t := new(Node)
t.opts.styles = DefaultStyles()
t.size = 1
t.open = true
t.isRoot = true
t.tree = ltree.New()
Expand All @@ -353,24 +334,8 @@ func NewNode() *Node {

// Root returns a new tree with the root set.
func Root(root any) *Node {
t := new(Node)
t.opts.styles = DefaultStyles()
t.size = 1
t := NewNode()
t.value = root
t.open = true
t.isRoot = true
switch root := root.(type) {
case *Node:
t.tree = ltree.Root(root.Value())
default:
item := new(Node)
item.value = root
item.opts.styles = DefaultStyles()
item.size = 1
item.open = true
item.isRoot = true
t.tree = ltree.Root(item)
}

t.tree = ltree.Root(root)
return t
}
2 changes: 1 addition & 1 deletion tree/styles.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func DefaultStyles() (s Styles) {

s.CursorStyle = lipgloss.NewStyle().PaddingRight(1).Foreground(lipgloss.Color("212")).Bold(true)

s.EnumeratorStyle = lipgloss.NewStyle().Foreground(verySubduedColor).PaddingRight(1)
s.EnumeratorStyle = lipgloss.NewStyle().Foreground(verySubduedColor)
s.IndenterStyle = lipgloss.NewStyle().Foreground(verySubduedColor)
s.OpenIndicatorStyle = lipgloss.NewStyle().Foreground(subduedColor)

Expand Down
77 changes: 20 additions & 57 deletions tree/tree.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package tree

import (
"fmt"
"strings"

tea "github.com/charmbracelet/bubbletea"
Expand Down Expand Up @@ -215,17 +214,6 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {

// View renders the component.
func (m Model) View() string {
// var leftDebugView string
// TODO: remove
// if os.Getenv("DEBUG") == "true" {
// leftDebugView = printDebugInfo(m.root) + " "
// }

// treeView := lipgloss.JoinHorizontal(
// lipgloss.Top,
// leftDebugView,
// m.viewport.View(),
// )
treeView := m.viewport.View()

var help string
Expand Down Expand Up @@ -287,7 +275,7 @@ func (m *Model) GoToTop() {

// GoToBottom moves the selection to the bottom of the tree.
func (m *Model) GoToBottom() {
m.updateViewport(m.root.size)
m.updateViewport(m.root.Size())
}

// ToggleCurrentNode toggles the current node open/close state.
Expand Down Expand Up @@ -334,7 +322,7 @@ func (m *Model) updateViewport(movement int) {
return
}

m.yOffset = max(min(m.root.size-1, m.yOffset+movement), 0)
m.yOffset = max(min(m.root.Size()-1, m.yOffset+movement), 0)
m.updateStyles()

cursor := m.cursorView()
Expand Down Expand Up @@ -398,6 +386,10 @@ func (m *Model) SetStyles(styles Styles) {
if m.root != nil {
m.root.EnumeratorStyle(styles.EnumeratorStyle)
m.root.IndenterStyle(styles.IndenterStyle)
m.root.ItemStyleFunc(func(children Nodes, i int) lipgloss.Style {
child := children.At(i)
return child.getStyle()
})
}

m.styles = styles
Expand Down Expand Up @@ -504,7 +496,7 @@ func (m Model) cursorView() string {
if m.CursorCharacter == "" {
return ""
}
cursor := strings.Split(strings.Repeat(" ", m.root.size), "")
cursor := strings.Split(strings.Repeat(" ", m.root.Size()), "")
cursor[m.yOffset] = m.CursorCharacter
return m.styles.CursorStyle.Render(lipgloss.JoinVertical(lipgloss.Left, cursor...))
}
Expand All @@ -526,7 +518,6 @@ func (m *Model) AllNodes() []*Node {

func (m *Model) setAttributes() {
setDepths(m.root, 0)
setSizes(m.root)
setYOffsets(m.root)
}

Expand All @@ -541,19 +532,6 @@ func setDepths(t *Node, depth int) {
}
}

// setSizes updates each Node's size
// Note that if a child isn't open, its size is 1
func setSizes(t *Node) int {
children := t.tree.Children()
size := 1 + children.Length()
for i := 0; i < children.Length(); i++ {
child := children.At(i)
size = size + setSizes(child.(*Node)) - 1
}
t.size = size
return size
}

// setYOffsets updates each Node's yOffset based on how many items are "above" it
func setYOffsets(t *Node) {
children := t.tree.Children()
Expand All @@ -563,7 +541,7 @@ func setYOffsets(t *Node) {
if child, ok := child.(*Node); ok {
child.yOffset = t.yOffset + above + i + 1
setYOffsets(child)
above += child.size - 1
above += child.Size() - 1
}
}
}
Expand Down Expand Up @@ -601,7 +579,6 @@ func (m *Model) Indenter(indenter ltree.Indenter) *Model {
// Since the selected node changes, we need to capture m.yOffset in the
// style function's closure again
func (m *Model) updateStyles() {
// TODO: add RootStyleFunc to the Node interface?
if m.root != nil {
m.root.RootStyle(m.rootStyle())
}
Expand All @@ -622,18 +599,18 @@ func (m *Model) getItemOpts() *itemOptions {
}
}

// selectedNodeStyle sets the node style
// and takes into account whether it's selected or not
func (m *Model) selectedNodeStyle() StyleFunc {
return func(children Nodes, i int) lipgloss.Style {
child := children.At(i)
if child.yOffset == m.yOffset {
return m.styles.selectedNodeFunc(children, i)
}

return m.styles.nodeFunc(children, i)
}
}
// // selectedNodeStyle sets the node style
// // and takes into account whether it's selected or not
// func (m *Model) selectedNodeStyle() StyleFunc {
// return func(children Nodes, i int) lipgloss.Style {
// child := children.At(i)
// if child.yOffset == m.yOffset {
// return m.styles.selectedNodeFunc(children, i)
// }
//
// return m.styles.nodeFunc(children, i)
// }
// }

func (m *Model) rootStyle() lipgloss.Style {
if m.root.yOffset == m.yOffset {
Expand All @@ -643,20 +620,6 @@ func (m *Model) rootStyle() lipgloss.Style {
return m.styles.rootNodeFunc(Nodes{m.root}, 0)
}

// TODO: remove
func printDebugInfo(t *Node) string {
debug := fmt.Sprintf("size=%2d y=%2d depth=%2d", t.size, t.yOffset, t.depth)
children := t.Children()
for i := 0; i < children.Length(); i++ {
child := children.At(i)
if child, ok := child.(*Node); ok {
debug = debug + "\n" + printDebugInfo(child)
}
}

return debug
}

// findNode starts a DFS search for the node with the given yOffset
// starting from the given item
func findNode(t *Node, yOffset int) *Node {
Expand Down

0 comments on commit 021d11d

Please sign in to comment.