| 17 | 17 |
// Bar represents a progress bar.
|
| 18 | 18 |
type Bar struct {
|
| 19 | 19 |
index int // used by heap
|
| 20 | |
toShutdown bool
|
| 21 | 20 |
hasEwmaDecorators bool
|
| 22 | 21 |
frameCh chan *frame
|
| 23 | 22 |
operateState chan func(*bState)
|
|
| 62 | 61 |
}
|
| 63 | 62 |
|
| 64 | 63 |
type frame struct {
|
| 65 | |
reader io.Reader
|
| 66 | |
lines int
|
|
64 |
reader io.Reader
|
|
65 |
lines int
|
|
66 |
shutdown bool
|
|
67 |
abort bool
|
| 67 | 68 |
}
|
| 68 | 69 |
|
| 69 | 70 |
func newBar(container *Progress, bs *bState) (*Bar, func()) {
|
|
| 274 | 275 |
// if bar is already in complete state. If drop is true bar will be
|
| 275 | 276 |
// removed as well.
|
| 276 | 277 |
func (b *Bar) Abort(drop bool) {
|
| 277 | |
done := make(chan struct{})
|
| 278 | |
select {
|
| 279 | |
case b.operateState <- func(s *bState) {
|
| 280 | |
if s.completed {
|
| 281 | |
close(done)
|
|
278 |
select {
|
|
279 |
case b.operateState <- func(s *bState) {
|
|
280 |
if s.completed || s.aborted {
|
| 282 | 281 |
return
|
| 283 | 282 |
}
|
| 284 | 283 |
s.aborted = true
|
| 285 | |
b.cancel()
|
| 286 | |
// container must be run during lifetime of this inner goroutine
|
| 287 | |
// we control this by done channel declared above
|
| 288 | |
go func() {
|
| 289 | |
if drop {
|
| 290 | |
b.container.dropBar(b)
|
| 291 | |
} else {
|
| 292 | |
var anyOtherUncompleted bool
|
| 293 | |
b.container.traverseBars(func(bar *Bar) bool {
|
| 294 | |
anyOtherUncompleted = b != bar && !bar.Completed()
|
| 295 | |
return !anyOtherUncompleted
|
| 296 | |
})
|
| 297 | |
if !anyOtherUncompleted {
|
| 298 | |
b.container.refreshCh <- time.Now()
|
| 299 | |
}
|
| 300 | |
}
|
| 301 | |
close(done) // release hold of Abort
|
| 302 | |
}()
|
| 303 | |
}:
|
| 304 | |
// guarantee: container is alive during lifetime of this hold
|
| 305 | |
<-done
|
|
284 |
s.dropOnComplete = drop
|
|
285 |
go b.forceRefreshIfLastUncompleted()
|
|
286 |
}:
|
|
287 |
<-b.done
|
| 306 | 288 |
case <-b.done:
|
| 307 | 289 |
}
|
| 308 | 290 |
}
|
|
| 321 | 303 |
func (b *Bar) render(tw int) {
|
| 322 | 304 |
select {
|
| 323 | 305 |
case b.operateState <- func(s *bState) {
|
|
306 |
var reader io.Reader
|
|
307 |
var lines int
|
| 324 | 308 |
stat := newStatistics(tw, s)
|
| 325 | 309 |
defer func() {
|
| 326 | 310 |
// recovering if user defined decorator panics for example
|
| 327 | 311 |
if p := recover(); p != nil {
|
| 328 | |
if b.recoveredPanic == nil {
|
| 329 | |
if s.debugOut != nil {
|
| 330 | |
fmt.Fprintln(s.debugOut, p)
|
| 331 | |
_, _ = s.debugOut.Write(debug.Stack())
|
| 332 | |
}
|
| 333 | |
s.extender = makePanicExtender(p)
|
| 334 | |
b.toShutdown = !b.toShutdown
|
| 335 | |
b.recoveredPanic = p
|
|
312 |
if s.debugOut != nil {
|
|
313 |
fmt.Fprintln(s.debugOut, p)
|
|
314 |
_, _ = s.debugOut.Write(debug.Stack())
|
| 336 | 315 |
}
|
| 337 | |
reader, lines := s.extender(nil, s.reqWidth, stat)
|
| 338 | |
b.frameCh <- &frame{reader, lines + 1}
|
| 339 | |
}
|
| 340 | |
s.completeFlushed = s.completed
|
|
316 |
s.aborted = true
|
|
317 |
s.extender = makePanicExtender(p)
|
|
318 |
reader, lines = s.extender(nil, s.reqWidth, stat)
|
|
319 |
b.recoveredPanic = p
|
|
320 |
}
|
|
321 |
b.frameCh <- &frame{
|
|
322 |
reader: reader,
|
|
323 |
lines: lines + 1,
|
|
324 |
shutdown: s.completed && !s.completeFlushed,
|
|
325 |
abort: s.aborted && !s.completeFlushed,
|
|
326 |
}
|
|
327 |
s.completeFlushed = s.completed || s.aborted
|
| 341 | 328 |
}()
|
| 342 | |
reader, lines := s.extender(s.draw(stat), s.reqWidth, stat)
|
| 343 | |
b.toShutdown = s.completed && !s.completeFlushed
|
| 344 | |
b.frameCh <- &frame{reader, lines + 1}
|
| 345 | |
}:
|
| 346 | |
case <-b.done:
|
| 347 | |
s := b.bs
|
| 348 | |
stat := newStatistics(tw, s)
|
| 349 | |
var r io.Reader
|
| 350 | 329 |
if b.recoveredPanic == nil {
|
| 351 | |
r = s.draw(stat)
|
| 352 | |
}
|
| 353 | |
reader, lines := s.extender(r, s.reqWidth, stat)
|
| 354 | |
b.frameCh <- &frame{reader, lines + 1}
|
|
330 |
reader = s.draw(stat)
|
|
331 |
}
|
|
332 |
reader, lines = s.extender(reader, s.reqWidth, stat)
|
|
333 |
}:
|
|
334 |
case <-b.done:
|
|
335 |
var reader io.Reader
|
|
336 |
var lines int
|
|
337 |
stat, s := newStatistics(tw, b.bs), b.bs
|
|
338 |
if b.recoveredPanic == nil {
|
|
339 |
reader = s.draw(stat)
|
|
340 |
}
|
|
341 |
reader, lines = s.extender(reader, s.reqWidth, stat)
|
|
342 |
b.frameCh <- &frame{
|
|
343 |
reader: reader,
|
|
344 |
lines: lines + 1,
|
|
345 |
}
|
| 355 | 346 |
}
|
| 356 | 347 |
}
|
| 357 | 348 |
|
|
| 521 | 512 |
Total: s.total,
|
| 522 | 513 |
Current: s.current,
|
| 523 | 514 |
Refill: s.refill,
|
| 524 | |
Completed: s.completeFlushed,
|
|
515 |
Completed: s.completeFlushed && !s.aborted,
|
| 525 | 516 |
Aborted: s.aborted,
|
| 526 | 517 |
}
|
| 527 | 518 |
}
|