...
1 package list
2
3 import (
4 "fmt"
5 "io"
6 "strings"
7 "unicode/utf8"
8 )
9
10 const (
11
12
13 DefaultHTMLCSSClass = "go-pretty-table"
14 )
15
16
17 type listItem struct {
18 Level int
19 Text string
20 }
21
22
23 type List struct {
24
25 approxSize int
26
27 htmlCSSClass string
28
29 items []*listItem
30
31 level int
32
33 outputMirror io.Writer
34
35 style *Style
36 }
37
38
39 func (l *List) AppendItem(item interface{}) {
40 l.items = append(l.items, l.analyzeAndStringify(item))
41 }
42
43
44 func (l *List) AppendItems(items []interface{}) {
45 for _, item := range items {
46 l.AppendItem(item)
47 }
48 }
49
50
51 func (l *List) Indent() {
52 if len(l.items) == 0 {
53
54 } else if l.level > l.items[len(l.items)-1].Level {
55
56 } else {
57 l.level++
58 }
59 }
60
61
62 func (l *List) Length() int {
63 return len(l.items)
64 }
65
66
67 func (l *List) Reset() {
68 l.approxSize = 0
69 l.items = make([]*listItem, 0)
70 l.level = 0
71 l.style = nil
72 }
73
74
75
76
77
78 func (l *List) SetHTMLCSSClass(cssClass string) {
79 l.htmlCSSClass = cssClass
80 }
81
82
83
84 func (l *List) SetOutputMirror(mirror io.Writer) {
85 l.outputMirror = mirror
86 }
87
88
89 func (l *List) SetStyle(style Style) {
90 l.style = &style
91 }
92
93
94 func (l *List) Style() *Style {
95 if l.style == nil {
96 tempStyle := StyleDefault
97 l.style = &tempStyle
98 }
99 return l.style
100 }
101
102 func (l *List) analyzeAndStringify(item interface{}) *listItem {
103 itemStr := fmt.Sprint(item)
104 if strings.Contains(itemStr, "\t") {
105 itemStr = strings.Replace(itemStr, "\t", " ", -1)
106 }
107 if strings.Contains(itemStr, "\r") {
108 itemStr = strings.Replace(itemStr, "\r", "", -1)
109 }
110 return &listItem{
111 Level: l.level,
112 Text: itemStr,
113 }
114 }
115
116
117 func (l *List) UnIndent() {
118 if l.level > 0 {
119 l.level--
120 }
121 }
122
123 func (l *List) UnIndentAll() {
124 l.level = 0
125 }
126
127 func (l *List) initForRender() {
128
129 l.Style()
130
131
132 l.approxSize = 0
133 for _, item := range l.items {
134
135
136 l.approxSize += utf8.RuneCountInString(l.style.LinePrefix)
137 if item.Level > 0 {
138 l.approxSize += utf8.RuneCountInString(l.style.CharItemVertical) * item.Level
139 }
140 l.approxSize += utf8.RuneCountInString(l.style.CharItemVertical)
141 l.approxSize += utf8.RuneCountInString(item.Text)
142 l.approxSize += utf8.RuneCountInString(l.style.CharNewline)
143 }
144
145
146 if l.htmlCSSClass == "" {
147 l.htmlCSSClass = DefaultHTMLCSSClass
148 }
149 }
150
151 func (l *List) hasMoreItemsInLevel(levelIdx int, fromItemIdx int) bool {
152 for idx := fromItemIdx + 1; idx >= 0 && idx < len(l.items); idx++ {
153 if l.items[idx].Level < levelIdx {
154 return false
155 } else if l.items[idx].Level == levelIdx {
156 return true
157 }
158 }
159 return false
160 }
161
162 func (l *List) render(out *strings.Builder) string {
163 outStr := out.String()
164 if l.outputMirror != nil && len(outStr) > 0 {
165 l.outputMirror.Write([]byte(outStr))
166 l.outputMirror.Write([]byte("\n"))
167 }
168 return outStr
169 }
170
171
172 type renderHint struct {
173 isTopItem bool
174 isFirstItem bool
175 isOnlyItem bool
176 isLastItem bool
177 isBottomItem bool
178 }
179
View as plain text