| 2 | 2 |
import (
|
| 3 | 3 |
"bytes"
|
| 4 | 4 |
"context"
|
| 5 | |
"fmt"
|
| 6 | 5 |
"io"
|
| 7 | |
"runtime/debug"
|
| 8 | 6 |
"strings"
|
| 9 | 7 |
"sync"
|
| 10 | 8 |
"time"
|
|
| 26 | 24 |
cancel func()
|
| 27 | 25 |
}
|
| 28 | 26 |
|
| 29 | |
type extenderFunc func(rows []io.Reader, stat decor.Statistics) []io.Reader
|
|
27 |
type extenderFunc func([]io.Reader, decor.Statistics) ([]io.Reader, error)
|
| 30 | 28 |
|
| 31 | 29 |
// bState is actual bar's state.
|
| 32 | 30 |
type bState struct {
|
|
| 62 | 60 |
}
|
| 63 | 61 |
|
| 64 | 62 |
type renderFrame struct {
|
| 65 | |
rows []io.Reader
|
| 66 | |
recovered bool
|
| 67 | |
shutdown int
|
|
63 |
rows []io.Reader
|
|
64 |
shutdown int
|
|
65 |
err error
|
| 68 | 66 |
}
|
| 69 | 67 |
|
| 70 | 68 |
func newBar(container *Progress, bs *bState) *Bar {
|
|
| 377 | 375 |
fn := func(s *bState) {
|
| 378 | 376 |
var rows []io.Reader
|
| 379 | 377 |
stat := newStatistics(tw, s)
|
| 380 | |
defer func() {
|
| 381 | |
// recovering if user defined decorator panics for example
|
| 382 | |
if p := recover(); p != nil {
|
| 383 | |
go func() {
|
| 384 | |
_, _ = fmt.Fprintln(b.container, p)
|
| 385 | |
}()
|
| 386 | |
if out := s.debugOut; out != nil {
|
| 387 | |
for _, fn := range []func() (int, error){
|
| 388 | |
func() (int, error) {
|
| 389 | |
return fmt.Fprintln(out, p)
|
| 390 | |
},
|
| 391 | |
func() (int, error) {
|
| 392 | |
return out.Write(debug.Stack())
|
| 393 | |
},
|
| 394 | |
} {
|
| 395 | |
if _, err := fn(); err != nil {
|
| 396 | |
panic(err)
|
| 397 | |
}
|
| 398 | |
}
|
| 399 | |
}
|
| 400 | |
s.aborted = !s.completed
|
| 401 | |
s.recovered = true
|
| 402 | |
}
|
| 403 | |
frame := &renderFrame{
|
| 404 | |
rows: rows,
|
| 405 | |
recovered: s.recovered,
|
| 406 | |
}
|
| 407 | |
if !done && (s.completed || s.aborted) {
|
| 408 | |
b.cancel()
|
| 409 | |
frame.shutdown++
|
| 410 | |
}
|
| 411 | |
b.frameCh <- frame
|
| 412 | |
}()
|
| 413 | |
rows = append(rows, s.draw(stat))
|
|
378 |
r, err := s.draw(stat)
|
|
379 |
if err != nil {
|
|
380 |
b.frameCh <- &renderFrame{err: err}
|
|
381 |
return
|
|
382 |
}
|
|
383 |
rows = append(rows, r)
|
| 414 | 384 |
if s.extender != nil {
|
| 415 | |
rows = s.extender(rows, stat)
|
| 416 | |
}
|
|
385 |
rows, err = s.extender(rows, stat)
|
|
386 |
if err != nil {
|
|
387 |
b.frameCh <- &renderFrame{err: err}
|
|
388 |
return
|
|
389 |
}
|
|
390 |
}
|
|
391 |
frame := &renderFrame{rows: rows}
|
|
392 |
if !done && (s.completed || s.aborted) {
|
|
393 |
frame.shutdown++
|
|
394 |
b.cancel()
|
|
395 |
}
|
|
396 |
b.frameCh <- frame
|
| 417 | 397 |
}
|
| 418 | 398 |
select {
|
| 419 | 399 |
case b.operateState <- fn:
|
|
| 465 | 445 |
}
|
| 466 | 446 |
}
|
| 467 | 447 |
|
| 468 | |
func (s *bState) draw(stat decor.Statistics) io.Reader {
|
|
448 |
func (s *bState) draw(stat decor.Statistics) (io.Reader, error) {
|
| 469 | 449 |
r, err := s.drawImpl(stat)
|
| 470 | 450 |
if err != nil {
|
| 471 | 451 |
for _, b := range s.buffers {
|
| 472 | 452 |
b.Reset()
|
| 473 | 453 |
}
|
| 474 | |
panic(err)
|
| 475 | |
}
|
| 476 | |
return io.MultiReader(r, strings.NewReader("\n"))
|
|
454 |
return nil, err
|
|
455 |
}
|
|
456 |
return io.MultiReader(r, strings.NewReader("\n")), nil
|
| 477 | 457 |
}
|
| 478 | 458 |
|
| 479 | 459 |
func (s *bState) drawImpl(stat decor.Statistics) (r io.Reader, err error) {
|