| 31 | 31 |
priority int
|
| 32 | 32 |
index int
|
| 33 | 33 |
|
| 34 | |
// pointer to running bar, which this bar should replace
|
| 35 | |
runningBar *Bar
|
| 36 | |
|
| 37 | |
// completed is set from master Progress goroutine only
|
| 38 | |
completed bool
|
| 39 | |
|
| 40 | |
removeOnComplete bool
|
| 41 | |
|
| 42 | |
operateState chan func(*bState)
|
|
34 |
runningBar *Bar
|
|
35 |
cacheState *bState
|
|
36 |
operateState chan func(*bState)
|
|
37 |
frameReaderCh chan io.Reader
|
|
38 |
|
| 43 | 39 |
// done is closed by Bar's goroutine, after cacheState is written
|
| 44 | 40 |
done chan struct{}
|
| 45 | 41 |
// shutdown is closed from master Progress goroutine only
|
| 46 | 42 |
shutdown chan struct{}
|
| 47 | |
|
| 48 | |
cacheState *bState
|
| 49 | 43 |
}
|
| 50 | 44 |
|
| 51 | 45 |
type (
|
|
| 62 | 56 |
trimRightSpace bool
|
| 63 | 57 |
toComplete bool
|
| 64 | 58 |
dynamic bool
|
|
59 |
removeOnComplete bool
|
| 65 | 60 |
barClearOnComplete bool
|
| 66 | 61 |
completeFlushed bool
|
| 67 | 62 |
startTime time.Time
|
|
| 76 | 71 |
panicMsg string
|
| 77 | 72 |
|
| 78 | 73 |
// following options are assigned to the *Bar
|
| 79 | |
priority int
|
| 80 | |
removeOnComplete bool
|
| 81 | |
runningBar *Bar
|
|
74 |
priority int
|
|
75 |
runningBar *Bar
|
| 82 | 76 |
}
|
| 83 | 77 |
refill struct {
|
| 84 | 78 |
char rune
|
| 85 | 79 |
till int64
|
| 86 | 80 |
}
|
| 87 | |
bFrame struct {
|
| 88 | |
bar *Bar
|
| 89 | |
reader io.Reader
|
| 90 | |
toComplete bool
|
|
81 |
frameReader struct {
|
|
82 |
io.Reader
|
|
83 |
toShutdown bool
|
|
84 |
removeOnComplete bool
|
| 91 | 85 |
}
|
| 92 | 86 |
)
|
| 93 | 87 |
|
|
| 116 | 110 |
s.bufA = bytes.NewBuffer(make([]byte, 0, s.width))
|
| 117 | 111 |
|
| 118 | 112 |
b := &Bar{
|
| 119 | |
priority: s.priority,
|
| 120 | |
removeOnComplete: s.removeOnComplete,
|
| 121 | |
runningBar: s.runningBar,
|
| 122 | |
operateState: make(chan func(*bState)),
|
| 123 | |
done: make(chan struct{}),
|
| 124 | |
shutdown: make(chan struct{}),
|
|
113 |
priority: s.priority,
|
|
114 |
runningBar: s.runningBar,
|
|
115 |
operateState: make(chan func(*bState)),
|
|
116 |
frameReaderCh: make(chan io.Reader, 1),
|
|
117 |
done: make(chan struct{}),
|
|
118 |
shutdown: make(chan struct{}),
|
| 125 | 119 |
}
|
| 126 | 120 |
|
| 127 | 121 |
if b.runningBar != nil {
|
|
| 172 | 166 |
|
| 173 | 167 |
// NumOfAppenders returns current number of append decorators
|
| 174 | 168 |
func (b *Bar) NumOfAppenders() int {
|
| 175 | |
result := make(chan int, 1)
|
|
169 |
result := make(chan int)
|
| 176 | 170 |
select {
|
| 177 | 171 |
case b.operateState <- func(s *bState) { result <- len(s.aDecorators) }:
|
| 178 | 172 |
return <-result
|
|
| 183 | 177 |
|
| 184 | 178 |
// NumOfPrependers returns current number of prepend decorators
|
| 185 | 179 |
func (b *Bar) NumOfPrependers() int {
|
| 186 | |
result := make(chan int, 1)
|
|
180 |
result := make(chan int)
|
| 187 | 181 |
select {
|
| 188 | 182 |
case b.operateState <- func(s *bState) { result <- len(s.pDecorators) }:
|
| 189 | 183 |
return <-result
|
|
| 194 | 188 |
|
| 195 | 189 |
// ID returs id of the bar
|
| 196 | 190 |
func (b *Bar) ID() int {
|
| 197 | |
result := make(chan int, 1)
|
|
191 |
result := make(chan int)
|
| 198 | 192 |
select {
|
| 199 | 193 |
case b.operateState <- func(s *bState) { result <- s.id }:
|
| 200 | 194 |
return <-result
|
|
| 205 | 199 |
|
| 206 | 200 |
// Current returns bar's current number, in other words sum of all increments.
|
| 207 | 201 |
func (b *Bar) Current() int64 {
|
| 208 | |
result := make(chan int64, 1)
|
|
202 |
result := make(chan int64)
|
| 209 | 203 |
select {
|
| 210 | 204 |
case b.operateState <- func(s *bState) { result <- s.current }:
|
| 211 | 205 |
return <-result
|
|
| 216 | 210 |
|
| 217 | 211 |
// Total returns bar's total number.
|
| 218 | 212 |
func (b *Bar) Total() int64 {
|
| 219 | |
result := make(chan int64, 1)
|
|
213 |
result := make(chan int64)
|
| 220 | 214 |
select {
|
| 221 | 215 |
case b.operateState <- func(s *bState) { result <- s.total }:
|
| 222 | 216 |
return <-result
|
|
| 246 | 240 |
func (b *Bar) StartBlock() {
|
| 247 | 241 |
now := time.Now()
|
| 248 | 242 |
select {
|
| 249 | |
case b.operateState <- func(s *bState) { s.blockStartTime = now }:
|
|
243 |
case b.operateState <- func(s *bState) {
|
|
244 |
if s.current == 0 {
|
|
245 |
s.startTime = now
|
|
246 |
}
|
|
247 |
s.blockStartTime = now
|
|
248 |
}:
|
| 250 | 249 |
case <-b.done:
|
| 251 | 250 |
}
|
| 252 | 251 |
}
|
|
| 275 | 274 |
|
| 276 | 275 |
// Completed reports whether the bar is in completed state
|
| 277 | 276 |
func (b *Bar) Completed() bool {
|
| 278 | |
result := make(chan bool, 1)
|
|
277 |
result := make(chan bool)
|
| 279 | 278 |
select {
|
| 280 | 279 |
case b.operateState <- func(s *bState) { result <- s.toComplete }:
|
| 281 | 280 |
return <-result
|
|
| 303 | 302 |
}
|
| 304 | 303 |
}
|
| 305 | 304 |
|
| 306 | |
func (b *Bar) render(debugOut io.Writer, tw int, pSyncer, aSyncer *widthSyncer) <-chan *bFrame {
|
| 307 | |
ch := make(chan *bFrame, 1)
|
| 308 | |
|
| 309 | |
go func() {
|
| 310 | |
select {
|
| 311 | |
case b.operateState <- func(s *bState) {
|
| 312 | |
var r io.Reader
|
| 313 | |
defer func() {
|
| 314 | |
// recovering if external decorators panic
|
| 315 | |
if p := recover(); p != nil {
|
| 316 | |
s.panicMsg = fmt.Sprintf("panic: %v", p)
|
| 317 | |
s.pDecorators = nil
|
| 318 | |
s.aDecorators = nil
|
| 319 | |
s.toComplete = true
|
| 320 | |
// truncate panic msg to one tw line, if necessary
|
| 321 | |
r = strings.NewReader(fmt.Sprintf(fmt.Sprintf("%%.%ds\n", tw), s.panicMsg))
|
| 322 | |
fmt.Fprintf(debugOut, "%s %s bar id %02d %v\n", "[mpb]", time.Now(), s.id, s.panicMsg)
|
| 323 | |
}
|
| 324 | |
ch <- &bFrame{b, r, s.toComplete && !(s.barClearOnComplete && !s.completeFlushed)}
|
| 325 | |
s.completeFlushed = s.toComplete
|
| 326 | |
}()
|
|
305 |
func (b *Bar) render(debugOut io.Writer, tw int, pSyncer, aSyncer *widthSyncer) {
|
|
306 |
var r io.Reader
|
|
307 |
select {
|
|
308 |
case b.operateState <- func(s *bState) {
|
|
309 |
defer func() {
|
|
310 |
// recovering if external decorators panic
|
|
311 |
if p := recover(); p != nil {
|
|
312 |
s.panicMsg = fmt.Sprintf("panic: %v", p)
|
|
313 |
s.pDecorators = nil
|
|
314 |
s.aDecorators = nil
|
|
315 |
s.toComplete = true
|
|
316 |
// truncate panic msg to one tw line, if necessary
|
|
317 |
r = strings.NewReader(fmt.Sprintf(fmt.Sprintf("%%.%ds\n", tw), s.panicMsg))
|
|
318 |
fmt.Fprintf(debugOut, "%s %s bar id %02d %v\n", "[mpb]", time.Now(), s.id, s.panicMsg)
|
|
319 |
}
|
|
320 |
b.frameReaderCh <- &frameReader{
|
|
321 |
Reader: r,
|
|
322 |
toShutdown: s.toComplete && !s.completeFlushed,
|
|
323 |
removeOnComplete: s.removeOnComplete,
|
|
324 |
}
|
|
325 |
s.completeFlushed = s.toComplete
|
|
326 |
}()
|
|
327 |
r = s.draw(tw, pSyncer, aSyncer)
|
|
328 |
}:
|
|
329 |
case <-b.done:
|
|
330 |
s := b.cacheState
|
|
331 |
if s.panicMsg != "" {
|
|
332 |
r = strings.NewReader(fmt.Sprintf(fmt.Sprintf("%%.%ds\n", tw), s.panicMsg))
|
|
333 |
} else {
|
| 327 | 334 |
r = s.draw(tw, pSyncer, aSyncer)
|
| 328 | |
}:
|
| 329 | |
case <-b.done:
|
| 330 | |
s := b.cacheState
|
| 331 | |
var r io.Reader
|
| 332 | |
if s.panicMsg != "" {
|
| 333 | |
r = strings.NewReader(fmt.Sprintf(fmt.Sprintf("%%.%ds\n", tw), s.panicMsg))
|
| 334 | |
} else {
|
| 335 | |
r = s.draw(tw, pSyncer, aSyncer)
|
| 336 | |
}
|
| 337 | |
ch <- &bFrame{b, r, true}
|
| 338 | |
}
|
| 339 | |
}()
|
| 340 | |
|
| 341 | |
return ch
|
|
335 |
}
|
|
336 |
b.frameReaderCh <- &frameReader{
|
|
337 |
Reader: r,
|
|
338 |
}
|
|
339 |
}
|
| 342 | 340 |
}
|
| 343 | 341 |
|
| 344 | 342 |
func (s *bState) draw(termWidth int, pSyncer, aSyncer *widthSyncer) io.Reader {
|