Codebase list golang-github-vbauerster-mpb / 11d342b
Correct PopCompletedMode with multiple bars Limit number of bars by terminal height Address issues #111 #109 #107 Vladimir Bauer 3 years ago
4 changed file(s) with 95 addition(s) and 74 deletion(s). Raw diff Collapse all Expand all
2828 recoveredPanic interface{}
2929 }
3030
31 type extenderFunc func(in io.Reader, reqWidth int, st decor.Statistics) (out io.Reader, lines int)
31 type extenderFunc func(rows []io.Reader, width int, stat decor.Statistics) []io.Reader
3232
3333 // bState is actual bar's state.
3434 type bState struct {
6161 }
6262
6363 type renderFrame struct {
64 reader io.Reader
65 lines int
66 shutdown bool
64 rows []io.Reader
65 shutdown int
6766 }
6867
6968 func newBar(container *Progress, bs *bState) *Bar {
358357 func (b *Bar) render(tw int) {
359358 select {
360359 case b.operateState <- func(s *bState) {
361 var reader io.Reader
362 var lines int
360 var rows []io.Reader
363361 stat := newStatistics(tw, s)
364362 defer func() {
365363 // recovering if user defined decorator panics for example
370368 }
371369 s.aborted = !s.completed
372370 s.extender = makePanicExtender(p)
373 reader, lines = s.extender(nil, s.reqWidth, stat)
374371 b.recoveredPanic = p
375372 }
376 frame := renderFrame{
377 reader: reader,
378 lines: lines + 1,
379 shutdown: s.completed || s.aborted,
380 }
381 if frame.shutdown {
373 if s.extender != nil {
374 rows = s.extender(rows, s.reqWidth, stat)
375 }
376 frame := &renderFrame{
377 rows: rows,
378 }
379 if s.completed || s.aborted {
382380 b.cancel()
383 }
384 b.frameCh <- &frame
381 frame.shutdown++
382 }
383 b.frameCh <- frame
385384 }()
386385 if b.recoveredPanic == nil {
387 reader = s.draw(stat)
388 }
389 reader, lines = s.extender(reader, s.reqWidth, stat)
390 }:
391 case <-b.done:
392 var reader io.Reader
393 var lines int
394 stat, s := newStatistics(tw, b.bs), b.bs
386 rows = append(rows, s.draw(stat))
387 }
388 }:
389 case <-b.done:
390 var rows []io.Reader
391 s, stat := b.bs, newStatistics(tw, b.bs)
395392 if b.recoveredPanic == nil {
396 reader = s.draw(stat)
397 }
398 reader, lines = s.extender(reader, s.reqWidth, stat)
399 b.frameCh <- &renderFrame{
400 reader: reader,
401 lines: lines + 1,
402 }
393 rows = append(rows, s.draw(stat))
394 }
395 if s.extender != nil {
396 rows = s.extender(rows, s.reqWidth, stat)
397 }
398 frame := &renderFrame{
399 rows: rows,
400 }
401 b.frameCh <- frame
403402 }
404403 }
405404
595594
596595 func makePanicExtender(p interface{}) extenderFunc {
597596 pstr := fmt.Sprint(p)
598 return func(_ io.Reader, _ int, st decor.Statistics) (io.Reader, int) {
599 mr := io.MultiReader(
600 strings.NewReader(runewidth.Truncate(pstr, st.AvailableWidth, "…")),
601 strings.NewReader("\n"),
597 return func(rows []io.Reader, _ int, stat decor.Statistics) []io.Reader {
598 r := io.MultiReader(
599 strings.NewReader(runewidth.Truncate(pstr, stat.AvailableWidth, "…")),
600 bytes.NewReader([]byte("\n")),
602601 )
603 return mr, 0
604 }
605 }
602 return append(rows, r)
603 }
604 }
130130
131131 func makeExtenderFunc(filler BarFiller) extenderFunc {
132132 buf := new(bytes.Buffer)
133 return func(r io.Reader, reqWidth int, st decor.Statistics) (io.Reader, int) {
134 filler.Fill(buf, reqWidth, st)
135 return io.MultiReader(r, buf), bytes.Count(buf.Bytes(), []byte("\n"))
133 return func(rows []io.Reader, width int, stat decor.Statistics) []io.Reader {
134 buf.Reset()
135 filler.Fill(buf, width, stat)
136 for {
137 b, err := buf.ReadBytes('\n')
138 if err != nil {
139 break
140 }
141 rows = append(rows, bytes.NewReader(b))
142 }
143 return rows
136144 }
137145 }
138146
55 func (pq priorityQueue) Len() int { return len(pq) }
66
77 func (pq priorityQueue) Less(i, j int) bool {
8 return pq[i].priority < pq[j].priority
8 // less priority pops first
9 return pq[i].priority > pq[j].priority
910 }
1011
1112 func (pq priorityQueue) Swap(i, j int) {
1111 "time"
1212
1313 "github.com/vbauerster/mpb/v7/cwriter"
14 "github.com/vbauerster/mpb/v7/decor"
1514 )
1615
1716 const (
4039 // following are provided/overrided by user
4140 idCount int
4241 reqWidth int
42 popPriority int
4343 popCompleted bool
4444 outputDiscarded bool
4545 rr time.Duration
6363 // method has been called.
6464 func NewWithContext(ctx context.Context, options ...ContainerOption) *Progress {
6565 s := &pState{
66 bHeap: priorityQueue{},
67 rr: prr,
68 queueBars: make(map[*Bar]*Bar),
69 output: os.Stdout,
66 bHeap: priorityQueue{},
67 rr: prr,
68 queueBars: make(map[*Bar]*Bar),
69 output: os.Stdout,
70 popPriority: math.MinInt32,
7071 }
7172
7273 for _, opt := range options {
238239 syncWidth(s.pMatrix)
239240 syncWidth(s.aMatrix)
240241
241 tw, err := cw.GetWidth()
242 width, height, err := cw.GetTermSize()
242243 if err != nil {
243 tw = s.reqWidth
244 width = s.reqWidth
244245 }
245246 for i := 0; i < s.bHeap.Len(); i++ {
246247 bar := s.bHeap[i]
247 go bar.render(tw)
248 }
249
250 return s.flush(cw)
251 }
252
253 func (s *pState) flush(cw *cwriter.Writer) error {
254 var lines int
248 go bar.render(width)
249 }
250
251 return s.flush(cw, height)
252 }
253
254 func (s *pState) flush(cw *cwriter.Writer, height int) error {
255 var popCount int
256 rows := make([]io.Reader, 0, s.bHeap.Len())
255257 pool := make([]*Bar, 0, s.bHeap.Len())
256258 for s.bHeap.Len() > 0 {
259 var frameRowsUsed int
257260 b := heap.Pop(&s.bHeap).(*Bar)
258261 frame := <-b.frameCh
259 lines += frame.lines
260 _, err := cw.ReadFrom(frame.reader)
261 if err != nil {
262 return err
263 }
264 if frame.shutdown {
262 for i := len(frame.rows) - 1; i >= 0; i-- {
263 if len(rows) == height {
264 break
265 }
266 rows = append(rows, frame.rows[i])
267 frameRowsUsed++
268 }
269 if frame.shutdown != 0 {
265270 b.Wait() // waiting for b.done, so it's safe to read b.bs
266 var toDrop bool
271 drop := b.bs.dropOnComplete
267272 if qb, ok := s.queueBars[b]; ok {
268273 delete(s.queueBars, b)
269274 qb.priority = b.priority
275 qb.bs.dropOnComplete = drop
270276 pool = append(pool, qb)
271 toDrop = true
277 drop = true
272278 } else if s.popCompleted && !b.bs.noPop {
273 lines -= frame.lines
274 toDrop = true
275 }
276 if toDrop || b.bs.dropOnComplete {
279 if frame.shutdown > 1 {
280 popCount += frameRowsUsed
281 drop = true
282 } else {
283 s.popPriority++
284 b.priority = s.popPriority
285 }
286 }
287 if drop {
277288 s.heapUpdated = true
278289 continue
279290 }
285296 heap.Push(&s.bHeap, b)
286297 }
287298
288 return cw.Flush(lines)
299 for i := len(rows) - 1; i >= 0; i-- {
300 _, err := cw.ReadFrom(rows[i])
301 if err != nil {
302 return err
303 }
304 }
305
306 return cw.Flush(len(rows) - popCount)
289307 }
290308
291309 func (s *pState) newTicker(done <-chan struct{}) chan time.Time {
351369 reqWidth: s.reqWidth,
352370 total: total,
353371 filler: filler,
354 extender: func(r io.Reader, _ int, _ decor.Statistics) (io.Reader, int) { return r, 0 },
355372 debugOut: s.debugOut,
356373 }
357374
368385 if bs.middleware != nil {
369386 bs.filler = bs.middleware(filler)
370387 bs.middleware = nil
371 }
372
373 if s.popCompleted && !bs.noPop {
374 bs.priority = -(math.MaxInt32 - s.idCount)
375388 }
376389
377390 for i := 0; i < len(bs.buffers); i++ {