mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
vendoring of treeprint library
This commit is contained in:
parent
ccb3a7c584
commit
8b037432e7
20
vendor/github.com/xlab/treeprint/LICENSE
generated
vendored
Normal file
20
vendor/github.com/xlab/treeprint/LICENSE
generated
vendored
Normal file
@ -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.
|
126
vendor/github.com/xlab/treeprint/README.md
generated
vendored
Normal file
126
vendor/github.com/xlab/treeprint/README.md
generated
vendored
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
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.
|
||||||
|
|
||||||
|
## Use cases
|
||||||
|
|
||||||
|
When you want to render a complex data structure:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
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 {
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
Yay! So it works.
|
||||||
|
|
||||||
|
## License
|
||||||
|
MIT
|
47
vendor/github.com/xlab/treeprint/helpers.go
generated
vendored
Normal file
47
vendor/github.com/xlab/treeprint/helpers.go
generated
vendored
Normal file
@ -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, " ")
|
||||||
|
}
|
340
vendor/github.com/xlab/treeprint/struct.go
generated
vendored
Normal file
340
vendor/github.com/xlab/treeprint/struct.go
generated
vendored
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
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 !val.CanSet() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
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", 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 !val.CanSet() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
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", 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 !val.CanSet() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
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", 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)
|
||||||
|
if !val.CanSet() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
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", 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)
|
||||||
|
if !val.CanSet() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
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", 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)
|
||||||
|
if !val.CanSet() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
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", 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
|
||||||
|
}
|
184
vendor/github.com/xlab/treeprint/treeprint.go
generated
vendored
Normal file
184
vendor/github.com/xlab/treeprint/treeprint.go
generated
vendored
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
// Package treeprint provides a simple ASCII tree composing tool.
|
||||||
|
package treeprint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Value interface{}
|
||||||
|
type MetaValue interface{}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// String renders the tree or subtree as a string.
|
||||||
|
String() string
|
||||||
|
// Bytes renders the tree or subtree as byteslice.
|
||||||
|
Bytes() []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type node struct {
|
||||||
|
Root *node
|
||||||
|
Meta MetaValue
|
||||||
|
Value Value
|
||||||
|
Nodes []*node
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *node) AddNode(v Value) Tree {
|
||||||
|
n.Nodes = append(n.Nodes, &node{
|
||||||
|
Root: n,
|
||||||
|
Value: v,
|
||||||
|
})
|
||||||
|
if n.Root != nil {
|
||||||
|
return n.Root
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *node) AddMetaNode(meta MetaValue, v Value) Tree {
|
||||||
|
n.Nodes = append(n.Nodes, &node{
|
||||||
|
Root: n,
|
||||||
|
Meta: meta,
|
||||||
|
Value: v,
|
||||||
|
})
|
||||||
|
if n.Root != nil {
|
||||||
|
return n.Root
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *node) AddBranch(v Value) Tree {
|
||||||
|
branch := &node{
|
||||||
|
Value: v,
|
||||||
|
}
|
||||||
|
n.Nodes = append(n.Nodes, branch)
|
||||||
|
return branch
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *node) AddMetaBranch(meta MetaValue, v Value) Tree {
|
||||||
|
branch := &node{
|
||||||
|
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
|
||||||
|
levelEnded := make(map[int]bool)
|
||||||
|
if n.Root == nil {
|
||||||
|
buf.WriteString(string(EdgeTypeStart))
|
||||||
|
buf.WriteByte('\n')
|
||||||
|
} else {
|
||||||
|
edge := EdgeTypeMid
|
||||||
|
if len(n.Nodes) == 0 {
|
||||||
|
edge = EdgeTypeEnd
|
||||||
|
levelEnded[level] = true
|
||||||
|
}
|
||||||
|
printValues(buf, 0, levelEnded, edge, n.Meta, n.Value)
|
||||||
|
}
|
||||||
|
if len(n.Nodes) > 0 {
|
||||||
|
printNodes(buf, level, levelEnded, n.Nodes)
|
||||||
|
}
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *node) String() string {
|
||||||
|
return string(n.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
func printNodes(wr io.Writer,
|
||||||
|
level int, levelEnded map[int]bool, nodes []*node) {
|
||||||
|
|
||||||
|
for i, node := range nodes {
|
||||||
|
edge := EdgeTypeMid
|
||||||
|
if i == len(nodes)-1 {
|
||||||
|
levelEnded[level] = true
|
||||||
|
edge = EdgeTypeEnd
|
||||||
|
}
|
||||||
|
printValues(wr, level, levelEnded, edge, node.Meta, node.Value)
|
||||||
|
if len(node.Nodes) > 0 {
|
||||||
|
printNodes(wr, level+1, levelEnded, node.Nodes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printValues(wr io.Writer,
|
||||||
|
level int, levelEnded map[int]bool, edge EdgeType, meta MetaValue, val Value) {
|
||||||
|
|
||||||
|
for i := 0; i < level; i++ {
|
||||||
|
if levelEnded[i] {
|
||||||
|
fmt.Fprint(wr, " ")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(wr, "%s ", EdgeTypeLink)
|
||||||
|
}
|
||||||
|
if meta != nil {
|
||||||
|
fmt.Fprintf(wr, "%s [%v] %v\n", edge, meta, val)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Fprintf(wr, "%s %v\n", edge, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
type EdgeType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
EdgeTypeStart EdgeType = "."
|
||||||
|
EdgeTypeLink EdgeType = "│"
|
||||||
|
EdgeTypeMid EdgeType = "├──"
|
||||||
|
EdgeTypeEnd EdgeType = "└──"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New() Tree {
|
||||||
|
return &node{}
|
||||||
|
}
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
@ -3210,6 +3210,12 @@
|
|||||||
"revision": "ff0417f4272e480246b4507459b3f6ae721a87ac",
|
"revision": "ff0417f4272e480246b4507459b3f6ae721a87ac",
|
||||||
"revisionTime": "2017-02-25T17:21:24Z"
|
"revisionTime": "2017-02-25T17:21:24Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "xtw+Llokq30p1Gn+Q8JBZ7NtE+I=",
|
||||||
|
"path": "github.com/xlab/treeprint",
|
||||||
|
"revision": "1d6e342255576c977e946a2384fc487a22d3fceb",
|
||||||
|
"revisionTime": "2016-10-29T10:40:18Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "eXEiPlpDRaamJQ4vPX/9t333kQc=",
|
"checksumSHA1": "eXEiPlpDRaamJQ4vPX/9t333kQc=",
|
||||||
"comment": "v1.5.4-13-g75ce5fb",
|
"comment": "v1.5.4-13-g75ce5fb",
|
||||||
|
Loading…
Reference in New Issue
Block a user