| 60 | 60 |
recoveredPanic interface{}
|
| 61 | 61 |
}
|
| 62 | 62 |
|
|
63 |
type extFunc func(in io.Reader, tw int, st *decor.Statistics) (out io.Reader, lines int)
|
|
64 |
|
| 63 | 65 |
type bState struct {
|
| 64 | 66 |
filler Filler
|
| 65 | |
extender Filler
|
| 66 | 67 |
id int
|
| 67 | 68 |
width int
|
| 68 | 69 |
total int64
|
|
| 70 | 71 |
trimSpace bool
|
| 71 | 72 |
toComplete bool
|
| 72 | 73 |
completeFlushed bool
|
| 73 | |
noBufBOnComplete bool
|
| 74 | 74 |
noPop bool
|
| 75 | 75 |
aDecorators []decor.Decorator
|
| 76 | 76 |
pDecorators []decor.Decorator
|
|
| 79 | 79 |
shutdownListeners []decor.ShutdownListener
|
| 80 | 80 |
averageAdjusters []decor.AverageAdjuster
|
| 81 | 81 |
bufP, bufB, bufA *bytes.Buffer
|
| 82 | |
bufE *bytes.Buffer
|
|
82 |
extender extFunc
|
| 83 | 83 |
|
| 84 | 84 |
// priority overrides *Bar's priority, if set
|
| 85 | 85 |
priority int
|
|
| 92 | 92 |
}
|
| 93 | 93 |
|
| 94 | 94 |
func newBar(container *Progress, bs *bState) *Bar {
|
| 95 | |
|
| 96 | |
bs.bufP = bytes.NewBuffer(make([]byte, 0, bs.width))
|
| 97 | |
bs.bufB = bytes.NewBuffer(make([]byte, 0, bs.width))
|
| 98 | |
bs.bufA = bytes.NewBuffer(make([]byte, 0, bs.width))
|
| 99 | |
if bs.extender != nil {
|
| 100 | |
bs.bufE = bytes.NewBuffer(make([]byte, 0, bs.width))
|
| 101 | |
}
|
| 102 | |
|
| 103 | 95 |
logPrefix := fmt.Sprintf("%sbar#%02d ", container.dlogger.Prefix(), bs.id)
|
| 104 | 96 |
ctx, cancel := context.WithCancel(container.ctx)
|
|
97 |
|
| 105 | 98 |
bar := &Bar{
|
| 106 | 99 |
container: container,
|
| 107 | 100 |
priority: bs.priority,
|
|
| 298 | 291 |
return <-b.completed
|
| 299 | 292 |
case <-b.done:
|
| 300 | 293 |
return true
|
| 301 | |
}
|
| 302 | |
}
|
| 303 | |
|
| 304 | |
func (b *Bar) wSyncTable() [][]chan int {
|
| 305 | |
select {
|
| 306 | |
case b.operateState <- func(s *bState) { b.syncTableCh <- s.wSyncTable() }:
|
| 307 | |
return <-b.syncTableCh
|
| 308 | |
case <-b.done:
|
| 309 | |
return b.cacheState.wSyncTable()
|
| 310 | 294 |
}
|
| 311 | 295 |
}
|
| 312 | 296 |
|
|
| 346 | 330 |
}
|
| 347 | 331 |
}()
|
| 348 | 332 |
|
| 349 | |
frame := s.draw(tw)
|
| 350 | |
|
| 351 | |
if s.extender != nil {
|
| 352 | |
s.extender.Fill(s.bufE, tw, newStatistics(s))
|
| 353 | |
b.extendedLines = countLines(s.bufE.Bytes())
|
| 354 | |
frame = io.MultiReader(frame, s.bufE)
|
| 355 | |
}
|
|
333 |
st := newStatistics(s)
|
|
334 |
frame := s.draw(tw, st)
|
|
335 |
frame, b.extendedLines = s.extender(frame, tw, st)
|
| 356 | 336 |
|
| 357 | 337 |
b.toShutdown = s.toComplete && !s.completeFlushed
|
| 358 | 338 |
s.completeFlushed = s.toComplete
|
| 359 | |
|
| 360 | 339 |
b.frameCh <- frame
|
| 361 | 340 |
}:
|
| 362 | 341 |
case <-b.done:
|
| 363 | 342 |
s := b.cacheState
|
| 364 | |
frame := s.draw(tw)
|
| 365 | |
if s.extender != nil {
|
| 366 | |
s.extender.Fill(s.bufE, tw, newStatistics(s))
|
| 367 | |
b.extendedLines = countLines(s.bufE.Bytes())
|
| 368 | |
frame = io.MultiReader(frame, s.bufE)
|
| 369 | |
}
|
|
343 |
st := newStatistics(s)
|
|
344 |
frame := s.draw(tw, st)
|
|
345 |
frame, b.extendedLines = s.extender(frame, tw, st)
|
| 370 | 346 |
b.frameCh <- frame
|
| 371 | 347 |
}
|
| 372 | 348 |
}
|
|
| 375 | 351 |
return strings.NewReader(fmt.Sprintf(fmt.Sprintf("%%.%dv\n", termWidth), b.recoveredPanic))
|
| 376 | 352 |
}
|
| 377 | 353 |
|
| 378 | |
func (s *bState) draw(termWidth int) io.Reader {
|
| 379 | |
|
| 380 | |
stat := newStatistics(s)
|
| 381 | |
|
|
354 |
func (b *Bar) subscribeDecorators() {
|
|
355 |
var amountReceivers []decor.AmountReceiver
|
|
356 |
var shutdownListeners []decor.ShutdownListener
|
|
357 |
var averageAdjusters []decor.AverageAdjuster
|
|
358 |
b.TraverseDecorators(func(d decor.Decorator) {
|
|
359 |
if d, ok := d.(decor.AmountReceiver); ok {
|
|
360 |
amountReceivers = append(amountReceivers, d)
|
|
361 |
}
|
|
362 |
if d, ok := d.(decor.ShutdownListener); ok {
|
|
363 |
shutdownListeners = append(shutdownListeners, d)
|
|
364 |
}
|
|
365 |
if d, ok := d.(decor.AverageAdjuster); ok {
|
|
366 |
averageAdjusters = append(averageAdjusters, d)
|
|
367 |
}
|
|
368 |
})
|
|
369 |
b.operateState <- func(s *bState) {
|
|
370 |
s.amountReceivers = amountReceivers
|
|
371 |
s.shutdownListeners = shutdownListeners
|
|
372 |
s.averageAdjusters = averageAdjusters
|
|
373 |
}
|
|
374 |
}
|
|
375 |
|
|
376 |
func (b *Bar) refreshNowTillShutdown() {
|
|
377 |
for {
|
|
378 |
select {
|
|
379 |
case b.container.forceRefresh <- time.Now():
|
|
380 |
case <-b.done:
|
|
381 |
return
|
|
382 |
}
|
|
383 |
}
|
|
384 |
}
|
|
385 |
|
|
386 |
func (b *Bar) wSyncTable() [][]chan int {
|
|
387 |
select {
|
|
388 |
case b.operateState <- func(s *bState) { b.syncTableCh <- s.wSyncTable() }:
|
|
389 |
return <-b.syncTableCh
|
|
390 |
case <-b.done:
|
|
391 |
return b.cacheState.wSyncTable()
|
|
392 |
}
|
|
393 |
}
|
|
394 |
|
|
395 |
func (s *bState) draw(termWidth int, stat *decor.Statistics) io.Reader {
|
| 382 | 396 |
for _, d := range s.pDecorators {
|
| 383 | 397 |
s.bufP.WriteString(d.Decor(stat))
|
| 384 | 398 |
}
|
|
| 388 | 402 |
}
|
| 389 | 403 |
|
| 390 | 404 |
s.bufA.WriteByte('\n')
|
| 391 | |
if s.noBufBOnComplete && s.completeFlushed {
|
| 392 | |
return io.MultiReader(s.bufP, s.bufA)
|
| 393 | |
}
|
| 394 | 405 |
|
| 395 | 406 |
prependCount := utf8.RuneCount(s.bufP.Bytes())
|
| 396 | 407 |
appendCount := utf8.RuneCount(s.bufA.Bytes()) - 1
|
|
| 433 | 444 |
return table
|
| 434 | 445 |
}
|
| 435 | 446 |
|
| 436 | |
func (b *Bar) refreshNowTillShutdown() {
|
| 437 | |
for {
|
| 438 | |
select {
|
| 439 | |
case b.container.forceRefresh <- time.Now():
|
| 440 | |
case <-b.done:
|
| 441 | |
return
|
| 442 | |
}
|
| 443 | |
}
|
| 444 | |
}
|
| 445 | |
|
| 446 | 447 |
func newStatistics(s *bState) *decor.Statistics {
|
| 447 | 448 |
return &decor.Statistics{
|
| 448 | 449 |
ID: s.id,
|
|
| 451 | 452 |
Current: s.current,
|
| 452 | 453 |
}
|
| 453 | 454 |
}
|
| 454 | |
|
| 455 | |
func countLines(b []byte) int {
|
| 456 | |
return bytes.Count(b, []byte("\n"))
|
| 457 | |
}
|