diff options
Diffstat (limited to 'vendor/github.com/vbauerster/mpb/bar.go')
-rw-r--r-- | vendor/github.com/vbauerster/mpb/bar.go | 186 |
1 files changed, 65 insertions, 121 deletions
diff --git a/vendor/github.com/vbauerster/mpb/bar.go b/vendor/github.com/vbauerster/mpb/bar.go index 5a506fc84..a304a87cb 100644 --- a/vendor/github.com/vbauerster/mpb/bar.go +++ b/vendor/github.com/vbauerster/mpb/bar.go @@ -2,6 +2,7 @@ package mpb import ( "bytes" + "context" "fmt" "io" "io/ioutil" @@ -11,21 +12,8 @@ import ( "unicode/utf8" "github.com/vbauerster/mpb/decor" - "github.com/vbauerster/mpb/internal" ) -const ( - rLeft = iota - rFill - rTip - rEmpty - rRight -) - -const formatLen = 5 - -type barRunes [formatLen]rune - // Bar represents a progress Bar type Bar struct { priority int @@ -45,15 +33,30 @@ type Bar struct { shutdown chan struct{} } +// Filler interface. +// Bar renders by calling Filler's Fill method. You can literally have +// any bar kind, by implementing this interface and passing it to the +// Add method. +type Filler interface { + Fill(w io.Writer, width int, s *decor.Statistics) +} + +// FillerFunc is function type adapter to convert function into Filler. +type FillerFunc func(w io.Writer, width int, stat *decor.Statistics) + +func (f FillerFunc) Fill(w io.Writer, width int, stat *decor.Statistics) { + f(w, width, stat) +} + type ( bState struct { + filler Filler id int width int + alignment int total int64 current int64 - runes barRunes - trimLeftSpace bool - trimRightSpace bool + trimSpace bool toComplete bool removeOnComplete bool barClearOnComplete bool @@ -73,8 +76,8 @@ type ( runningBar *Bar } refill struct { - char rune - till int64 + r rune + limit int64 } frameReader struct { io.Reader @@ -84,14 +87,20 @@ type ( } ) -func newBar(wg *sync.WaitGroup, id int, total int64, cancel <-chan struct{}, options ...BarOption) *Bar { - if total <= 0 { - total = time.Now().Unix() - } +func newBar( + ctx context.Context, + wg *sync.WaitGroup, + filler Filler, + id, width int, + total int64, + options ...BarOption, +) *Bar { s := &bState{ + filler: filler, id: id, priority: id, + width: width, total: total, } @@ -104,6 +113,9 @@ func newBar(wg *sync.WaitGroup, id int, total int64, cancel <-chan struct{}, opt s.bufP = bytes.NewBuffer(make([]byte, 0, s.width)) s.bufB = bytes.NewBuffer(make([]byte, 0, s.width)) s.bufA = bytes.NewBuffer(make([]byte, 0, s.width)) + if s.newLineExtendFn != nil { + s.bufNL = bytes.NewBuffer(make([]byte, 0, s.width)) + } b := &Bar{ priority: s.priority, @@ -121,11 +133,7 @@ func newBar(wg *sync.WaitGroup, id int, total int64, cancel <-chan struct{}, opt b.priority = b.runningBar.priority } - if s.newLineExtendFn != nil { - s.bufNL = bytes.NewBuffer(make([]byte, 0, s.width)) - } - - go b.serve(wg, s, cancel) + go b.serve(ctx, wg, s) return b } @@ -178,52 +186,42 @@ func (b *Bar) Current() int64 { } // SetTotal sets total dynamically. -// Set final to true, when total is known, it will trigger bar complete event. -func (b *Bar) SetTotal(total int64, final bool) bool { +// Set complete to true, to trigger bar complete event now. +func (b *Bar) SetTotal(total int64, complete bool) { select { case b.operateState <- func(s *bState) { - if total > 0 { - s.total = total - } - if final { + s.total = total + if complete && !s.toComplete { s.current = s.total s.toComplete = true } }: - return true case <-b.done: - return false } } -// SetRefill sets fill rune to r, up until n. -func (b *Bar) SetRefill(n int, r rune) { - if n <= 0 { - return - } +// SetRefill sets refill, if supported by underlying Filler. +func (b *Bar) SetRefill(amount int64) { b.operateState <- func(s *bState) { - s.refill = &refill{r, int64(n)} + if f, ok := s.filler.(interface{ SetRefill(int64) }); ok { + f.SetRefill(amount) + } } } -// RefillBy is deprecated, use SetRefill -func (b *Bar) RefillBy(n int, r rune) { - b.SetRefill(n, r) -} - // Increment is a shorthand for b.IncrBy(1). func (b *Bar) Increment() { b.IncrBy(1) } // IncrBy increments progress bar by amount of n. -// wdd is optional work duration i.e. time.Since(start), -// which expected to be provided, if any ewma based decorator is used. +// wdd is optional work duration i.e. time.Since(start), which expected +// to be provided, if any ewma based decorator is used. func (b *Bar) IncrBy(n int, wdd ...time.Duration) { select { case b.operateState <- func(s *bState) { s.current += int64(n) - if s.current >= s.total { + if s.total > 0 && s.current >= s.total { s.current = s.total s.toComplete = true } @@ -238,9 +236,9 @@ func (b *Bar) IncrBy(n int, wdd ...time.Duration) { // Completed reports whether the bar is in completed state. func (b *Bar) Completed() bool { // omit select here, because primary usage of the method is for loop - // condition, like for !bar.Completed() {...} - // so when toComplete=true it is called once (at which time, the bar is still alive), - // then quits the loop and never suppose to be called afterwards. + // condition, like for !bar.Completed() {...} so when toComplete=true + // it is called once (at which time, the bar is still alive), then + // quits the loop and never suppose to be called afterwards. return <-b.boolCh } @@ -253,8 +251,9 @@ func (b *Bar) wSyncTable() [][]chan int { } } -func (b *Bar) serve(wg *sync.WaitGroup, s *bState, cancel <-chan struct{}) { +func (b *Bar) serve(ctx context.Context, wg *sync.WaitGroup, s *bState) { defer wg.Done() + cancel := ctx.Done() for { select { case op := <-b.operateState: @@ -322,8 +321,6 @@ func (b *Bar) render(debugOut io.Writer, tw int) { } func (s *bState) draw(termWidth int) io.Reader { - defer s.bufA.WriteByte('\n') - if s.panicMsg != "" { return strings.NewReader(fmt.Sprintf(fmt.Sprintf("%%.%ds\n", termWidth), s.panicMsg)) } @@ -338,77 +335,32 @@ func (s *bState) draw(termWidth int) io.Reader { s.bufA.WriteString(d.Decor(stat)) } - prependCount := utf8.RuneCount(s.bufP.Bytes()) - appendCount := utf8.RuneCount(s.bufA.Bytes()) - if s.barClearOnComplete && s.completeFlushed { + s.bufA.WriteByte('\n') return io.MultiReader(s.bufP, s.bufA) } - s.fillBar(s.width) - barCount := utf8.RuneCount(s.bufB.Bytes()) - totalCount := prependCount + barCount + appendCount - if spaceCount := 0; totalCount > termWidth { - if !s.trimLeftSpace { - spaceCount++ - } - if !s.trimRightSpace { - spaceCount++ - } - s.fillBar(termWidth - prependCount - appendCount - spaceCount) - } - - return io.MultiReader(s.bufP, s.bufB, s.bufA) -} - -func (s *bState) fillBar(width int) { - defer func() { - s.bufB.WriteRune(s.runes[rRight]) - if !s.trimRightSpace { - s.bufB.WriteByte(' ') - } - }() + prependCount := utf8.RuneCount(s.bufP.Bytes()) + appendCount := utf8.RuneCount(s.bufA.Bytes()) - s.bufB.Reset() - if !s.trimLeftSpace { + if !s.trimSpace { + // reserve space for edge spaces + termWidth -= 2 s.bufB.WriteByte(' ') } - s.bufB.WriteRune(s.runes[rLeft]) - if width <= 2 { - return - } - - // bar s.width without leftEnd and rightEnd runes - barWidth := width - 2 - - completedWidth := internal.Percentage(s.total, s.current, int64(barWidth)) - if s.refill != nil { - till := internal.Percentage(s.total, s.refill.till, int64(barWidth)) - // append refill rune - var i int64 - for i = 0; i < till; i++ { - s.bufB.WriteRune(s.refill.char) - } - for i = till; i < completedWidth; i++ { - s.bufB.WriteRune(s.runes[rFill]) - } + if prependCount+s.width+appendCount > termWidth { + s.filler.Fill(s.bufB, termWidth-prependCount-appendCount, stat) } else { - var i int64 - for i = 0; i < completedWidth; i++ { - s.bufB.WriteRune(s.runes[rFill]) - } + s.filler.Fill(s.bufB, s.width, stat) } - if completedWidth < int64(barWidth) && completedWidth > 0 { - _, size := utf8.DecodeLastRune(s.bufB.Bytes()) - s.bufB.Truncate(s.bufB.Len() - size) - s.bufB.WriteRune(s.runes[rTip]) + if !s.trimSpace { + s.bufB.WriteByte(' ') } - for i := completedWidth; i < int64(barWidth); i++ { - s.bufB.WriteRune(s.runes[rEmpty]) - } + s.bufA.WriteByte('\n') + return io.MultiReader(s.bufP, s.bufB, s.bufA) } func (s *bState) wSyncTable() [][]chan int { @@ -442,14 +394,6 @@ func newStatistics(s *bState) *decor.Statistics { } } -func strToBarRunes(format string) (array barRunes) { - for i, n := 0, 0; len(format) > 0; i++ { - array[i], n = utf8.DecodeRuneInString(format) - format = format[n:] - } - return -} - func countLines(b []byte) int { return bytes.Count(b, []byte("\n")) } |