github.com/dolthub/go-mysql-server@v0.18.0/sql/treeprinter.go (about) 1 // Copyright 2020-2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package sql 16 17 import ( 18 "bufio" 19 "bytes" 20 "errors" 21 "fmt" 22 "io" 23 "strings" 24 ) 25 26 // TreePrinter is a printer for tree nodes. 27 type TreePrinter struct { 28 buf bytes.Buffer 29 nodeWritten bool 30 written bool 31 } 32 33 // NewTreePrinter creates a new tree printer. 34 func NewTreePrinter() *TreePrinter { 35 return new(TreePrinter) 36 } 37 38 // WriteNode writes the main node. 39 func (p *TreePrinter) WriteNode(format string, args ...interface{}) error { 40 if p.nodeWritten { 41 return ErrNodeAlreadyWritten 42 } 43 44 _, err := fmt.Fprintf(&p.buf, format, args...) 45 if err != nil { 46 return err 47 } 48 p.nodeWritten = true 49 p.buf.WriteRune('\n') 50 return nil 51 } 52 53 var ( 54 // ErrNodeNotWritten is returned when the children are printed before the node. 55 ErrNodeNotWritten = errors.New("treeprinter: a child was written before the node") 56 // ErrNodeAlreadyWritten is returned when the node has already been written. 57 ErrNodeAlreadyWritten = errors.New("treeprinter: node already written") 58 // ErrChildrenAlreadyWritten is returned when the children have already been written. 59 ErrChildrenAlreadyWritten = errors.New("treeprinter: children already written") 60 ) 61 62 // WriteChildren writes a children of the tree. 63 func (p *TreePrinter) WriteChildren(children ...string) error { 64 if !p.nodeWritten { 65 return ErrNodeNotWritten 66 } 67 68 if p.written { 69 return ErrChildrenAlreadyWritten 70 } 71 72 p.written = true 73 74 for i, child := range children { 75 last := i+1 == len(children) 76 r := bufio.NewReader(strings.NewReader(child)) 77 78 var first = true 79 for { 80 line, _, err := r.ReadLine() 81 if err == io.EOF { 82 break 83 } 84 85 if err != nil { 86 return err 87 } 88 89 if first && last { 90 p.buf.WriteString(" └─ ") 91 } else if first { 92 p.buf.WriteString(" ├─ ") 93 } else if !last { 94 p.buf.WriteString(" │ ") 95 } else { 96 p.buf.WriteString(" ") 97 } 98 99 p.buf.Write(line) 100 p.buf.WriteRune('\n') 101 first = false 102 } 103 } 104 105 return nil 106 } 107 108 // String returns the output of the printed tree. 109 func (p *TreePrinter) String() string { 110 return p.buf.String() 111 }