diff --git a/bar.go b/bar.go index 9bcfa94..a47b831 100644 --- a/bar.go +++ b/bar.go @@ -85,9 +85,9 @@ } ) -func newBar(id int, total int64, width int, format string, wg *sync.WaitGroup, cancel <-chan struct{}) *Bar { +func newBar(total int64, wg *sync.WaitGroup, cancel <-chan struct{}, options ...BarOption) *Bar { b := &Bar{ - width: width, + // width: width, stateCh: make(chan state), incrCh: make(chan incrReq), flushedCh: make(chan struct{}), @@ -95,23 +95,24 @@ completeReqCh: make(chan struct{}), done: make(chan struct{}), inProgress: make(chan struct{}), - cancel: cancel, } s := state{ - id: id, total: total, - width: width, etaAlpha: 0.25, } if total <= 0 { s.simpleSpinner = getSpinner() - } else { - s.updateFormat(format) - } - - go b.server(wg, s) + } + + for _, opt := range options { + opt(&s) + } + + b.width = s.width + + go b.server(s, wg, cancel) return b } @@ -298,7 +299,7 @@ } } -func (b *Bar) server(wg *sync.WaitGroup, s state) { +func (b *Bar) server(s state, wg *sync.WaitGroup, cancel <-chan struct{}) { var incrStartTime time.Time defer func() { diff --git a/bar_option.go b/bar_option.go new file mode 100644 index 0000000..a912c34 --- /dev/null +++ b/bar_option.go @@ -0,0 +1,46 @@ +package mpb + +type BarOption func(*state) + +func AppendDecorators(appenders ...DecoratorFunc) BarOption { + return func(bs *state) { + bs.appendFuncs = append(bs.appendFuncs, appenders...) + } +} + +func PrependDecorators(prependers ...DecoratorFunc) BarOption { + return func(bs *state) { + bs.prependFuncs = append(bs.prependFuncs, prependers...) + } +} + +func BarTrimLeft(bs *state) { + bs.trimLeftSpace = true +} + +func BarTrimRight(bs *state) { + bs.trimRightSpace = true +} + +func BarTrim(bs *state) { + bs.trimLeftSpace = true + bs.trimRightSpace = true +} + +func BarID(id int) BarOption { + return func(bs *state) { + bs.id = id + } +} + +func barWidth(w int) BarOption { + return func(bs *state) { + bs.width = w + } +} + +func barFormat(format string) BarOption { + return func(bs *state) { + bs.updateFormat(format) + } +} diff --git a/decorators.go b/decorators.go index 15affaa..4591997 100644 --- a/decorators.go +++ b/decorators.go @@ -24,15 +24,13 @@ // DecoratorFunc is a function that can be prepended and appended to the progress bar type DecoratorFunc func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string -// PrependName prepends name argument to the bar. -// The conf argument defines the formatting properties -func (b *Bar) PrependName(name string, minWidth int, conf byte) *Bar { +func Name(name string, minWidth int, conf byte) DecoratorFunc { format := "%%" if (conf & DidentRight) != 0 { format += "-" } format += "%ds" - b.PrependFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { + return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { if (conf & DwidthSync) != 0 { myWidth <- utf8.RuneCountInString(name) max := <-maxWidth @@ -42,17 +40,16 @@ return fmt.Sprintf(fmt.Sprintf(format, max), name) } return fmt.Sprintf(fmt.Sprintf(format, minWidth), name) - }) - return b + } } -func (b *Bar) PrependCounters(pairFormat string, unit Units, minWidth int, conf byte) *Bar { +func Counters(pairFormat string, unit Units, minWidth int, conf byte) DecoratorFunc { format := "%%" if (conf & DidentRight) != 0 { format += "-" } format += "%ds" - b.PrependFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { + return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { current := Format(s.Current).To(unit) total := Format(s.Total).To(unit) str := fmt.Sprintf(pairFormat, current, total) @@ -65,17 +62,16 @@ return fmt.Sprintf(fmt.Sprintf(format, max), str) } return fmt.Sprintf(fmt.Sprintf(format, minWidth), str) - }) - return b + } } -func (b *Bar) PrependETA(minWidth int, conf byte) *Bar { +func ETA(minWidth int, conf byte) DecoratorFunc { format := "%%" if (conf & DidentRight) != 0 { format += "-" } format += "%ds" - b.PrependFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { + return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { str := fmt.Sprint(time.Duration(s.Eta().Seconds()) * time.Second) if (conf & DwidthSync) != 0 { myWidth <- utf8.RuneCountInString(str) @@ -86,38 +82,16 @@ return fmt.Sprintf(fmt.Sprintf(format, max), str) } return fmt.Sprintf(fmt.Sprintf(format, minWidth), str) - }) - return b + } } -func (b *Bar) AppendETA(minWidth int, conf byte) *Bar { +func (b *Bar) Elapsed(minWidth int, conf byte) DecoratorFunc { format := "%%" if (conf & DidentRight) != 0 { format += "-" } format += "%ds" - b.AppendFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { - str := fmt.Sprint(time.Duration(s.Eta().Seconds()) * time.Second) - if (conf & DwidthSync) != 0 { - myWidth <- utf8.RuneCountInString(str) - max := <-maxWidth - if (conf & DextraSpace) != 0 { - max++ - } - return fmt.Sprintf(fmt.Sprintf(format, max), str) - } - return fmt.Sprintf(fmt.Sprintf(format, minWidth), str) - }) - return b -} - -func (b *Bar) PrependElapsed(minWidth int, conf byte) *Bar { - format := "%%" - if (conf & DidentRight) != 0 { - format += "-" - } - format += "%ds" - b.PrependFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { + return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { str := fmt.Sprint(time.Duration(s.TimeElapsed.Seconds()) * time.Second) if (conf & DwidthSync) != 0 { myWidth <- utf8.RuneCountInString(str) @@ -128,38 +102,16 @@ return fmt.Sprintf(fmt.Sprintf(format, max), str) } return fmt.Sprintf(fmt.Sprintf(format, minWidth), str) - }) - return b + } } -func (b *Bar) AppendElapsed(minWidth int, conf byte) *Bar { +func Percentage(minWidth int, conf byte) DecoratorFunc { format := "%%" if (conf & DidentRight) != 0 { format += "-" } format += "%ds" - b.AppendFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { - str := fmt.Sprint(time.Duration(s.TimeElapsed.Seconds()) * time.Second) - if (conf & DwidthSync) != 0 { - myWidth <- utf8.RuneCountInString(str) - max := <-maxWidth - if (conf & DextraSpace) != 0 { - max++ - } - return fmt.Sprintf(fmt.Sprintf(format, max), str) - } - return fmt.Sprintf(fmt.Sprintf(format, minWidth), str) - }) - return b -} - -func (b *Bar) AppendPercentage(minWidth int, conf byte) *Bar { - format := "%%" - if (conf & DidentRight) != 0 { - format += "-" - } - format += "%ds" - b.AppendFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { + return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { str := fmt.Sprintf("%d %%", percentage(s.Total, s.Current, 100)) if (conf & DwidthSync) != 0 { myWidth <- utf8.RuneCountInString(str) @@ -170,27 +122,5 @@ return fmt.Sprintf(fmt.Sprintf(format, max), str) } return fmt.Sprintf(fmt.Sprintf(format, minWidth), str) - }) - return b + } } - -func (b *Bar) PrependPercentage(minWidth int, conf byte) *Bar { - format := "%%" - if (conf & DidentRight) != 0 { - format += "-" - } - format += "%ds" - b.PrependFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { - str := fmt.Sprintf("%d %%", percentage(s.Total, s.Current, 100)) - if (conf & DwidthSync) != 0 { - myWidth <- utf8.RuneCountInString(str) - max := <-maxWidth - if (conf & DextraSpace) != 0 { - max++ - } - return fmt.Sprintf(fmt.Sprintf(format, max), str) - } - return fmt.Sprintf(fmt.Sprintf(format, minWidth), str) - }) - return b -} diff --git a/example/prependETA/main.go b/example/prependETA/main.go index 6a615b0..ae8cebd 100644 --- a/example/prependETA/main.go +++ b/example/prependETA/main.go @@ -15,61 +15,40 @@ func main() { + p := mpb.New(mpb.WithWidth(64)) + + total := 100 + numBars := 3 var wg sync.WaitGroup - p := mpb.New().SetWidth(64) + wg.Add(numBars) - name1 := "Bar#1:" - bar1 := p.AddBar(50). - PrependName(name1, 0, mpb.DwidthSync|mpb.DidentRight). - PrependETA(4, mpb.DwidthSync|mpb.DextraSpace). - AppendPercentage(5, 0) - - wg.Add(1) - go func() { - defer wg.Done() - blockSize := rand.Intn(maxBlockSize) + 1 - for i := 0; i < 50; i++ { - sleep(blockSize) - bar1.Incr(1) - blockSize = rand.Intn(maxBlockSize) + 1 + for i := 0; i < numBars; i++ { + var name string + if i != 1 { + name = fmt.Sprintf("Bar#%d:", i) } - }() - - bar2 := p.AddBar(100). - PrependName("", 0, mpb.DwidthSync). - PrependETA(4, mpb.DwidthSync|mpb.DextraSpace). - AppendPercentage(5, 0) - - wg.Add(1) - go func() { - defer wg.Done() - blockSize := rand.Intn(maxBlockSize) + 1 - for i := 0; i < 100; i++ { - sleep(blockSize) - bar2.Incr(1) - blockSize = rand.Intn(maxBlockSize) + 1 - } - }() - - bar3 := p.AddBar(80). - PrependName("Bar#3:", 0, mpb.DwidthSync|mpb.DidentRight). - PrependETA(4, mpb.DwidthSync|mpb.DextraSpace). - AppendPercentage(5, 0) - - wg.Add(1) - go func() { - defer wg.Done() - blockSize := rand.Intn(maxBlockSize) + 1 - for i := 0; i < 80; i++ { - sleep(blockSize) - bar3.Incr(1) - blockSize = rand.Intn(maxBlockSize) + 1 - } - }() + b := p.AddBar(int64(total), + mpb.PrependDecorators( + mpb.Name(name, 0, mpb.DwidthSync|mpb.DidentRight), + mpb.ETA(4, mpb.DwidthSync|mpb.DextraSpace), + ), + mpb.AppendDecorators( + mpb.Percentage(5, 0), + ), + ) + go func() { + defer wg.Done() + blockSize := rand.Intn(maxBlockSize) + 1 + for i := 0; i < total; i++ { + sleep(blockSize) + b.Incr(1) + blockSize = rand.Intn(maxBlockSize) + 1 + } + }() + } wg.Wait() p.Stop() - // p.AddBar(1) // panic: you cannot reuse p, create new one! fmt.Println("stop") } diff --git a/progress.go b/progress.go index b540d96..b2caa73 100644 --- a/progress.go +++ b/progress.go @@ -118,28 +118,15 @@ }) } -// RefreshRate Deprecated, use mpb.WithRefreshRate -func (p *Progress) RefreshRate(d time.Duration) *Progress { - return updateConf(p, func(c *pConf) { - c.ticker.Stop() - c.ticker = time.NewTicker(d) - c.rr = d - }) -} - // AddBar creates a new progress bar and adds to the container. -func (p *Progress) AddBar(total int64) *Bar { - return p.AddBarWithID(0, total) -} - -// AddBarWithID creates a new progress bar and adds to the container. -func (p *Progress) AddBarWithID(id int, total int64) *Bar { +func (p *Progress) AddBar(total int64, options ...BarOption) *Bar { result := make(chan *Bar, 1) op := func(c *pConf) { - bar := newBar(id, total, c.width, c.format, p.wg, c.cancel) - c.bars = append(c.bars, bar) + options = append(options, barWidth(c.width), barFormat(c.format)) + b := newBar(total, p.wg, c.cancel, options...) + c.bars = append(c.bars, b) p.wg.Add(1) - result <- bar + result <- b } select { case p.ops <- op: