diff options
Diffstat (limited to 'vendor/github.com/xlab')
| -rw-r--r-- | vendor/github.com/xlab/treeprint/.gitignore | 3 | ||||
| -rw-r--r-- | vendor/github.com/xlab/treeprint/LICENSE | 20 | ||||
| -rw-r--r-- | vendor/github.com/xlab/treeprint/README.md | 154 | ||||
| -rw-r--r-- | vendor/github.com/xlab/treeprint/helpers.go | 47 | ||||
| -rw-r--r-- | vendor/github.com/xlab/treeprint/struct.go | 322 | ||||
| -rw-r--r-- | vendor/github.com/xlab/treeprint/treeprint.go | 294 |
6 files changed, 840 insertions, 0 deletions
diff --git a/vendor/github.com/xlab/treeprint/.gitignore b/vendor/github.com/xlab/treeprint/.gitignore new file mode 100644 index 0000000..7c9305d --- /dev/null +++ b/vendor/github.com/xlab/treeprint/.gitignore @@ -0,0 +1,3 @@ +vendor/** +.idea +**/**.iml diff --git a/vendor/github.com/xlab/treeprint/LICENSE b/vendor/github.com/xlab/treeprint/LICENSE new file mode 100644 index 0000000..5ab533a --- /dev/null +++ b/vendor/github.com/xlab/treeprint/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) +Copyright © 2016 Maxim Kupriianov <max@kc.vc> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/xlab/treeprint/README.md b/vendor/github.com/xlab/treeprint/README.md new file mode 100644 index 0000000..59fb121 --- /dev/null +++ b/vendor/github.com/xlab/treeprint/README.md @@ -0,0 +1,154 @@ +treeprint [](https://godoc.org/github.com/xlab/treeprint)  +========= + +Package `treeprint` provides a simple ASCII tree composing tool. + +<a href="https://upload.wikimedia.org/wikipedia/commons/5/58/ENC_SYSTEME_FIGURE.jpeg"><img alt="SYSTEME FIGURE" src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/ENC_SYSTEME_FIGURE.jpeg/896px-ENC_SYSTEME_FIGURE.jpeg" align="left" width="300"></a> + +If you are familiar with the [tree](http://mama.indstate.edu/users/ice/tree/) utility that is a recursive directory listing command that produces a depth indented listing of files, then you have the idea of what it would look like. + +On my system the command yields the following + +``` + $ tree +. +├── LICENSE +├── README.md +├── treeprint.go +└── treeprint_test.go + +0 directories, 4 files +``` + +and I'd like to have the same format for my Go data structures when I print them. + +## Installation + +``` +$ go get github.com/xlab/treeprint +``` + +## Concept of work + +The general idea is that you initialise a new tree with `treeprint.New()` and then add nodes and +branches into it. Use `AddNode()` when you want add a node on the same level as the target or +use `AddBranch()` when you want to go a level deeper. So `tree.AddBranch().AddNode().AddNode()` would +create a new level with two distinct nodes on it. So `tree.AddNode().AddNode()` is a flat thing and +`tree.AddBranch().AddBranch().AddBranch()` is a high thing. Use `String()` or `Bytes()` on a branch +to render a subtree, or use it on the root to print the whole tree. + +The utility will yield Unicode-friendly trees. The output is predictable and there is no platform-dependent exceptions, so if you have issues with displaying the tree in the console, all platform-related transformations can be done after the tree has been rendered: [an example](https://github.com/xlab/treeprint/issues/2#issuecomment-324944141) for Asian locales. + +## Use cases + +### When you want to render a complex data structure: + +```go +func main() { + // to add a custom root name use `treeprint.NewWithRoot()` instead + tree := treeprint.New() + + // create a new branch in the root + one := tree.AddBranch("one") + + // add some nodes + one.AddNode("subnode1").AddNode("subnode2") + + // create a new sub-branch + one.AddBranch("two"). + AddNode("subnode1").AddNode("subnode2"). // add some nodes + AddBranch("three"). // add a new sub-branch + AddNode("subnode1").AddNode("subnode2") // add some nodes too + + // add one more node that should surround the inner branch + one.AddNode("subnode3") + + // add a new node to the root + tree.AddNode("outernode") + + fmt.Println(tree.String()) +} +``` + +Will give you: + +``` +. +├── one +│ ├── subnode1 +│ ├── subnode2 +│ ├── two +│ │ ├── subnode1 +│ │ ├── subnode2 +│ │ └── three +│ │ ├── subnode1 +│ │ └── subnode2 +│ └── subnode3 +└── outernode +``` + +### Another case, when you have to make a tree where any leaf may have some meta-data (as `tree` is capable of it): + +```go +func main { + // to add a custom root name use `treeprint.NewWithRoot()` instead + tree := treeprint.New() + + tree.AddNode("Dockerfile") + tree.AddNode("Makefile") + tree.AddNode("aws.sh") + tree.AddMetaBranch(" 204", "bin"). + AddNode("dbmaker").AddNode("someserver").AddNode("testtool") + tree.AddMetaBranch(" 374", "deploy"). + AddNode("Makefile").AddNode("bootstrap.sh") + tree.AddMetaNode("122K", "testtool.a") + + fmt.Println(tree.String()) +} +``` + +Output: + +``` +. +├── Dockerfile +├── Makefile +├── aws.sh +├── [ 204] bin +│ ├── dbmaker +│ ├── someserver +│ └── testtool +├── [ 374] deploy +│ ├── Makefile +│ └── bootstrap.sh +└── [122K] testtool.a +``` + +### Iterating over the tree nodes + +```go +tree := New() + +one := tree.AddBranch("one") +one.AddNode("one-subnode1").AddNode("one-subnode2") +one.AddBranch("two").AddNode("two-subnode1").AddNode("two-subnode2"). + AddBranch("three").AddNode("three-subnode1").AddNode("three-subnode2") +tree.AddNode("outernode") + +// if you need to iterate over the whole tree +// call `VisitAll` from your top root node. +tree.VisitAll(func(item *node) { + if len(item.Nodes) > 0 { + // branch nodes + fmt.Println(item.Value) // will output one, two, three + } else { + // leaf nodes + fmt.Println(item.Value) // will output one-*, two-*, three-* and outernode + } +}) + +``` +Yay! So it works. + +## License +MIT diff --git a/vendor/github.com/xlab/treeprint/helpers.go b/vendor/github.com/xlab/treeprint/helpers.go new file mode 100644 index 0000000..a091a5a --- /dev/null +++ b/vendor/github.com/xlab/treeprint/helpers.go @@ -0,0 +1,47 @@ +package treeprint + +import ( + "reflect" + "strings" +) + +func isEmpty(v *reflect.Value) bool { + switch v.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + return false +} + +func tagSpec(tag string) (name string, omit bool) { + parts := strings.Split(tag, ",") + if len(parts) < 2 { + return tag, false + } + if parts[1] == "omitempty" { + return parts[0], true + } + return parts[0], false +} + +func filterTags(tag reflect.StructTag) string { + tags := strings.Split(string(tag), " ") + filtered := make([]string, 0, len(tags)) + for i := range tags { + if strings.HasPrefix(tags[i], "tree:") { + continue + } + filtered = append(filtered, tags[i]) + } + return strings.Join(filtered, " ") +} diff --git a/vendor/github.com/xlab/treeprint/struct.go b/vendor/github.com/xlab/treeprint/struct.go new file mode 100644 index 0000000..4d5cc82 --- /dev/null +++ b/vendor/github.com/xlab/treeprint/struct.go @@ -0,0 +1,322 @@ +package treeprint + +import ( + "fmt" + "reflect" + "strings" +) + +type StructTreeOption int + +const ( + StructNameTree StructTreeOption = iota + StructValueTree + StructTagTree + StructTypeTree + StructTypeSizeTree +) + +func FromStruct(v interface{}, opt ...StructTreeOption) (Tree, error) { + var treeOpt StructTreeOption + if len(opt) > 0 { + treeOpt = opt[0] + } + switch treeOpt { + case StructNameTree: + tree := New() + err := nameTree(tree, v) + return tree, err + case StructValueTree: + tree := New() + err := valueTree(tree, v) + return tree, err + case StructTagTree: + tree := New() + err := tagTree(tree, v) + return tree, err + case StructTypeTree: + tree := New() + err := typeTree(tree, v) + return tree, err + case StructTypeSizeTree: + tree := New() + err := typeSizeTree(tree, v) + return tree, err + default: + err := fmt.Errorf("treeprint: invalid StructTreeOption %v", treeOpt) + return nil, err + } +} + +type FmtFunc func(name string, v interface{}) (string, bool) + +func FromStructWithMeta(v interface{}, fmtFunc FmtFunc) (Tree, error) { + if fmtFunc == nil { + tree := New() + err := nameTree(tree, v) + return tree, err + } + tree := New() + err := metaTree(tree, v, fmtFunc) + return tree, err +} + +func Repr(v interface{}) string { + tree := New() + vType := reflect.TypeOf(v) + vValue := reflect.ValueOf(v) + _, val, isStruct := getValue(vType, &vValue) + if !isStruct { + return fmt.Sprintf("%+v", val.Interface()) + } + err := valueTree(tree, val.Interface()) + if err != nil { + return err.Error() + } + return tree.String() +} + +func nameTree(tree Tree, v interface{}) error { + typ, val, err := checkType(v) + if err != nil { + return err + } + fields := typ.NumField() + for i := 0; i < fields; i++ { + field := typ.Field(i) + fieldValue := val.Field(i) + name, skip, omit := getMeta(field.Name, field.Tag) + if skip || omit && isEmpty(&fieldValue) { + continue + } + typ, val, isStruct := getValue(field.Type, &fieldValue) + if !isStruct { + tree.AddNode(name) + continue + } else if subNum := typ.NumField(); subNum == 0 { + tree.AddNode(name) + continue + } + branch := tree.AddBranch(name) + if err := nameTree(branch, val.Interface()); err != nil { + err := fmt.Errorf("%v on struct branch %s", err, name) + return err + } + } + return nil +} + +func getMeta(fieldName string, tag reflect.StructTag) (name string, skip, omit bool) { + if tagStr := tag.Get("tree"); len(tagStr) > 0 { + name, omit = tagSpec(tagStr) + } + if name == "-" { + return fieldName, true, omit + } + if len(name) == 0 { + name = fieldName + } else if trimmed := strings.TrimSpace(name); len(trimmed) == 0 { + name = fieldName + } + return +} + +func valueTree(tree Tree, v interface{}) error { + typ, val, err := checkType(v) + if err != nil { + return err + } + fields := typ.NumField() + for i := 0; i < fields; i++ { + field := typ.Field(i) + fieldValue := val.Field(i) + name, skip, omit := getMeta(field.Name, field.Tag) + if skip || omit && isEmpty(&fieldValue) { + continue + } + typ, val, isStruct := getValue(field.Type, &fieldValue) + if !isStruct { + tree.AddMetaNode(val.Interface(), name) + continue + } else if subNum := typ.NumField(); subNum == 0 { + tree.AddMetaNode(val.Interface(), name) + continue + } + branch := tree.AddBranch(name) + if err := valueTree(branch, val.Interface()); err != nil { + err := fmt.Errorf("%v on struct branch %s", err, name) + return err + } + } + return nil +} + +func tagTree(tree Tree, v interface{}) error { + typ, val, err := checkType(v) + if err != nil { + return err + } + fields := typ.NumField() + for i := 0; i < fields; i++ { + field := typ.Field(i) + fieldValue := val.Field(i) + name, skip, omit := getMeta(field.Name, field.Tag) + if skip || omit && isEmpty(&fieldValue) { + continue + } + filteredTag := filterTags(field.Tag) + typ, val, isStruct := getValue(field.Type, &fieldValue) + if !isStruct { + tree.AddMetaNode(filteredTag, name) + continue + } else if subNum := typ.NumField(); subNum == 0 { + tree.AddMetaNode(filteredTag, name) + continue + } + branch := tree.AddMetaBranch(filteredTag, name) + if err := tagTree(branch, val.Interface()); err != nil { + err := fmt.Errorf("%v on struct branch %s", err, name) + return err + } + } + return nil +} + +func typeTree(tree Tree, v interface{}) error { + typ, val, err := checkType(v) + if err != nil { + return err + } + fields := typ.NumField() + for i := 0; i < fields; i++ { + field := typ.Field(i) + fieldValue := val.Field(i) + name, skip, omit := getMeta(field.Name, field.Tag) + if skip || omit && isEmpty(&fieldValue) { + continue + } + typ, val, isStruct := getValue(field.Type, &fieldValue) + typename := fmt.Sprintf("%T", val.Interface()) + if !isStruct { + tree.AddMetaNode(typename, name) + continue + } else if subNum := typ.NumField(); subNum == 0 { + tree.AddMetaNode(typename, name) + continue + } + branch := tree.AddMetaBranch(typename, name) + if err := typeTree(branch, val.Interface()); err != nil { + err := fmt.Errorf("%v on struct branch %s", err, name) + return err + } + } + return nil +} + +func typeSizeTree(tree Tree, v interface{}) error { + typ, val, err := checkType(v) + if err != nil { + return err + } + fields := typ.NumField() + for i := 0; i < fields; i++ { + field := typ.Field(i) + fieldValue := val.Field(i) + name, skip, omit := getMeta(field.Name, field.Tag) + if skip || omit && isEmpty(&fieldValue) { + continue + } + typ, val, isStruct := getValue(field.Type, &fieldValue) + typesize := typ.Size() + if !isStruct { + tree.AddMetaNode(typesize, name) + continue + } else if subNum := typ.NumField(); subNum == 0 { + tree.AddMetaNode(typesize, name) + continue + } + branch := tree.AddMetaBranch(typesize, name) + if err := typeSizeTree(branch, val.Interface()); err != nil { + err := fmt.Errorf("%v on struct branch %s", err, name) + return err + } + } + return nil +} + +func metaTree(tree Tree, v interface{}, fmtFunc FmtFunc) error { + typ, val, err := checkType(v) + if err != nil { + return err + } + fields := typ.NumField() + for i := 0; i < fields; i++ { + field := typ.Field(i) + fieldValue := val.Field(i) + name, skip, omit := getMeta(field.Name, field.Tag) + if skip || omit && isEmpty(&fieldValue) { + continue + } + typ, val, isStruct := getValue(field.Type, &fieldValue) + formatted, show := fmtFunc(name, val.Interface()) + if !isStruct { + if show { + tree.AddMetaNode(formatted, name) + continue + } + tree.AddNode(name) + continue + } else if subNum := typ.NumField(); subNum == 0 { + if show { + tree.AddMetaNode(formatted, name) + continue + } + tree.AddNode(name) + continue + } + var branch Tree + if show { + branch = tree.AddMetaBranch(formatted, name) + } else { + branch = tree.AddBranch(name) + } + if err := metaTree(branch, val.Interface(), fmtFunc); err != nil { + err := fmt.Errorf("%v on struct branch %s", err, name) + return err + } + } + return nil +} + +func getValue(typ reflect.Type, val *reflect.Value) (reflect.Type, *reflect.Value, bool) { + switch typ.Kind() { + case reflect.Ptr: + typ = typ.Elem() + if typ.Kind() == reflect.Struct { + elem := val.Elem() + return typ, &elem, true + } + case reflect.Struct: + return typ, val, true + } + return typ, val, false +} + +func checkType(v interface{}) (reflect.Type, *reflect.Value, error) { + typ := reflect.TypeOf(v) + val := reflect.ValueOf(v) + switch typ.Kind() { + case reflect.Ptr: + typ = typ.Elem() + if typ.Kind() != reflect.Struct { + err := fmt.Errorf("treeprint: %T is not a struct we could work with", v) + return nil, nil, err + } + val = val.Elem() + case reflect.Struct: + default: + err := fmt.Errorf("treeprint: %T is not a struct we could work with", v) + return nil, nil, err + } + return typ, &val, nil +} diff --git a/vendor/github.com/xlab/treeprint/treeprint.go b/vendor/github.com/xlab/treeprint/treeprint.go new file mode 100644 index 0000000..fc8204b --- /dev/null +++ b/vendor/github.com/xlab/treeprint/treeprint.go @@ -0,0 +1,294 @@ +// Package treeprint provides a simple ASCII tree composing tool. +package treeprint + +import ( + "bytes" + "fmt" + "io" + "reflect" + "strings" +) + +// Value defines any value +type Value interface{} + +// MetaValue defines any meta value +type MetaValue interface{} + +// NodeVisitor function type for iterating over nodes +type NodeVisitor func(item *Node) + +// Tree represents a tree structure with leaf-nodes and branch-nodes. +type Tree interface { + // AddNode adds a new Node to a branch. + AddNode(v Value) Tree + // AddMetaNode adds a new Node with meta value provided to a branch. + AddMetaNode(meta MetaValue, v Value) Tree + // AddBranch adds a new branch Node (a level deeper). + AddBranch(v Value) Tree + // AddMetaBranch adds a new branch Node (a level deeper) with meta value provided. + AddMetaBranch(meta MetaValue, v Value) Tree + // Branch converts a leaf-Node to a branch-Node, + // applying this on a branch-Node does no effect. + Branch() Tree + // FindByMeta finds a Node whose meta value matches the provided one by reflect.DeepEqual, + // returns nil if not found. + FindByMeta(meta MetaValue) Tree + // FindByValue finds a Node whose value matches the provided one by reflect.DeepEqual, + // returns nil if not found. + FindByValue(value Value) Tree + // returns the last Node of a tree + FindLastNode() Tree + // String renders the tree or subtree as a string. + String() string + // Bytes renders the tree or subtree as byteslice. + Bytes() []byte + + SetValue(value Value) + SetMetaValue(meta MetaValue) + + // VisitAll iterates over the tree, branches and nodes. + // If need to iterate over the whole tree, use the root Node. + // Note this method uses a breadth-first approach. + VisitAll(fn NodeVisitor) +} + +type Node struct { + Root *Node + Meta MetaValue + Value Value + Nodes []*Node +} + +func (n *Node) FindLastNode() Tree { + ns := n.Nodes + if len(ns) == 0 { + return nil + } + return ns[len(ns)-1] +} + +func (n *Node) AddNode(v Value) Tree { + n.Nodes = append(n.Nodes, &Node{ + Root: n, + Value: v, + }) + return n +} + +func (n *Node) AddMetaNode(meta MetaValue, v Value) Tree { + n.Nodes = append(n.Nodes, &Node{ + Root: n, + Meta: meta, + Value: v, + }) + return n +} + +func (n *Node) AddBranch(v Value) Tree { + branch := &Node{ + Root: n, + Value: v, + } + n.Nodes = append(n.Nodes, branch) + return branch +} + +func (n *Node) AddMetaBranch(meta MetaValue, v Value) Tree { + branch := &Node{ + Root: n, + Meta: meta, + Value: v, + } + n.Nodes = append(n.Nodes, branch) + return branch +} + +func (n *Node) Branch() Tree { + n.Root = nil + return n +} + +func (n *Node) FindByMeta(meta MetaValue) Tree { + for _, node := range n.Nodes { + if reflect.DeepEqual(node.Meta, meta) { + return node + } + if v := node.FindByMeta(meta); v != nil { + return v + } + } + return nil +} + +func (n *Node) FindByValue(value Value) Tree { + for _, node := range n.Nodes { + if reflect.DeepEqual(node.Value, value) { + return node + } + if v := node.FindByMeta(value); v != nil { + return v + } + } + return nil +} + +func (n *Node) Bytes() []byte { + buf := new(bytes.Buffer) + level := 0 + var levelsEnded []int + if n.Root == nil { + if n.Meta != nil { + buf.WriteString(fmt.Sprintf("[%v] %v", n.Meta, n.Value)) + } else { + buf.WriteString(fmt.Sprintf("%v", n.Value)) + } + buf.WriteByte('\n') + } else { + edge := EdgeTypeMid + if len(n.Nodes) == 0 { + edge = EdgeTypeEnd + levelsEnded = append(levelsEnded, level) + } + printValues(buf, 0, levelsEnded, edge, n) + } + if len(n.Nodes) > 0 { + printNodes(buf, level, levelsEnded, n.Nodes) + } + return buf.Bytes() +} + +func (n *Node) String() string { + return string(n.Bytes()) +} + +func (n *Node) SetValue(value Value) { + n.Value = value +} + +func (n *Node) SetMetaValue(meta MetaValue) { + n.Meta = meta +} + +func (n *Node) VisitAll(fn NodeVisitor) { + for _, node := range n.Nodes { + fn(node) + + if len(node.Nodes) > 0 { + node.VisitAll(fn) + continue + } + } +} + +func printNodes(wr io.Writer, + level int, levelsEnded []int, nodes []*Node) { + + for i, node := range nodes { + edge := EdgeTypeMid + if i == len(nodes)-1 { + levelsEnded = append(levelsEnded, level) + edge = EdgeTypeEnd + } + printValues(wr, level, levelsEnded, edge, node) + if len(node.Nodes) > 0 { + printNodes(wr, level+1, levelsEnded, node.Nodes) + } + } +} + +func printValues(wr io.Writer, + level int, levelsEnded []int, edge EdgeType, node *Node) { + + for i := 0; i < level; i++ { + if isEnded(levelsEnded, i) { + fmt.Fprint(wr, strings.Repeat(" ", IndentSize+1)) + continue + } + fmt.Fprintf(wr, "%s%s", EdgeTypeLink, strings.Repeat(" ", IndentSize)) + } + + val := renderValue(level, node) + meta := node.Meta + + if meta != nil { + fmt.Fprintf(wr, "%s [%v] %v\n", edge, meta, val) + return + } + fmt.Fprintf(wr, "%s %v\n", edge, val) +} + +func isEnded(levelsEnded []int, level int) bool { + for _, l := range levelsEnded { + if l == level { + return true + } + } + return false +} + +func renderValue(level int, node *Node) Value { + lines := strings.Split(fmt.Sprintf("%v", node.Value), "\n") + + // If value does not contain multiple lines, return itself. + if len(lines) < 2 { + return node.Value + } + + // If value contains multiple lines, + // generate a padding and prefix each line with it. + pad := padding(level, node) + + for i := 1; i < len(lines); i++ { + lines[i] = fmt.Sprintf("%s%s", pad, lines[i]) + } + + return strings.Join(lines, "\n") +} + +// padding returns a padding for the multiline values with correctly placed link edges. +// It is generated by traversing the tree upwards (from leaf to the root of the tree) +// and, on each level, checking if the Node the last one of its siblings. +// If a Node is the last one, the padding on that level should be empty (there's nothing to link to below it). +// If a Node is not the last one, the padding on that level should be the link edge so the sibling below is correctly connected. +func padding(level int, node *Node) string { + links := make([]string, level+1) + + for node.Root != nil { + if isLast(node) { + links[level] = strings.Repeat(" ", IndentSize+1) + } else { + links[level] = fmt.Sprintf("%s%s", EdgeTypeLink, strings.Repeat(" ", IndentSize)) + } + level-- + node = node.Root + } + + return strings.Join(links, "") +} + +// isLast checks if the Node is the last one in the slice of its parent children +func isLast(n *Node) bool { + return n == n.Root.FindLastNode() +} + +type EdgeType string + +var ( + EdgeTypeLink EdgeType = "│" + EdgeTypeMid EdgeType = "├──" + EdgeTypeEnd EdgeType = "└──" +) + +// IndentSize is the number of spaces per tree level. +var IndentSize = 3 + +// New Generates new tree +func New() Tree { + return &Node{Value: "."} +} + +// NewWithRoot Generates new tree with the given root value +func NewWithRoot(root Value) Tree { + return &Node{Value: root} +} |
