summaryrefslogtreecommitdiff
path: root/vendor/github.com/vbauerster/mpb/bar.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/vbauerster/mpb/bar.go')
-rw-r--r--vendor/github.com/vbauerster/mpb/bar.go186
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"))
}