charmbracelet / lipgloss

Style definitions for nice terminal layouts πŸ‘„
MIT License
8.03k stars 228 forks source link

Dynamically generating a tree #375

Closed rchaganti closed 3 weeks ago

rchaganti commented 3 weeks ago

Describe the bug When dynamically generating a tree, the child nodes are not aligned properly

Setup Please complete the following information along with version numbers, if applicable.

To Reproduce Steps to reproduce the behavior: Run the following program.

Source Code

package main

import (
    "fmt"

    "github.com/charmbracelet/lipgloss/tree"
)

type Node struct {
    Name     string
    Category []Category
}

type Category struct {
    Name  string
    Items []Item
}

type Item struct {
    Name string
}

var categories = []Category{
    {
        Name: "cat1",
        Items: []Item{
            {Name: "item1"},
            {Name: "item2"},
        },
    },
    {
        Name: "cat2",
        Items: []Item{
            {Name: "item3"},
            {Name: "item4"},
        },
    },
}

func main() {
    data := Node{
        Name:     "root",
        Category: categories,
    }

    // Create a new tree
    root := tree.Root(data.Name)

    for _, cat := range data.Category {
        cTree := root.Child(
            tree.New().Root(cat.Name),
        )

        for _, item := range cat.Items {
            cTree.Child(item.Name)
        }
    }

    fmt.Println(root)
}

Expected behavior root, child, and leaf aligned per the relationships.

Screenshots

$ go run main.go 
root
β”œβ”€β”€ cat1
β”œβ”€β”€ item1
β”œβ”€β”€ item2
β”œβ”€β”€ cat2
β”œβ”€β”€ item3
└── item4

Additional context Add any other context about the problem here.

bashbunni commented 3 weeks ago

Hey, the issue here is where you assign the output of root.Child to cTree which makes cTree a pointer to the root tree, not the child.

Here's a working version of what you're looking for:

package main

import (
    "fmt"

    "github.com/charmbracelet/lipgloss/tree"
)

type Node struct {
    Name     string
    Category []Category
}

type Category struct {
    Name  string
    Items []Item
}

type Item struct {
    Name string
}

var categories = []Category{
    {
        Name: "cat1",
        Items: []Item{
            {Name: "item1"},
            {Name: "item2"},
        },
    },
    {
        Name: "cat2",
        Items: []Item{
            {Name: "item3"},
            {Name: "item4"},
        },
    },
}

func main() {
    data := Node{
        Name:     "root",
        Category: categories,
    }

    // Create a new tree
    root := tree.Root(data.Name)

    for _, cat := range data.Category {
        cTree := tree.New().Root(cat.Name)

        for _, item := range cat.Items {
            cTree.Child(item.Name)
        }
        root.Child(cTree)
    }

    fmt.Println(root)
}

Output

 root                                                                                               
 β”œβ”€β”€ cat1                                                                                           
 β”‚   β”œβ”€β”€ item1                                                                                      
 β”‚   └── item2                                                                                      
 └── cat2                                                                                           
     β”œβ”€β”€ item3                                                                                      
     └── item4 
rchaganti commented 3 weeks ago

Awesome! Thank you.