...
1 package progress
2
3 import (
4 "strings"
5 "time"
6
7 "github.com/jedib0t/go-pretty/v6/text"
8 )
9
10
11
12 type IndeterminateIndicator struct {
13 Position int
14 Text string
15 }
16
17
18
19
20
21
22
23
24 type IndeterminateIndicatorGenerator func(maxLen int) IndeterminateIndicator
25
26
27
28 func IndeterminateIndicatorDominoes(duration time.Duration) IndeterminateIndicatorGenerator {
29 return timedIndeterminateIndicatorGenerator(indeterminateIndicatorDominoes(), duration)
30 }
31
32
33
34
35 func IndeterminateIndicatorMovingBackAndForth(indicator string, duration time.Duration) IndeterminateIndicatorGenerator {
36 return timedIndeterminateIndicatorGenerator(indeterminateIndicatorMovingBackAndForth(indicator), duration)
37 }
38
39
40
41
42 func IndeterminateIndicatorMovingLeftToRight(indicator string, duration time.Duration) IndeterminateIndicatorGenerator {
43 return timedIndeterminateIndicatorGenerator(indeterminateIndicatorMovingLeftToRight(indicator), duration)
44 }
45
46
47
48
49 func IndeterminateIndicatorMovingRightToLeft(indicator string, duration time.Duration) IndeterminateIndicatorGenerator {
50 return timedIndeterminateIndicatorGenerator(indeterminateIndicatorMovingRightToLeft(indicator), duration)
51 }
52
53
54
55 func IndeterminateIndicatorPacMan(duration time.Duration) IndeterminateIndicatorGenerator {
56 return timedIndeterminateIndicatorGenerator(indeterminateIndicatorPacMan(), duration)
57 }
58
59 func indeterminateIndicatorDominoes() IndeterminateIndicatorGenerator {
60 direction := 1
61 nextPosition := 0
62
63 out := strings.Builder{}
64 generateIndicator := func(currentPosition int, maxLen int) string {
65 out.Reset()
66 out.WriteString(strings.Repeat("/", currentPosition))
67 out.WriteString(strings.Repeat("\\", maxLen-currentPosition))
68 return out.String()
69 }
70
71 return func(maxLen int) IndeterminateIndicator {
72 currentPosition := nextPosition
73
74 if currentPosition == 0 {
75 direction = 1
76 } else if currentPosition == maxLen {
77 direction = -1
78 }
79 nextPosition += direction
80
81 return IndeterminateIndicator{
82 Position: 0,
83 Text: generateIndicator(currentPosition, maxLen),
84 }
85 }
86 }
87
88 func indeterminateIndicatorMovingBackAndForth(indicator string) IndeterminateIndicatorGenerator {
89 direction := 1
90 nextPosition := 0
91
92 return func(maxLen int) IndeterminateIndicator {
93 currentPosition := nextPosition
94
95 if currentPosition == 0 {
96 direction = 1
97 } else if currentPosition+text.RuneWidthWithoutEscSequences(indicator) == maxLen {
98 direction = -1
99 }
100 nextPosition += direction
101
102 return IndeterminateIndicator{
103 Position: currentPosition,
104 Text: indicator,
105 }
106 }
107 }
108
109 func indeterminateIndicatorMovingLeftToRight(indicator string) IndeterminateIndicatorGenerator {
110 nextPosition := 0
111
112 return func(maxLen int) IndeterminateIndicator {
113 currentPosition := nextPosition
114
115 nextPosition++
116 if nextPosition+text.RuneWidthWithoutEscSequences(indicator) > maxLen {
117 nextPosition = 0
118 }
119
120 return IndeterminateIndicator{
121 Position: currentPosition,
122 Text: indicator,
123 }
124 }
125 }
126
127 func indeterminateIndicatorMovingRightToLeft(indicator string) IndeterminateIndicatorGenerator {
128 nextPosition := -1
129
130 return func(maxLen int) IndeterminateIndicator {
131 if nextPosition == -1 {
132 nextPosition = maxLen - text.RuneWidthWithoutEscSequences(indicator)
133 }
134 currentPosition := nextPosition
135 nextPosition--
136
137 return IndeterminateIndicator{
138 Position: currentPosition,
139 Text: indicator,
140 }
141 }
142 }
143
144 func indeterminateIndicatorPacMan() IndeterminateIndicatorGenerator {
145 pacManMovingRight, pacManMovingLeft := "ᗧ", "ᗤ"
146 direction := 1
147 indicator := pacManMovingRight
148 nextPosition := 0
149
150 out := strings.Builder{}
151 generateIndicator := func(currentPosition int, maxLen int) string {
152 out.Reset()
153 if currentPosition > 0 {
154 out.WriteString(strings.Repeat(" ", currentPosition))
155 }
156 out.WriteString(indicator)
157 out.WriteString(strings.Repeat(" ", maxLen-currentPosition-1))
158 return out.String()
159 }
160
161 return func(maxLen int) IndeterminateIndicator {
162 currentPosition := nextPosition
163 currentText := generateIndicator(currentPosition, maxLen)
164
165 if currentPosition == 0 {
166 direction = 1
167 indicator = pacManMovingRight
168 } else if currentPosition+text.RuneWidthWithoutEscSequences(indicator) == maxLen {
169 direction = -1
170 indicator = pacManMovingLeft
171 }
172 nextPosition += direction
173
174 return IndeterminateIndicator{
175 Position: 0,
176 Text: currentText,
177 }
178 }
179 }
180
181
182
183 func timedIndeterminateIndicatorGenerator(indicatorGenerator IndeterminateIndicatorGenerator, duration time.Duration) IndeterminateIndicatorGenerator {
184 var indeterminateIndicator *IndeterminateIndicator
185 lastRenderTime := time.Now()
186
187 return func(maxLen int) IndeterminateIndicator {
188 currRenderTime := time.Now()
189 if indeterminateIndicator == nil || duration == 0 || currRenderTime.Sub(lastRenderTime) > duration {
190 tmpIndeterminateIndicator := indicatorGenerator(maxLen)
191 indeterminateIndicator = &tmpIndeterminateIndicator
192 lastRenderTime = currRenderTime
193 }
194
195 return *indeterminateIndicator
196 }
197 }
198
View as plain text