Codebase list golang-github-vbauerster-mpb / 7b19941
introduce BeforeRender Vladimir Bauer 9 years ago
2 changed file(s) with 61 addition(s) and 74 deletion(s). Raw diff Collapse all Expand all
2828 lastState state
2929 }
3030
31 // Statistics represents statistics of the progress bar
32 // instance of this, sent to DecoratorFunc, as param
31 // Statistics represents statistics of the progress bar.
32 // Cantains: Total, Current, TimeElapsed, TimePerItemEstimate
3333 type Statistics struct {
3434 Total, Current int64
35 TermWidth int
3635 TimeElapsed, TimePerItemEstimate time.Duration
3736 }
3837
38 // Eta returns exponential-weighted-moving-average ETA estimator
3939 func (s *Statistics) Eta() time.Duration {
4040 return time.Duration(s.Total-s.Current) * s.TimePerItemEstimate
4141 }
200200 b.refillCh <- &refill{c, int64(n)}
201201 }
202202
203 // Current returns the actual current.
204 func (b *Bar) Current() int64 {
205 if IsClosed(b.done) {
206 return b.lastState.current
207 }
208 ch := make(chan state, 1)
209 b.stateReqCh <- ch
210 state := <-ch
211 return state.current
203 // GetAppenders returns slice of appender DecoratorFunc
204 func (b *Bar) GetAppenders() []DecoratorFunc {
205 s := b.getState()
206 return s.appendFuncs
207 }
208
209 // GetAppenders returns slice of prepender DecoratorFunc
210 func (b *Bar) GetPrependers() []DecoratorFunc {
211 s := b.getState()
212 return s.prependFuncs
213 }
214
215 // GetStatistics returs *Statistics, which contains information like Tottal,
216 // Current, TimeElapsed and TimePerItemEstimate
217 func (b *Bar) GetStatistics() *Statistics {
218 state := b.getState()
219 return state.newStat()
212220 }
213221
214222 // InProgress returns true, while progress is running
261269 b.completeReqCh <- struct{}{}
262270 }
263271
264 func (b *Bar) bytes(termWidth int) []byte {
265 if IsClosed(b.done) {
266 return b.lastState.draw(termWidth)
272 func (b *Bar) getState() state {
273 if IsClosed(b.done) {
274 return b.lastState
267275 }
268276 ch := make(chan state, 1)
269277 b.stateReqCh <- ch
270 s := <-ch
271 return s.draw(termWidth)
278 return <-ch
279 }
280
281 func (b *Bar) bytes(termWidth int) []byte {
282 state := b.getState()
283 return state.draw(termWidth)
272284 }
273285
274286 func (b *Bar) server(ctx context.Context, wg *sync.WaitGroup, total int64, barWidth int) {
364376 b.removeReqCh <- struct{}{}
365377 }
366378
379 func (s *state) newStat() *Statistics {
380 return &Statistics{
381 Total: s.total,
382 Current: s.current,
383 TimeElapsed: s.timeElapsed,
384 TimePerItemEstimate: s.timePerItem,
385 }
386 }
387
367388 func (s *state) draw(termWidth int) []byte {
368389 if termWidth <= 0 {
369390 termWidth = s.barWidth
370391 }
371 stat := &Statistics{
372 Total: s.total,
373 Current: s.current,
374 TermWidth: termWidth,
375 TimeElapsed: s.timeElapsed,
376 TimePerItemEstimate: s.timePerItem,
377 }
392
393 stat := s.newStat()
378394
379395 // render append functions to the right of the bar
380396 var appendBlock []byte
458474 return buf
459475 }
460476
461 func (b *Bar) status() int {
462 var total, current int64
463 if IsClosed(b.done) {
464 total = b.lastState.total
465 current = b.lastState.current
466 } else {
467 ch := make(chan state, 1)
468 b.stateReqCh <- ch
469 state := <-ch
470 total = state.total
471 current = state.current
472 }
473 return percentage(total, current, 100)
474 }
475
476 // SortableBarSlice satisfies sort interface
477 type SortableBarSlice []*Bar
478
479 func (p SortableBarSlice) Len() int { return len(p) }
480
481 func (p SortableBarSlice) Less(i, j int) bool { return p[i].status() < p[j].status() }
482
483 func (p SortableBarSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
484
485477 func calcTimePerItemEstimate(tpie time.Duration, blockStartTime time.Time, alpha float64, items int64) time.Duration {
486478 lastBlockTime := time.Since(blockStartTime)
487479 lastItemEstimate := float64(lastBlockTime) / float64(items)
55 "io"
66 "log"
77 "os"
8 "sort"
98 "sync"
109 "time"
1110
1918 var ErrCallAfterStop = errors.New("method call on stopped Progress instance")
2019
2120 type (
22 // SortType defines sort direction of bar
23 SortType uint
24 opType uint
21 // BeforeRender is a func, which gets called before render process
22 BeforeRender func([]*Bar)
23 barOpType uint
2524
2625 operation struct {
27 kind opType
26 kind barOpType
2827 bar *Bar
2928 result chan bool
3029 }
4241 )
4342
4443 const (
45 opBarAdd opType = iota
46 opBarRemove
47 )
48
49 const (
50 SortNone SortType = iota
51 SortTop
52 SortBottom
44 barAdd barOpType = iota
45 barRemove
5346 )
5447
5548 // default RefreshRate
6457
6558 out io.Writer
6659 width int
67 sort SortType
6860
6961 operationCh chan *operation
7062 rrChangeReqCh chan time.Duration
7163 outChangeReqCh chan io.Writer
7264 barCountReqCh chan chan int
65 brCh chan BeforeRender
7366 done chan struct{}
7467 }
7568
8679 rrChangeReqCh: make(chan time.Duration),
8780 outChangeReqCh: make(chan io.Writer),
8881 barCountReqCh: make(chan chan int),
82 brCh: make(chan BeforeRender),
8983 done: make(chan struct{}),
9084 wg: new(sync.WaitGroup),
9185 ctx: ctx,
126120 return p
127121 }
128122
129 // WithSort sorts the bars, while redering
130 func (p *Progress) WithSort(sort SortType) *Progress {
131 p.sort = sort
123 func (p *Progress) BeforeRenderFunc(f BeforeRender) *Progress {
124 if IsClosed(p.done) {
125 panic(ErrCallAfterStop)
126 }
127 p.brCh <- f
132128 return p
133129 }
134130
140136 }
141137 result := make(chan bool)
142138 bar := newBar(p.ctx, p.wg, total, p.width)
143 p.operationCh <- &operation{opBarAdd, bar, result}
139 p.operationCh <- &operation{barAdd, bar, result}
144140 if <-result {
145141 p.wg.Add(1)
146142 }
154150 panic(ErrCallAfterStop)
155151 }
156152 result := make(chan bool)
157 p.operationCh <- &operation{opBarRemove, b, result}
153 p.operationCh <- &operation{barRemove, b, result}
158154 return <-result
159155 }
160156
186182 }()
187183 const numDrawers = 3
188184 bars := make([]*Bar, 0, 4)
185 var beforeRender BeforeRender
189186 var wg sync.WaitGroup
190187 recoverIfPanic := func() {
191188 if e := recover(); e != nil {
203200 return
204201 }
205202 switch op.kind {
206 case opBarAdd:
203 case barAdd:
207204 bars = append(bars, op.bar)
208205 op.result <- true
209 case opBarRemove:
206 case barRemove:
210207 var ok bool
211208 for i, b := range bars {
212209 if b == op.bar {
220217 }
221218 case respCh := <-p.barCountReqCh:
222219 respCh <- len(bars)
220 case beforeRender = <-p.brCh:
223221 case <-t.C:
224 switch p.sort {
225 case SortTop:
226 sort.Sort(sort.Reverse(SortableBarSlice(bars)))
227 case SortBottom:
228 sort.Sort(SortableBarSlice(bars))
222 if beforeRender != nil {
223 beforeRender(bars)
229224 }
230225
231226 width, _, _ := cwriter.GetTermSize()