add RefreshInterval method
Vladimir Bauer
9 years ago
| 8 | 8 | "github.com/gosuri/uilive" |
| 9 | 9 | ) |
| 10 | 10 | |
| 11 | // Out is the default writer to render progress bars to | |
| 12 | // var Out = os.Stdout | |
| 13 | ||
| 14 | // RefreshInterval in the default time duration to wait for refreshing the output | |
| 15 | var RefreshInterval = time.Millisecond * 10 | |
| 16 | ||
| 17 | // Progress represents the container that renders progress bars | |
| 18 | type Progress struct { | |
| 19 | // Out is the writer to render progress bars to | |
| 11 | // progress represents the container that renders progress bars | |
| 12 | type progress struct { | |
| 13 | // out is the writer to render progress bars to | |
| 20 | 14 | out io.Writer |
| 21 | 15 | |
| 22 | 16 | // Width is the width of the progress bars |
| 23 | 17 | // Width int |
| 24 | 18 | |
| 25 | // Bars is the collection of progress bars | |
| 26 | // Bars []*Bar | |
| 19 | lw *uilive.Writer | |
| 27 | 20 | |
| 28 | // RefreshInterval in the time duration to wait for refreshing the output | |
| 29 | // RefreshInterval time.Duration | |
| 21 | // new Bars can be added over this channel | |
| 22 | bars chan *Bar | |
| 30 | 23 | |
| 31 | lw *uilive.Writer | |
| 32 | // stopChan chan struct{} | |
| 33 | // mtx *sync.RWMutex | |
| 34 | bars chan *Bar | |
| 35 | ticker *time.Ticker | |
| 24 | // new refresh interval to be send over this channel | |
| 25 | interval chan time.Duration | |
| 36 | 26 | } |
| 37 | 27 | |
| 38 | 28 | // New returns a new progress bar with defaults |
| 39 | func New() *Progress { | |
| 40 | p := &Progress{ | |
| 41 | out: os.Stdout, | |
| 42 | lw: uilive.New(), | |
| 43 | bars: make(chan *Bar), | |
| 44 | ticker: time.NewTicker(RefreshInterval), | |
| 29 | func New() *progress { | |
| 30 | p := &progress{ | |
| 31 | out: os.Stdout, | |
| 32 | lw: uilive.New(), | |
| 33 | bars: make(chan *Bar), | |
| 34 | interval: make(chan time.Duration), | |
| 45 | 35 | } |
| 46 | 36 | go p.server() |
| 47 | 37 | return p |
| 48 | 38 | } |
| 49 | 39 | |
| 50 | // SetOut is the writer to render progress bars to | |
| 51 | func (p *Progress) SetOut(w io.Writer) *Progress { | |
| 40 | // RefreshInterval overrides default interval value 30 ms | |
| 41 | func (p *progress) RefreshInterval(d time.Duration) *progress { | |
| 42 | p.interval <- d | |
| 43 | return p | |
| 44 | } | |
| 45 | ||
| 46 | // SetOut sets underlying writer of progress | |
| 47 | // default is os.Stdout | |
| 48 | func (p *progress) SetOut(w io.Writer) *progress { | |
| 52 | 49 | p.out = w |
| 53 | 50 | return p |
| 54 | 51 | } |
| 55 | 52 | |
| 56 | 53 | // AddBar creates a new progress bar and adds to the container |
| 57 | func (p *Progress) AddBar(total int) *Bar { | |
| 54 | func (p *progress) AddBar(total int) *Bar { | |
| 58 | 55 | bar := NewBar(total) |
| 59 | 56 | // bar.Width = p.Width |
| 60 | 57 | p.bars <- bar |
| 61 | 58 | return bar |
| 62 | 59 | } |
| 63 | 60 | |
| 64 | // Listen listens for updates and renders the progress bars | |
| 65 | func (p *Progress) server() { | |
| 61 | // Bypass returns a writer which allows non-buffered data to be written to the underlying output | |
| 62 | func (p *progress) Bypass() io.Writer { | |
| 63 | return p.lw.Bypass() | |
| 64 | } | |
| 65 | ||
| 66 | // Stop stops listening | |
| 67 | func (p *progress) Stop() { | |
| 68 | close(p.bars) | |
| 69 | } | |
| 70 | ||
| 71 | // server listens for updates and renders the progress bars | |
| 72 | func (p *progress) server() { | |
| 73 | t := time.NewTicker(30 * time.Millisecond) | |
| 66 | 74 | bars := make([]*Bar, 0) |
| 67 | 75 | p.lw.Out = p.out |
| 68 | loop: | |
| 69 | 76 | for { |
| 70 | 77 | select { |
| 71 | 78 | case bar, ok := <-p.bars: |
| 72 | 79 | if !ok { |
| 73 | break loop | |
| 80 | t.Stop() | |
| 81 | return | |
| 74 | 82 | } |
| 75 | 83 | bars = append(bars, bar) |
| 76 | case <-p.ticker.C: | |
| 84 | case <-t.C: | |
| 77 | 85 | for _, bar := range bars { |
| 78 | 86 | fmt.Fprintln(p.lw, bar.String()) |
| 79 | 87 | } |
| 80 | 88 | p.lw.Flush() |
| 89 | case d := <-p.interval: | |
| 90 | t.Stop() | |
| 91 | t = time.NewTicker(d) | |
| 81 | 92 | } |
| 82 | 93 | } |
| 83 | 94 | } |