Documentation
¶
Overview ¶
Package asciitree pretty-prints hierarchical node data structures as ASCII trees. Asciitree offers different styles, "pure ASCII" and Unicode-based line "graphics" (see illustration below).
root1 ├── 1 ├── 2 │ ├── 2.1 │ └── 2.2 └── 3 └── 3.1 root2 └── X
User-defined tree data structures can automatically be traversed if they are either structs or maps and they have been tagged. In many situations this avoids having to write adaptors (or more specific: visitors) that adapt your user data to the form needed by asciitree. With simple tagging, all you need to do is tag your data structure, such as in:
type node struct { Label string `asciitree:"label"` Props []string `asciitree:"properties"` Children []node `asciitree:"children"` }
Asciitree can both work with a single-root tree, as well as with multiple roots. Simply pass the Render() function either a single root node, or a slice of root nodes, and it will handle both cases automatically. You can also pass a user-data struct with only an `asciitree:"roots"` tag, attached to a struct field storing your root nodes. Traversal will then proceed as usual.
In addition to automatically rendering tagged user-data structs, asciitree can also automatically traverse maps if those follow these rules: (1) your map must be of type "map[string]interface{}". And (2), your map needs to use the well-known map keys "label", "properties", and "children". If one or more of these keys is missing, asciitree will assume them to be zero. Finally, you can optionally pass in a top-level map with the well-known map key "roots" holding your root nodes. Or you can pass in a slide of root nodes. The Render() function will detect these use case automatically and handle them accordingly.
Example ¶
package main import ( "fmt" asciitree "github.com/thediveo/go-asciitree" ) func main() { // user-defined tree data structure with asciitree-related field tags. type node struct { Label string `asciitree:"label"` Props []string `asciitree:"properties"` Children []node `asciitree:"children"` } // set up a tree of nodes. root := node{ Label: "root", Children: []node{ {Label: "child 1", Props: []string{"childish"}}, {Label: "child 2", Children: []node{ {Label: "grandchild 1", Props: []string{"very childish"}}, {Label: "grandchild 2"}, }}, {Label: "child 3"}, }, } // render the tree into a string and print it. fmt.Println(asciitree.RenderFancy(root)) }
Output: root ├─ child 1 │ • childish ├─ child 2 │ ├─ grandchild 1 │ │ • very childish │ └─ grandchild 2 └─ child 3
Example (MultiRoot) ¶
package main import ( "fmt" asciitree "github.com/thediveo/go-asciitree" ) func main() { // user-defined tree data structure with asciitree-related field tags. type node struct { Label string `asciitree:"label"` Props []string `asciitree:"properties"` Children []node `asciitree:"children"` } // set up two root nodes with their own tree of child nodes roots := []node{ { Label: "root 1", Children: []node{ {Label: "child 1", Props: []string{"childish"}}, {Label: "child 2", Children: []node{ {Label: "grandchild 1", Props: []string{"very childish"}}, {Label: "grandchild 2"}, }}, {Label: "child 3"}, }, }, { Label: "root 2", Children: []node{ {Label: "child 2-1"}, }, }, } // render the trees into a string and print it. fmt.Println(asciitree.RenderFancy(roots)) }
Output: root 1 ├─ child 1 │ • childish ├─ child 2 │ ├─ grandchild 1 │ │ • very childish │ └─ grandchild 2 └─ child 3 root 2 └─ child 2-1
Example (Sorted) ¶
package main import ( "fmt" asciitree "github.com/thediveo/go-asciitree" ) func main() { // user-defined tree data structure with asciitree-related field tags. type node struct { Label string `asciitree:"label"` Props []string `asciitree:"properties"` Children []node `asciitree:"children"` } // set up a tree of nodes. rootb := node{ Label: "beta root", Children: []node{ {Label: "foo", Props: []string{"childish"}}, {Label: "alpha", Children: []node{ {Label: "grandchild 2"}, {Label: "grandchild 1", Props: []string{"very childish"}}, }}, {Label: "bar"}, }, } roota := node{ Label: "alpha root", Children: []node{ {Label: "alphachild"}, }, } // create a new visitor and tell it to sort the nodes by label, and also // to sort the properties. sortingVisitor := asciitree.NewMapStructVisitor(true, true) // render the tree(s) into a string and print it. fmt.Println(asciitree.Render([]node{rootb, roota}, sortingVisitor, asciitree.LineTreeStyler)) }
Output: alpha root └─ alphachild beta root ├─ alpha │ ├─ grandchild 1 │ │ • very childish │ └─ grandchild 2 ├─ bar └─ foo • childish
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ASCIIStyle = TreeStyle{
Fork: "+",
Nodeconn: "-",
Nofork: "|",
Lastnode: "`",
Property: "*",
}
ASCIIStyle styles rendered trees using only "pure" ASCII characters, without any help of special line or box characters.
var DefaultTreeStyler = NewTreeStyler(ASCIIStyle)
DefaultTreeStyler offers a pure ASCII tree styler, using only "safe" ASCII characters, but no Unicode characters. Ideal for the lovers of unwatered ASCII art.
var DefaultVisitor = &MapStructVisitor{}
DefaultVisitor provides visitor capable of traversing (annotated) maps and structs.
var LineStyle = TreeStyle{
Fork: "├",
Nodeconn: "─",
Nofork: "│",
Lastnode: "└",
Property: "•",
}
LineStyle styles ASCII trees using Unicode line characters.
var LineTreeStyler = NewTreeStyler(LineStyle)
LineTreeStyler uses Unicode box characters to draw slightly fancy tree branches.
Functions ¶
func Render ¶
func Render(roots interface{}, visitor Visitor, styler *TreeStyler) string
Render renders a tree (or multi-root tree) into a multi-line text string, using the supplied visitor and tree styler.
The roots can be specified as a slice of structs, or also as a single struct. In every case, the passed root(s), as well as their subtree nodes need to have two struct fields exported and tagged as `asciitree:"label"` and `asciitree:"children"` respectively.
For the visitor, you might want to simply use the DefaultVisitor that handles annotated structs and maps with well-known keys.
As a styler, simply use DefaultTreeStyler, or the slightly more fancyful NewTreeStyler(LineStyle).
Example ¶
package main import ( "fmt" asciitree "github.com/thediveo/go-asciitree" ) func main() { // user-defined tree data structure with asciitree-related field tags. type tree struct { Label string `asciitree:"label"` Children []tree `asciitree:"children"` } // set up a tree of nodes. root := tree{ Label: "root", Children: []tree{ {Label: "child 1"}, {Label: "child 2", Children: []tree{ {Label: "grandchild 1"}, {Label: "grandchild 2"}, }}, {Label: "child 3"}, }, } // render the tree into a string and print it. fmt.Println( asciitree.Render(root, asciitree.DefaultVisitor, asciitree.DefaultTreeStyler)) }
Output: root +- child 1 +- child 2 | +- grandchild 1 | `- grandchild 2 `- child 3
func RenderFancy ¶
func RenderFancy(roots interface{}) string
RenderFancy works like RenderPlain, rendering a tree or multi-root tree into a multi-line text string, but it uses Unicode box characters to render the branch lines.
Example ¶
package main import ( "fmt" asciitree "github.com/thediveo/go-asciitree" ) func main() { // user-defined tree data structure with asciitree-related field tags. type tree struct { Label string `asciitree:"label"` Children []tree `asciitree:"children"` } // set up a tree of nodes. root := tree{ Label: "root", Children: []tree{ {Label: "child 1"}, {Label: "child 2", Children: []tree{ {Label: "grandchild 1"}, {Label: "grandchild 2"}, }}, {Label: "child 3"}, }, } // render the tree into a string and print it. fmt.Println(asciitree.RenderFancy(root)) }
Output: root ├─ child 1 ├─ child 2 │ ├─ grandchild 1 │ └─ grandchild 2 └─ child 3
func RenderPlain ¶
func RenderPlain(roots interface{}) string
RenderPlain renders a tree or multi-root tree into a multi-line text string using the default tree styling and (user data) visitor.
The roots can be specified as a slice of structs, or also as a single struct. In every case, the passed root(s), as well as their subtree nodes need to have two struct fields exported and tagged as `asciitree:"label"` and `asciitree:"children"` respectively.
Example ¶
package main import ( "fmt" asciitree "github.com/thediveo/go-asciitree" ) func main() { // user-defined tree data structure with asciitree-related field tags. type tree struct { Label string `asciitree:"label"` Children []tree `asciitree:"children"` } // set up a tree of nodes. root := tree{ Label: "root", Children: []tree{ {Label: "child 1"}, {Label: "child 2", Children: []tree{ {Label: "grandchild 1"}, {Label: "grandchild 2"}, }}, {Label: "child 3"}, }, } // render the tree into a string and print it. fmt.Println(asciitree.RenderPlain(root)) }
Output: root +- child 1 +- child 2 | +- grandchild 1 | `- grandchild 2 `- child 3
Types ¶
type MapStructVisitor ¶
MapStructVisitor visits tagged ("annotated") user-defined structs as well as maps (the latter using well-known keys) and retrieves their tree-relevant data. For convenience, it also handles slices and pointers to structs and maps.
func NewMapStructVisitor ¶
func NewMapStructVisitor(sortNodes bool, sortProperties bool) *MapStructVisitor
NewMapStructVisitor creates a visitor that optionally sorts nodes and their properties.
func (*MapStructVisitor) Get ¶
func (v *MapStructVisitor) Get(node reflect.Value) (label string, properties []string, children reflect.Value)
Get returns the label, properties, and children of a tree node, hiding pesty details about how to fetch them from tagged structs or maps with well-known fields.
type TreeStyle ¶
type TreeStyle struct { Fork string // depicts forking off a node, such as "├". Nodeconn string // depicts the branch going to a node "leaf", such as "─". Nofork string // depicts a continuing vertical main branch, such as "│". Lastnode string // depicts a vertical main branch ending in a node, such as "└". Property string // depicts a property, such as "•" }
TreeStyle defines the ASCII art elements required for "painting" beautiful ASCII trees. In this case, we also subsume Unicode under ASCII for a suitable definition of "ASCII" and "Unicode".
type TreeStyler ¶
type TreeStyler struct { Style TreeStyle // The specific TreeStyle to use, such as ASCIIStyle, or LineStyle. ChildIndent int // The indentation of child nodes. PropIndent int // The indentation of properties w.r.t. their node }
TreeStyler describes the tree branch and node properties indentations, as well as the style of "line art" to use when rendering ASCII trees.
func NewTreeStyler ¶
func NewTreeStyler(style TreeStyle) *TreeStyler
NewTreeStyler returns a Style object suitable for use with rendering trees.
type Visitor ¶
type Visitor interface { Roots(roots reflect.Value) (children []reflect.Value) Label(node reflect.Value) (label string) Get(node reflect.Value) (label string, properties []string, children reflect.Value) }
Visitor looks into user-defined data structures, trying to locate the anointed, erm, annotated ("tagged") user-data entries which represent node labels, properties, and children. The Visitor interface is used by tree renderers for visiting nodes in order to retrieve their tree-relevant information while traversing trees.
Visitors thus avoid having to implement an asciitree-specific interface on user data-structures, that is, they avoid adaptors. In many use cases, a MapStructVisitor will suffice as it implements the visitor pattern on tagged structs and maps with well-known keys.
Please note that Visitors do not traverse; that is the job of the asciitree Render...() functions.