...
1 package list
2
3 import (
4 "strings"
5 "unicode/utf8"
6 )
7
8
9
10
11
12
13
14
15
16
17
18 func (l *List) Render() string {
19 l.initForRender()
20
21 var out strings.Builder
22 out.Grow(l.approxSize)
23 for idx, item := range l.items {
24 hint := renderHint{
25 isTopItem: bool(idx == 0),
26 isFirstItem: bool(idx == 0 || item.Level > l.items[idx-1].Level),
27 isLastItem: !l.hasMoreItemsInLevel(item.Level, idx),
28 isBottomItem: bool(idx == len(l.items)-1),
29 }
30 if hint.isFirstItem && hint.isLastItem {
31 hint.isOnlyItem = true
32 }
33 l.renderItem(&out, idx, item, hint)
34 }
35 return l.render(&out)
36 }
37
38 func (l *List) renderItem(out *strings.Builder, idx int, item *listItem, hint renderHint) {
39
40 if idx > 0 {
41 out.WriteRune('\n')
42 }
43
44
45 itemStr := l.style.Format.Apply(item.Text)
46
47
48 if strings.Contains(itemStr, "\n") && l.style.CharNewline != "\n" {
49 itemStr = strings.Replace(itemStr, "\n", l.style.CharNewline, -1)
50 }
51
52
53 for lineIdx, lineStr := range strings.Split(itemStr, "\n") {
54 if lineIdx > 0 {
55 out.WriteRune('\n')
56 }
57
58
59 l.renderItemBulletPrefix(out, idx, item.Level, lineIdx, hint)
60 l.renderItemBullet(out, lineIdx, hint)
61
62
63 out.WriteString(lineStr)
64 }
65 }
66
67 func (l *List) renderItemBullet(out *strings.Builder, lineIdx int, hint renderHint) {
68 if lineIdx > 0 {
69
70 if hint.isLastItem {
71 out.WriteString(strings.Repeat(" ", utf8.RuneCountInString(l.style.CharItemVertical)))
72 } else {
73 out.WriteString(l.style.CharItemVertical)
74 }
75 } else {
76 l.renderItemBulletSingleLine(out, lineIdx, hint)
77 }
78 }
79
80 func (l *List) renderItemBulletSingleLine(out *strings.Builder, lineIdx int, hint renderHint) {
81
82 if hint.isOnlyItem {
83 if hint.isTopItem {
84 out.WriteString(l.style.CharItemSingle)
85 } else {
86 out.WriteString(l.style.CharItemBottom)
87 }
88 } else if hint.isTopItem {
89 out.WriteString(l.style.CharItemTop)
90 } else if hint.isFirstItem {
91 out.WriteString(l.style.CharItemFirst)
92 } else if hint.isBottomItem || hint.isLastItem {
93 out.WriteString(l.style.CharItemBottom)
94 } else {
95 out.WriteString(l.style.CharItemMiddle)
96 }
97 out.WriteRune(' ')
98 }
99
100 func (l *List) renderItemBulletPrefix(out *strings.Builder, itemIdx int, itemLevel int, lineIdx int, hint renderHint) {
101
102 if l.style.LinePrefix != "" {
103 out.WriteString(l.style.LinePrefix)
104 }
105
106
107 for levelIdx := 0; levelIdx < itemLevel; levelIdx++ {
108 if l.hasMoreItemsInLevel(levelIdx, itemIdx) {
109 out.WriteString(l.style.CharItemVertical)
110 } else {
111 out.WriteString(strings.Repeat(" ", utf8.RuneCountInString(l.style.CharItemVertical)))
112 }
113 }
114 }
115
View as plain text