diff --git a/README.md b/README.md index a87786d..d0560d7 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # Multi Progress Bar -[![GoDoc](https://pkg.go.dev/badge/github.com/vbauerster/mpb)](https://pkg.go.dev/github.com/vbauerster/mpb/v6) +[![GoDoc](https://pkg.go.dev/badge/github.com/vbauerster/mpb)](https://pkg.go.dev/github.com/vbauerster/mpb/v7) [![Build Status](https://travis-ci.org/vbauerster/mpb.svg?branch=master)](https://travis-ci.org/vbauerster/mpb) [![Go Report Card](https://goreportcard.com/badge/github.com/vbauerster/mpb)](https://goreportcard.com/report/github.com/vbauerster/mpb) +[![Donate with PayPal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/vbauerster) **mpb** is a Go lib for rendering progress bars in terminal applications. @@ -26,8 +27,8 @@ "math/rand" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { @@ -39,7 +40,7 @@ // adding a single bar, which will inherit container's width bar := p.Add(int64(total), // progress bar filler with customized style - mpb.NewBarFiller("╢▌▌░╟"), + mpb.NewBarFiller(mpb.BarStyle().Lbound("╢").Filler("▌").Tip("▌").Padding("░").Rbound("╟")), mpb.PrependDecorators( // display our name with one space on the right decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight}), @@ -65,7 +66,7 @@ ```go var wg sync.WaitGroup - // pass &wg (optional), so p will wait for it eventually + // passed &wg will be accounted at p.Wait() call p := mpb.New(mpb.WithWaitGroup(&wg)) total, numBars := 100, 3 wg.Add(numBars) diff --git a/_examples/barExtender/go.mod b/_examples/barExtender/go.mod index be164a9..9a2af7e 100644 --- a/_examples/barExtender/go.mod +++ b/_examples/barExtender/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/barExtender/main.go b/_examples/barExtender/main.go index 34e760f..d4724b6 100644 --- a/_examples/barExtender/main.go +++ b/_examples/barExtender/main.go @@ -7,8 +7,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { diff --git a/_examples/cancel/go.mod b/_examples/cancel/go.mod index e6192d2..b6db6b1 100644 --- a/_examples/cancel/go.mod +++ b/_examples/cancel/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/cancel/main.go b/_examples/cancel/main.go index 6f4a3de..4025b79 100644 --- a/_examples/cancel/main.go +++ b/_examples/cancel/main.go @@ -7,8 +7,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { diff --git a/_examples/complex/go.mod b/_examples/complex/go.mod index b6b796e..322a14d 100644 --- a/_examples/complex/go.mod +++ b/_examples/complex/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/complex/main.go b/_examples/complex/main.go index 85aa98f..0e96a36 100644 --- a/_examples/complex/main.go +++ b/_examples/complex/main.go @@ -6,8 +6,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func init() { diff --git a/_examples/decoratorsOnTop/go.mod b/_examples/decoratorsOnTop/go.mod index 299a87f..1f33097 100644 --- a/_examples/decoratorsOnTop/go.mod +++ b/_examples/decoratorsOnTop/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/decoratorsOnTop/main.go b/_examples/decoratorsOnTop/main.go index bdd0bd5..16163b6 100644 --- a/_examples/decoratorsOnTop/main.go +++ b/_examples/decoratorsOnTop/main.go @@ -5,8 +5,8 @@ "math/rand" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { @@ -24,7 +24,7 @@ decor.AverageETA(decor.ET_STYLE_GO), "done", ), ), - mpb.BarExtender(nlBarFiller(mpb.NewBarFiller("╢▌▌░╟"))), + mpb.BarExtender(nlBarFiller(mpb.NewBarFiller(mpb.BarStyle()))), ) // simulating some work max := 100 * time.Millisecond diff --git a/_examples/differentWidth/go.mod b/_examples/differentWidth/go.mod index 57700e2..ffca3ec 100644 --- a/_examples/differentWidth/go.mod +++ b/_examples/differentWidth/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/differentWidth/main.go b/_examples/differentWidth/main.go index 7ed5b42..378bb57 100644 --- a/_examples/differentWidth/main.go +++ b/_examples/differentWidth/main.go @@ -6,8 +6,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { diff --git a/_examples/dynTotal/go.mod b/_examples/dynTotal/go.mod index 2ae2bad..7e9bc47 100644 --- a/_examples/dynTotal/go.mod +++ b/_examples/dynTotal/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/dynTotal/main.go b/_examples/dynTotal/main.go index 99342ba..aabcc42 100644 --- a/_examples/dynTotal/main.go +++ b/_examples/dynTotal/main.go @@ -5,8 +5,8 @@ "math/rand" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func init() { diff --git a/_examples/io/go.mod b/_examples/io/go.mod index 2eba870..6b373db 100644 --- a/_examples/io/go.mod +++ b/_examples/io/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/io/main.go b/_examples/io/main.go index bd07df9..6f2bf89 100644 --- a/_examples/io/main.go +++ b/_examples/io/main.go @@ -6,8 +6,8 @@ "io/ioutil" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { @@ -20,7 +20,7 @@ ) bar := p.Add(total, - mpb.NewBarFiller("[=>-|"), + mpb.NewBarFiller(mpb.BarStyle().Rbound("|")), mpb.PrependDecorators( decor.CountersKibiByte("% .2f / % .2f"), ), diff --git a/_examples/merge/go.mod b/_examples/merge/go.mod index 748b441..9195740 100644 --- a/_examples/merge/go.mod +++ b/_examples/merge/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/merge/main.go b/_examples/merge/main.go index 5b54e14..beda1d4 100644 --- a/_examples/merge/main.go +++ b/_examples/merge/main.go @@ -6,8 +6,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { diff --git a/_examples/mexicanBar/go.mod b/_examples/mexicanBar/go.mod new file mode 100644 index 0000000..185d104 --- /dev/null +++ b/_examples/mexicanBar/go.mod @@ -0,0 +1,5 @@ +module github.com/vbauerster/mpb/_examples/mexicanBar + +go 1.14 + +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/mexicanBar/main.go b/_examples/mexicanBar/main.go new file mode 100644 index 0000000..c157ae9 --- /dev/null +++ b/_examples/mexicanBar/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "math/rand" + "time" + + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" +) + +func main() { + // initialize progress container, with custom width + p := mpb.New(mpb.WithWidth(80)) + + total := 100 + name := "Complex Filler:" + bs := mpb.BarStyle() + bs.Lbound("[\u001b[36;1m") + bs.Filler("_") + bs.Tip("\u001b[0m⛵\u001b[36;1m") + bs.Padding("_") + bs.Rbound("\u001b[0m]") + bar := p.Add(int64(total), + mpb.NewBarFiller(bs), + mpb.PrependDecorators(decor.Name(name)), + mpb.AppendDecorators(decor.Percentage()), + ) + // simulating some work + max := 100 * time.Millisecond + for i := 0; i < total; i++ { + time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) + bar.Increment() + } + // wait for our bar to complete + p.Wait() +} diff --git a/_examples/multiBars/go.mod b/_examples/multiBars/go.mod index 2a1ac25..14d365a 100644 --- a/_examples/multiBars/go.mod +++ b/_examples/multiBars/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/multiBars/main.go b/_examples/multiBars/main.go index 65cfeef..b16562a 100644 --- a/_examples/multiBars/main.go +++ b/_examples/multiBars/main.go @@ -6,13 +6,13 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { var wg sync.WaitGroup - // pass &wg (optional), so p will wait for it eventually + // passed &wg will be accounted at p.Wait() call p := mpb.New(mpb.WithWaitGroup(&wg)) total, numBars := 100, 3 wg.Add(numBars) diff --git a/_examples/panic/go.mod b/_examples/panic/go.mod index 15a905b..8f26d32 100644 --- a/_examples/panic/go.mod +++ b/_examples/panic/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/panic/main.go b/_examples/panic/main.go index a569c49..ae0b890 100644 --- a/_examples/panic/main.go +++ b/_examples/panic/main.go @@ -7,8 +7,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { diff --git a/_examples/poplog/go.mod b/_examples/poplog/go.mod index d1de4d5..e7eba2a 100644 --- a/_examples/poplog/go.mod +++ b/_examples/poplog/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/poplog/main.go b/_examples/poplog/main.go index d787444..b481a1a 100644 --- a/_examples/poplog/main.go +++ b/_examples/poplog/main.go @@ -5,8 +5,8 @@ "math/rand" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { diff --git a/_examples/quietMode/go.mod b/_examples/quietMode/go.mod index 03d30bb..246f3df 100644 --- a/_examples/quietMode/go.mod +++ b/_examples/quietMode/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/quietMode/main.go b/_examples/quietMode/main.go index 3d1b3cb..4c953d5 100644 --- a/_examples/quietMode/main.go +++ b/_examples/quietMode/main.go @@ -7,8 +7,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) var quietMode bool diff --git a/_examples/remove/go.mod b/_examples/remove/go.mod index 48bee75..d48ed71 100644 --- a/_examples/remove/go.mod +++ b/_examples/remove/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/remove/main.go b/_examples/remove/main.go index ab8d90d..d67d360 100644 --- a/_examples/remove/main.go +++ b/_examples/remove/main.go @@ -6,8 +6,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { diff --git a/_examples/reverseBar/go.mod b/_examples/reverseBar/go.mod index 8e07e8c..7c7eed0 100644 --- a/_examples/reverseBar/go.mod +++ b/_examples/reverseBar/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/reverseBar/main.go b/_examples/reverseBar/main.go index 23450cc..14a13be 100644 --- a/_examples/reverseBar/main.go +++ b/_examples/reverseBar/main.go @@ -6,8 +6,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { @@ -19,9 +19,13 @@ for i := 0; i < numBars; i++ { name := fmt.Sprintf("Bar#%d:", i) + bs := mpb.BarStyle() + if i == 1 { + // reverse Bar#1 + bs = bs.Tip("<").Reverse() + } bar := p.Add(int64(total), - // reverse Bar#1 - mpb.NewBarFillerPick("", i == 1), + mpb.NewBarFiller(bs), mpb.PrependDecorators( // simple name decorator decor.Name(name), diff --git a/_examples/singleBar/go.mod b/_examples/singleBar/go.mod index 6cd0933..d74dd07 100644 --- a/_examples/singleBar/go.mod +++ b/_examples/singleBar/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/singleBar/main.go b/_examples/singleBar/main.go index f0ba8ea..f0b87a3 100644 --- a/_examples/singleBar/main.go +++ b/_examples/singleBar/main.go @@ -4,8 +4,8 @@ "math/rand" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { @@ -17,7 +17,7 @@ // adding a single bar, which will inherit container's width bar := p.Add(int64(total), // progress bar filler with customized style - mpb.NewBarFiller("╢▌▌░╟"), + mpb.NewBarFiller(mpb.BarStyle().Lbound("╢").Filler("▌").Tip("▌").Padding("░").Rbound("╟")), mpb.PrependDecorators( // display our name with one space on the right decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight}), diff --git a/_examples/spinTipBar/go.mod b/_examples/spinTipBar/go.mod new file mode 100644 index 0000000..98f55ac --- /dev/null +++ b/_examples/spinTipBar/go.mod @@ -0,0 +1,5 @@ +module github.com/vbauerster/mpb/_examples/spinTipBar + +go 1.14 + +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/spinTipBar/main.go b/_examples/spinTipBar/main.go new file mode 100644 index 0000000..51aeb10 --- /dev/null +++ b/_examples/spinTipBar/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "math/rand" + "time" + + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" +) + +func main() { + // initialize progress container, with custom width + p := mpb.New(mpb.WithWidth(80)) + + total := 100 + name := "Single Bar:" + bar := p.Add(int64(total), + mpb.NewBarFiller(mpb.BarStyle().Tip(`-`, `\`, `|`, `/`)), + mpb.PrependDecorators(decor.Name(name)), + mpb.AppendDecorators(decor.Percentage()), + ) + // simulating some work + max := 100 * time.Millisecond + for i := 0; i < total; i++ { + time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) + bar.Increment() + } + // wait for our bar to complete and flush + p.Wait() +} diff --git a/_examples/spinnerBar/go.mod b/_examples/spinnerBar/go.mod index 4f28efb..75b4888 100644 --- a/_examples/spinnerBar/go.mod +++ b/_examples/spinnerBar/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/spinnerBar/main.go b/_examples/spinnerBar/main.go index 7867037..bf3c8db 100644 --- a/_examples/spinnerBar/main.go +++ b/_examples/spinnerBar/main.go @@ -6,8 +6,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { @@ -26,7 +26,7 @@ var bar *mpb.Bar if i == 0 { bar = p.Add(int64(total), - mpb.NewBarFiller("╢▌▌░╟"), + mpb.NewBarFiller(mpb.BarStyle().Lbound("╢").Filler("▌").Tip("▌").Padding("░").Rbound("╟")), mpb.PrependDecorators( // simple name decorator decor.Name(name), @@ -41,7 +41,7 @@ ) } else { bar = p.Add(int64(total), - mpb.NewSpinnerFiller(spinnerStyle, mpb.SpinnerOnMiddle), + mpb.NewBarFiller(mpb.SpinnerStyle(spinnerStyle...)), mpb.PrependDecorators( // simple name decorator decor.Name(name), diff --git a/_examples/spinnerDecorator/go.mod b/_examples/spinnerDecorator/go.mod index 4bb0416..84dcf8e 100644 --- a/_examples/spinnerDecorator/go.mod +++ b/_examples/spinnerDecorator/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/spinnerDecorator/main.go b/_examples/spinnerDecorator/main.go index 03fcd72..4a64409 100644 --- a/_examples/spinnerDecorator/main.go +++ b/_examples/spinnerDecorator/main.go @@ -6,8 +6,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { diff --git a/_examples/stress/go.mod b/_examples/stress/go.mod index a7f5409..ee0641f 100644 --- a/_examples/stress/go.mod +++ b/_examples/stress/go.mod @@ -2,4 +2,4 @@ go 1.14 -require github.com/vbauerster/mpb/v6 v6.0.3 +require github.com/vbauerster/mpb/v7 v7.0.3 diff --git a/_examples/stress/main.go b/_examples/stress/main.go index 1dd199f..86198a7 100644 --- a/_examples/stress/main.go +++ b/_examples/stress/main.go @@ -6,8 +6,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) const ( diff --git a/_examples/suppressBar/go.mod b/_examples/suppressBar/go.mod index 0d10445..61f139c 100644 --- a/_examples/suppressBar/go.mod +++ b/_examples/suppressBar/go.mod @@ -3,6 +3,6 @@ go 1.14 require ( - github.com/mattn/go-runewidth v0.0.10 - github.com/vbauerster/mpb/v6 v6.0.3 + github.com/mattn/go-runewidth v0.0.13 + github.com/vbauerster/mpb/v7 v7.0.3 ) diff --git a/_examples/suppressBar/main.go b/_examples/suppressBar/main.go index f3dfc56..7dc38c0 100644 --- a/_examples/suppressBar/main.go +++ b/_examples/suppressBar/main.go @@ -9,8 +9,8 @@ "time" "github.com/mattn/go-runewidth" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func main() { diff --git a/bar.go b/bar.go index f18ef96..ed6c73e 100644 --- a/bar.go +++ b/bar.go @@ -12,7 +12,7 @@ "github.com/acarl005/stripansi" "github.com/mattn/go-runewidth" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7/decor" ) // Bar represents a progress bar. @@ -390,12 +390,6 @@ } func (s *bState) draw(stat decor.Statistics) io.Reader { - if !s.trimSpace { - stat.AvailableWidth -= 2 - s.bufB.WriteByte(' ') - defer s.bufB.WriteByte(' ') - } - nlr := strings.NewReader("\n") tw := stat.AvailableWidth for _, d := range s.pDecorators { @@ -403,10 +397,16 @@ stat.AvailableWidth -= runewidth.StringWidth(stripansi.Strip(str)) s.bufP.WriteString(str) } - if stat.AvailableWidth <= 0 { + if stat.AvailableWidth < 1 { trunc := strings.NewReader(runewidth.Truncate(stripansi.Strip(s.bufP.String()), tw, "…")) s.bufP.Reset() - return io.MultiReader(trunc, s.bufB, nlr) + return io.MultiReader(trunc, nlr) + } + + if !s.trimSpace && stat.AvailableWidth > 1 { + stat.AvailableWidth -= 2 + s.bufB.WriteByte(' ') + defer s.bufB.WriteByte(' ') } tw = stat.AvailableWidth @@ -415,7 +415,7 @@ stat.AvailableWidth -= runewidth.StringWidth(stripansi.Strip(str)) s.bufA.WriteString(str) } - if stat.AvailableWidth <= 0 { + if stat.AvailableWidth < 1 { trunc := strings.NewReader(runewidth.Truncate(stripansi.Strip(s.bufA.String()), tw, "…")) s.bufA.Reset() return io.MultiReader(s.bufP, s.bufB, trunc, nlr) diff --git a/bar_filler.go b/bar_filler.go index c8cedaa..a69087c 100644 --- a/bar_filler.go +++ b/bar_filler.go @@ -3,7 +3,7 @@ import ( "io" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7/decor" ) // BarFiller interface. @@ -14,13 +14,16 @@ // // Default implementations can be obtained via: // -// func NewBarFiller(style string) BarFiller -// func NewBarFillerRev(style string) BarFiller -// func NewBarFillerPick(style string, rev bool) BarFiller -// func NewSpinnerFiller(style []string, alignment SpinnerAlignment) BarFiller +// func NewBarFiller(BarStyle()) BarFiller +// func NewBarFiller(SpinnerStyle()) BarFiller // type BarFiller interface { Fill(w io.Writer, reqWidth int, stat decor.Statistics) +} + +// BarFillerBuilder interface. +type BarFillerBuilder interface { + Build() BarFiller } // BarFillerFunc is function type adapter to convert function into BarFiller. @@ -29,3 +32,8 @@ func (f BarFillerFunc) Fill(w io.Writer, reqWidth int, stat decor.Statistics) { f(w, reqWidth, stat) } + +// NewBarFiller constructs a BarFiller from provided BarFillerBuilder. +func NewBarFiller(b BarFillerBuilder) BarFiller { + return b.Build() +} diff --git a/bar_filler_bar.go b/bar_filler_bar.go index 1c339e9..e30d492 100644 --- a/bar_filler_bar.go +++ b/bar_filler_bar.go @@ -1,191 +1,219 @@ package mpb import ( - "bytes" "io" - "unicode/utf8" - + + "github.com/acarl005/stripansi" "github.com/mattn/go-runewidth" - "github.com/rivo/uniseg" - "github.com/vbauerster/mpb/v6/decor" - "github.com/vbauerster/mpb/v6/internal" + "github.com/vbauerster/mpb/v7/decor" + "github.com/vbauerster/mpb/v7/internal" ) const ( - rLeft = iota - rFill - rTip - rSpace - rRight - rRevTip - rRefill + iLbound = iota + iRbound + iFiller + iRefiller + iPadding + components ) -// BarDefaultStyle is a style for rendering a progress bar. -// It consist of 7 ordered runes: -// -// '1st rune' stands for left boundary rune -// -// '2nd rune' stands for fill rune -// -// '3rd rune' stands for tip rune -// -// '4th rune' stands for space rune -// -// '5th rune' stands for right boundary rune -// -// '6th rune' stands for reverse tip rune -// -// '7th rune' stands for refill rune -// -const BarDefaultStyle string = "[=>-]<+" - -type barFiller struct { - format [][]byte - rwidth []int - tip []byte - refill int64 - reverse bool - flush func(io.Writer, *space, [][]byte) -} - -type space struct { - space []byte - rwidth int - count int -} - -// NewBarFiller returns a BarFiller implementation which renders a -// progress bar in regular direction. If style is empty string, -// BarDefaultStyle is applied. To be used with `*Progress.Add(...) -// *Bar` method. -func NewBarFiller(style string) BarFiller { - return newBarFiller(style, false) -} - -// NewBarFillerRev returns a BarFiller implementation which renders a -// progress bar in reverse direction. If style is empty string, -// BarDefaultStyle is applied. To be used with `*Progress.Add(...) -// *Bar` method. -func NewBarFillerRev(style string) BarFiller { - return newBarFiller(style, true) -} - -// NewBarFillerPick pick between regular and reverse BarFiller implementation -// based on rev param. To be used with `*Progress.Add(...) *Bar` method. -func NewBarFillerPick(style string, rev bool) BarFiller { - return newBarFiller(style, rev) -} - -func newBarFiller(style string, rev bool) BarFiller { - bf := &barFiller{ - format: make([][]byte, len(BarDefaultStyle)), - rwidth: make([]int, len(BarDefaultStyle)), - reverse: rev, - } - bf.parse(BarDefaultStyle) - if style != "" && style != BarDefaultStyle { - bf.parse(style) +// BarStyleComposer interface. +type BarStyleComposer interface { + BarFillerBuilder + Lbound(string) BarStyleComposer + Rbound(string) BarStyleComposer + Filler(string) BarStyleComposer + Refiller(string) BarStyleComposer + Padding(string) BarStyleComposer + Tip(...string) BarStyleComposer + Reverse() BarStyleComposer +} + +type bFiller struct { + components [components]*component + tip struct { + count uint + frames []*component + } + flush func(dst io.Writer, filling, padding [][]byte) +} + +type component struct { + width int + bytes []byte +} + +type barStyle struct { + lbound string + rbound string + filler string + refiller string + padding string + tip []string + rev bool +} + +// BarStyle constructs default bar style which can be altered via +// BarStyleComposer interface. +func BarStyle() BarStyleComposer { + return &barStyle{ + lbound: "[", + rbound: "]", + filler: "=", + refiller: "+", + padding: "-", + tip: []string{">"}, + } +} + +func (s *barStyle) Lbound(bound string) BarStyleComposer { + s.lbound = bound + return s +} + +func (s *barStyle) Rbound(bound string) BarStyleComposer { + s.rbound = bound + return s +} + +func (s *barStyle) Filler(filler string) BarStyleComposer { + s.filler = filler + return s +} + +func (s *barStyle) Refiller(refiller string) BarStyleComposer { + s.refiller = refiller + return s +} + +func (s *barStyle) Padding(padding string) BarStyleComposer { + s.padding = padding + return s +} + +func (s *barStyle) Tip(tip ...string) BarStyleComposer { + if len(tip) != 0 { + s.tip = append(s.tip[:0], tip...) + } + return s +} + +func (s *barStyle) Reverse() BarStyleComposer { + s.rev = true + return s +} + +func (s *barStyle) Build() BarFiller { + bf := new(bFiller) + if s.rev { + bf.flush = func(dst io.Writer, filling, padding [][]byte) { + flush(dst, padding, filling) + } + } else { + bf.flush = flush + } + bf.components[iLbound] = &component{ + width: runewidth.StringWidth(stripansi.Strip(s.lbound)), + bytes: []byte(s.lbound), + } + bf.components[iRbound] = &component{ + width: runewidth.StringWidth(stripansi.Strip(s.rbound)), + bytes: []byte(s.rbound), + } + bf.components[iFiller] = &component{ + width: runewidth.StringWidth(stripansi.Strip(s.filler)), + bytes: []byte(s.filler), + } + bf.components[iRefiller] = &component{ + width: runewidth.StringWidth(stripansi.Strip(s.refiller)), + bytes: []byte(s.refiller), + } + bf.components[iPadding] = &component{ + width: runewidth.StringWidth(stripansi.Strip(s.padding)), + bytes: []byte(s.padding), + } + bf.tip.frames = make([]*component, len(s.tip)) + for i, t := range s.tip { + bf.tip.frames[i] = &component{ + width: runewidth.StringWidth(stripansi.Strip(t)), + bytes: []byte(t), + } } return bf } -func (s *barFiller) parse(style string) { - if !utf8.ValidString(style) { - panic("invalid bar style") - } - srcFormat := make([][]byte, len(BarDefaultStyle)) - srcRwidth := make([]int, len(BarDefaultStyle)) - i := 0 - for gr := uniseg.NewGraphemes(style); i < len(BarDefaultStyle) && gr.Next(); i++ { - srcFormat[i] = gr.Bytes() - srcRwidth[i] = runewidth.StringWidth(gr.Str()) - } - copy(s.format, srcFormat[:i]) - copy(s.rwidth, srcRwidth[:i]) - if s.reverse { - s.tip = s.format[rRevTip] - s.flush = reverseFlush - } else { - s.tip = s.format[rTip] - s.flush = regularFlush - } -} - -func (s *barFiller) Fill(w io.Writer, reqWidth int, stat decor.Statistics) { - width := internal.CheckRequestedWidth(reqWidth, stat.AvailableWidth) - brackets := s.rwidth[rLeft] + s.rwidth[rRight] +func (s *bFiller) Fill(w io.Writer, width int, stat decor.Statistics) { + width = internal.CheckRequestedWidth(width, stat.AvailableWidth) + brackets := s.components[iLbound].width + s.components[iRbound].width if width < brackets { return } // don't count brackets as progress width -= brackets - w.Write(s.format[rLeft]) - defer w.Write(s.format[rRight]) - - cwidth := int(internal.PercentageRound(stat.Total, stat.Current, width)) - space := &space{ - space: s.format[rSpace], - rwidth: s.rwidth[rSpace], - count: width - cwidth, - } - - index, refill := 0, 0 - bb := make([][]byte, cwidth) - - if cwidth > 0 && cwidth != width { - bb[index] = s.tip - cwidth -= s.rwidth[rTip] - index++ - } - - if stat.Refill > 0 { - refill = int(internal.PercentageRound(stat.Total, int64(stat.Refill), width)) - if refill > cwidth { - refill = cwidth - } - cwidth -= refill - } - - for cwidth > 0 { - bb[index] = s.format[rFill] - cwidth -= s.rwidth[rFill] - index++ - } - - for refill > 0 { - bb[index] = s.format[rRefill] - refill -= s.rwidth[rRefill] - index++ - } - - if cwidth+refill < 0 || space.rwidth > 1 { - buf := new(bytes.Buffer) - s.flush(buf, space, bb[:index]) - io.WriteString(w, runewidth.Truncate(buf.String(), width, "…")) - return - } - - s.flush(w, space, bb) -} - -func regularFlush(w io.Writer, space *space, bb [][]byte) { - for i := len(bb) - 1; i >= 0; i-- { - w.Write(bb[i]) - } - for space.count > 0 { - w.Write(space.space) - space.count -= space.rwidth - } -} - -func reverseFlush(w io.Writer, space *space, bb [][]byte) { - for space.count > 0 { - w.Write(space.space) - space.count -= space.rwidth - } - for i := 0; i < len(bb); i++ { - w.Write(bb[i]) - } -} + w.Write(s.components[iLbound].bytes) + defer w.Write(s.components[iRbound].bytes) + + curWidth := int(internal.PercentageRound(stat.Total, stat.Current, width)) + refWidth, filled := 0, curWidth + filling := make([][]byte, 0, curWidth) + + if curWidth > 0 && curWidth != width { + tipFrame := s.tip.frames[s.tip.count%uint(len(s.tip.frames))] + filling = append(filling, tipFrame.bytes) + curWidth -= tipFrame.width + s.tip.count++ + } + + if stat.Refill > 0 && curWidth > 0 { + refWidth = int(internal.PercentageRound(stat.Total, int64(stat.Refill), width)) + if refWidth > curWidth { + refWidth = curWidth + } + curWidth -= refWidth + } + + for curWidth > 0 && curWidth >= s.components[iFiller].width { + filling = append(filling, s.components[iFiller].bytes) + curWidth -= s.components[iFiller].width + if s.components[iFiller].width == 0 { + break + } + } + + for refWidth > 0 && refWidth >= s.components[iRefiller].width { + filling = append(filling, s.components[iRefiller].bytes) + refWidth -= s.components[iRefiller].width + if s.components[iRefiller].width == 0 { + break + } + } + + filled -= curWidth + refWidth + padWidth := width - filled + padding := make([][]byte, 0, padWidth) + for padWidth > 0 && padWidth >= s.components[iPadding].width { + padding = append(padding, s.components[iPadding].bytes) + padWidth -= s.components[iPadding].width + if s.components[iPadding].width == 0 { + break + } + } + + for padWidth > 0 { + padding = append(padding, []byte("…")) + padWidth-- + } + + s.flush(w, filling, padding) +} + +func flush(dst io.Writer, filling, padding [][]byte) { + for i := len(filling) - 1; i >= 0; i-- { + dst.Write(filling[i]) + } + for i := 0; i < len(padding); i++ { + dst.Write(padding[i]) + } +} diff --git a/bar_filler_spinner.go b/bar_filler_spinner.go index 0817b19..58ae1c5 100644 --- a/bar_filler_spinner.go +++ b/bar_filler_spinner.go @@ -4,62 +4,84 @@ "io" "strings" + "github.com/acarl005/stripansi" "github.com/mattn/go-runewidth" - "github.com/vbauerster/mpb/v6/decor" - "github.com/vbauerster/mpb/v6/internal" + "github.com/vbauerster/mpb/v7/decor" + "github.com/vbauerster/mpb/v7/internal" ) -// SpinnerAlignment enum. -type SpinnerAlignment int - -// SpinnerAlignment kinds. const ( - SpinnerOnLeft SpinnerAlignment = iota - SpinnerOnMiddle - SpinnerOnRight + positionLeft = 1 + iota + positionRight ) -// SpinnerDefaultStyle is a style for rendering a spinner. -var SpinnerDefaultStyle = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"} - -type spinnerFiller struct { - frames []string - count uint - alignment SpinnerAlignment +// SpinnerStyleComposer interface. +type SpinnerStyleComposer interface { + BarFillerBuilder + PositionLeft() SpinnerStyleComposer + PositionRight() SpinnerStyleComposer } -// NewSpinnerFiller returns a BarFiller implementation which renders -// a spinner. If style is nil or zero length, SpinnerDefaultStyle is -// applied. To be used with `*Progress.Add(...) *Bar` method. -func NewSpinnerFiller(style []string, alignment SpinnerAlignment) BarFiller { - if len(style) == 0 { - style = SpinnerDefaultStyle - } - filler := &spinnerFiller{ - frames: style, - alignment: alignment, - } - return filler +type sFiller struct { + count uint + position uint + frames []string } -func (s *spinnerFiller) Fill(w io.Writer, reqWidth int, stat decor.Statistics) { - width := internal.CheckRequestedWidth(reqWidth, stat.AvailableWidth) +type spinnerStyle struct { + position uint + frames []string +} + +// SpinnerStyle constructs default spinner style which can be altered via +// SpinnerStyleComposer interface. +func SpinnerStyle(frames ...string) SpinnerStyleComposer { + ss := new(spinnerStyle) + if len(frames) != 0 { + ss.frames = append(ss.frames, frames...) + } else { + ss.frames = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"} + } + return ss +} + +func (s *spinnerStyle) PositionLeft() SpinnerStyleComposer { + s.position = positionLeft + return s +} + +func (s *spinnerStyle) PositionRight() SpinnerStyleComposer { + s.position = positionRight + return s +} + +func (s *spinnerStyle) Build() BarFiller { + sf := &sFiller{ + position: s.position, + frames: s.frames, + } + return sf +} + +func (s *sFiller) Fill(w io.Writer, width int, stat decor.Statistics) { + width = internal.CheckRequestedWidth(width, stat.AvailableWidth) frame := s.frames[s.count%uint(len(s.frames))] - frameWidth := runewidth.StringWidth(frame) + frameWidth := runewidth.StringWidth(stripansi.Strip(frame)) if width < frameWidth { return } - switch rest := width - frameWidth; s.alignment { - case SpinnerOnLeft: + rest := width - frameWidth + switch s.position { + case positionLeft: io.WriteString(w, frame+strings.Repeat(" ", rest)) - case SpinnerOnMiddle: + case positionRight: + io.WriteString(w, strings.Repeat(" ", rest)+frame) + default: str := strings.Repeat(" ", rest/2) + frame + strings.Repeat(" ", rest/2+rest%2) io.WriteString(w, str) - case SpinnerOnRight: - io.WriteString(w, strings.Repeat(" ", rest)+frame) } s.count++ } diff --git a/bar_option.go b/bar_option.go index e359c11..46b7de0 100644 --- a/bar_option.go +++ b/bar_option.go @@ -4,8 +4,8 @@ "bytes" "io" - "github.com/vbauerster/mpb/v6/decor" - "github.com/vbauerster/mpb/v6/internal" + "github.com/vbauerster/mpb/v7/decor" + "github.com/vbauerster/mpb/v7/internal" ) // BarOption is a func option to alter default behavior of a bar. diff --git a/bar_test.go b/bar_test.go index 1f0067c..59d9f88 100644 --- a/bar_test.go +++ b/bar_test.go @@ -10,8 +10,8 @@ "time" "unicode/utf8" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func TestBarCompleted(t *testing.T) { @@ -61,9 +61,9 @@ total := 100 till := 30 - refillRune, _ := utf8.DecodeLastRuneInString(mpb.BarDefaultStyle) - - bar := p.AddBar(int64(total), mpb.BarFillerTrim()) + refiller := "+" + + bar := p.Add(int64(total), mpb.NewBarFiller(mpb.BarStyle().Refiller(refiller)), mpb.BarFillerTrim()) bar.SetRefill(int64(till)) bar.IncrBy(till) @@ -76,7 +76,7 @@ p.Wait() wantBar := fmt.Sprintf("[%s%s]", - strings.Repeat(string(refillRune), till-1), + strings.Repeat(refiller, till-1), strings.Repeat("=", total-till-1), ) @@ -143,22 +143,29 @@ func TestBarStyle(t *testing.T) { var buf bytes.Buffer customFormat := "╢▌▌░╟" + runes := []rune(customFormat) total := 80 p := mpb.New(mpb.WithWidth(total), mpb.WithOutput(&buf)) - bar := p.Add(int64(total), mpb.NewBarFiller(customFormat), mpb.BarFillerTrim()) - - for i := 0; i < total; i++ { - bar.Increment() - time.Sleep(10 * time.Millisecond) - } - - p.Wait() - - runes := []rune(customFormat) - wantBar := fmt.Sprintf("%s%s%s", + bs := mpb.BarStyle() + bs.Lbound(string(runes[0])) + bs.Filler(string(runes[1])) + bs.Tip(string(runes[2])) + bs.Padding(string(runes[3])) + bs.Rbound(string(runes[4])) + bar := p.Add(int64(total), mpb.NewBarFiller(bs), mpb.BarFillerTrim()) + + for i := 0; i < total; i++ { + bar.Increment() + time.Sleep(10 * time.Millisecond) + } + + p.Wait() + + wantBar := fmt.Sprintf("%s%s%s%s", string(runes[0]), - strings.Repeat(string(runes[1]), total-2), - string(runes[len(runes)-1]), + strings.Repeat(string(runes[1]), total-3), + string(runes[2]), + string(runes[4]), ) got := string(getLastLine(buf.Bytes())) @@ -247,6 +254,57 @@ } } +func TestDecorStatisticsAvailableWidth(t *testing.T) { + td1 := func(s decor.Statistics) string { + if s.AvailableWidth != 80 { + t.Errorf("expected AvailableWidth %d got %d\n", 80, s.AvailableWidth) + } + return fmt.Sprintf("\x1b[31;1;4m%s\x1b[0m", strings.Repeat("0", 20)) + } + checkDone := make(chan struct{}) + td2 := func(s decor.Statistics) string { + defer func() { + checkDone <- struct{}{} + }() + if s.AvailableWidth != 40 { + t.Errorf("expected AvailableWidth %d got %d\n", 40, s.AvailableWidth) + } + return "" + } + total := 100 + down := make(chan struct{}) + p := mpb.New( + mpb.WithWidth(100), + mpb.WithShutdownNotifier(down), + mpb.WithOutput(ioutil.Discard), + ) + bar := p.AddBar(int64(total), + mpb.BarFillerTrim(), + mpb.PrependDecorators( + decor.Name(strings.Repeat("0", 20)), + decor.Any(td1), + ), + mpb.AppendDecorators( + decor.Name(strings.Repeat("0", 20)), + decor.Any(td2), + ), + ) + go func() { + for { + select { + case <-checkDone: + bar.Abort(false) + case <-down: + return + } + } + }() + for !bar.Completed() { + bar.Increment() + } + p.Wait() +} + func panicDecorator(panicMsg string, cond func(decor.Statistics) bool) decor.Decorator { return decor.Any(func(st decor.Statistics) string { if cond(st) { diff --git a/barbench_test.go b/barbench_test.go index 76beece..ab1d602 100644 --- a/barbench_test.go +++ b/barbench_test.go @@ -4,7 +4,7 @@ "io/ioutil" "testing" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7/decor" ) func BenchmarkIncrSingleBar(b *testing.B) { diff --git a/container_option.go b/container_option.go index b92c757..e4254f6 100644 --- a/container_option.go +++ b/container_option.go @@ -6,7 +6,7 @@ "sync" "time" - "github.com/vbauerster/mpb/v6/internal" + "github.com/vbauerster/mpb/v7/internal" ) // ContainerOption is a func option to alter default behavior of a bar diff --git a/cwriter/util_zos.go b/cwriter/util_zos.go new file mode 100644 index 0000000..b7d67fc --- /dev/null +++ b/cwriter/util_zos.go @@ -0,0 +1,7 @@ +// +build zos + +package cwriter + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TCGETS diff --git a/decor/doc.go b/decor/doc.go index bfbb82e..4e42993 100644 --- a/decor/doc.go +++ b/decor/doc.go @@ -1,20 +1,19 @@ -// Package decor provides common decorators for "github.com/vbauerster/mpb/v6" module. -/* - Some decorators returned by this package might have a closure state. It is ok to use - decorators concurrently, unless you share the same decorator among multiple - *mpb.Bar instances. To avoid data races, create new decorator per *mpb.Bar instance. - - Don't: - - p := mpb.New() - name := decor.Name("bar") - p.AddBar(100, mpb.AppendDecorators(name)) - p.AddBar(100, mpb.AppendDecorators(name)) - - Do: - - p := mpb.New() - p.AddBar(100, mpb.AppendDecorators(decor.Name("bar1"))) - p.AddBar(100, mpb.AppendDecorators(decor.Name("bar2"))) -*/ +// Package decor provides common decorators for "github.com/vbauerster/mpb/v7" module. +// +// Some decorators returned by this package might have a closure state. It is ok to use +// decorators concurrently, unless you share the same decorator among multiple +// *mpb.Bar instances. To avoid data races, create new decorator per *mpb.Bar instance. +// +// Don't: +// +// p := mpb.New() +// name := decor.Name("bar") +// p.AddBar(100, mpb.AppendDecorators(name)) +// p.AddBar(100, mpb.AppendDecorators(name)) +// +// Do: +// +// p := mpb.New() +// p.AddBar(100, mpb.AppendDecorators(decor.Name("bar1"))) +// p.AddBar(100, mpb.AppendDecorators(decor.Name("bar2"))) package decor diff --git a/decor/percentage.go b/decor/percentage.go index f4922bb..2b0a7a9 100644 --- a/decor/percentage.go +++ b/decor/percentage.go @@ -5,7 +5,7 @@ "io" "strconv" - "github.com/vbauerster/mpb/v6/internal" + "github.com/vbauerster/mpb/v7/internal" ) type percentageType float64 diff --git a/decorators_test.go b/decorators_test.go index 99c49ce..788cc85 100644 --- a/decorators_test.go +++ b/decorators_test.go @@ -4,8 +4,8 @@ "sync" "testing" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func TestNameDecorator(t *testing.T) { diff --git a/draw_test.go b/draw_test.go index 2553ca6..dbd3bc0 100644 --- a/draw_test.go +++ b/draw_test.go @@ -9,14 +9,13 @@ func TestDraw(t *testing.T) { // key is termWidth testSuite := map[int][]struct { + style BarStyleComposer name string - style string total int64 current int64 refill int64 barWidth int trim bool - reverse bool want string }{ 0: { @@ -24,22 +23,22 @@ name: "t,c{60,20}", total: 60, current: 20, - want: "… ", - }, - { - name: "t,c{60,20}trim", - total: 60, - current: 20, - trim: true, want: "", }, + { + name: "t,c{60,20}trim", + total: 60, + current: 20, + trim: true, + want: "", + }, }, 1: { { name: "t,c{60,20}", total: 60, current: 20, - want: "… ", + want: "", }, { name: "t,c{60,20}trim", @@ -184,6 +183,57 @@ want: "[==================>---------------------------------------]", }, }, + 99: { + { + style: BarStyle().Lbound("[").Filler("の").Tip("だ").Padding("つ").Rbound("]"), + name: "[のだつ] t,c{99,1}", + total: 99, + current: 1, + want: " [だつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつ…] ", + }, + { + style: BarStyle().Lbound("[").Filler("の").Tip("だ").Padding("つ").Rbound("]"), + name: "[のだつ] t,c{99,2}", + total: 99, + current: 2, + want: " [だつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつ…] ", + }, + { + style: BarStyle().Lbound("[").Filler("の").Tip("だ").Padding("つ").Rbound("]"), + name: "[のだつ] t,c{99,3}", + total: 99, + current: 3, + want: " [だつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつ…] ", + }, + { + style: BarStyle().Lbound("[").Filler("の").Tip("だ").Padding("つ").Rbound("]"), + name: "[のだつ] t,c{99,4}", + total: 99, + current: 4, + want: " [のだつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつ…] ", + }, + { + style: BarStyle().Lbound("[").Filler("の").Tip("だ").Padding("つ").Rbound("]"), + name: "[のだつ] t,c{99,5}", + total: 99, + current: 5, + want: " [のだつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつ…] ", + }, + { + style: BarStyle().Lbound("[").Filler("の").Tip("だ").Padding("つ").Rbound("]"), + name: "[のだつ] t,c{99,6}", + total: 99, + current: 6, + want: " [ののだつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつ…] ", + }, + { + style: BarStyle().Lbound("[").Filler("の").Tip("だ").Padding("つ").Rbound("]").Reverse(), + name: "[のだつ] t,c{99,6}rev", + total: 99, + current: 6, + want: " […つつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつつだのの] ", + }, + }, 100: { { name: "t,c{100,0}", @@ -259,11 +309,11 @@ want: "[===============================>------------------------------------------------------------------]", }, { + style: BarStyle().Tip("<").Reverse(), name: "t,c{100,33}trim,rev", total: 100, current: 33, trim: true, - reverse: true, want: "[------------------------------------------------------------------<===============================]", }, { @@ -282,12 +332,12 @@ want: "[+++++++++++++++++++++++++++++++>------------------------------------------------------------------]", }, { + style: BarStyle().Tip("<").Reverse(), name: "t,c,r{100,33,33}trim,rev", total: 100, current: 33, refill: 33, trim: true, - reverse: true, want: "[------------------------------------------------------------------<+++++++++++++++++++++++++++++++]", }, { @@ -306,28 +356,21 @@ want: "[++++++++++++++++++++++++++++++++======>-----------------------------------------------------------]", }, { + style: BarStyle().Tip("<").Reverse(), name: "t,c,r{100,40,33},rev", total: 100, current: 40, refill: 33, - reverse: true, want: " [----------------------------------------------------------<=====++++++++++++++++++++++++++++++++] ", }, { + style: BarStyle().Tip("<").Reverse(), name: "t,c,r{100,40,33}trim,rev", total: 100, current: 40, refill: 33, trim: true, - reverse: true, want: "[-----------------------------------------------------------<======++++++++++++++++++++++++++++++++]", - }, - { - name: "[=の-] t,c{100,1}", - style: "[=の-]", - total: 100, - current: 1, - want: " [の---------------------------------------------------------------------------------------------…] ", }, }, 197: { @@ -346,7 +389,10 @@ var tmpBuf bytes.Buffer for tw, cases := range testSuite { for _, tc := range cases { - s := newTestState(tc.style, tc.reverse) + if tc.style == nil { + tc.style = BarStyle() + } + s := newTestState(NewBarFiller(tc.style)) s.reqWidth = tc.barWidth s.total = tc.total s.current = tc.current @@ -367,9 +413,9 @@ } } -func newTestState(style string, rev bool) *bState { +func newTestState(filler BarFiller) *bState { s := &bState{ - filler: NewBarFillerPick(style, rev), + filler: filler, bufP: new(bytes.Buffer), bufB: new(bytes.Buffer), bufA: new(bytes.Buffer), diff --git a/example_test.go b/example_test.go index 6f25c1b..cde49f8 100644 --- a/example_test.go +++ b/example_test.go @@ -7,8 +7,8 @@ "math/rand" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func Example() { @@ -20,7 +20,7 @@ // adding a single bar, which will inherit container's width bar := p.Add(int64(total), // progress bar filler with customized style - mpb.NewBarFiller("╢▌▌░╟"), + mpb.NewBarFiller(mpb.BarStyle().Lbound("╢").Filler("▌").Tip("▌").Padding("░").Rbound("╟")), mpb.PrependDecorators( // display our name with one space on the right decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight}), diff --git a/go.mod b/go.mod index 55d523e..22a2c65 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,10 @@ -module github.com/vbauerster/mpb/v6 +module github.com/vbauerster/mpb/v7 require ( - github.com/VividCortex/ewma v1.1.1 + github.com/VividCortex/ewma v1.2.0 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d - github.com/mattn/go-runewidth v0.0.10 - github.com/rivo/uniseg v0.2.0 - golang.org/x/sys v0.0.0-20210324051608-47abb6519492 + github.com/mattn/go-runewidth v0.0.13 + golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 ) go 1.14 diff --git a/go.sum b/go.sum index 4809b4a..59051bd 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,10 @@ -github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= -github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= +github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= +github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= -github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= -github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/internal/width.go b/internal/width.go index 216320f..7677e40 100644 --- a/internal/width.go +++ b/internal/width.go @@ -3,7 +3,7 @@ // CheckRequestedWidth checks that requested width doesn't overflow // available width func CheckRequestedWidth(requested, available int) int { - if requested <= 0 || requested >= available { + if requested < 1 || requested >= available { return available } return requested diff --git a/progress.go b/progress.go index 5a3f962..b2017f3 100644 --- a/progress.go +++ b/progress.go @@ -13,8 +13,8 @@ "sync" "time" - "github.com/vbauerster/mpb/v6/cwriter" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7/cwriter" + "github.com/vbauerster/mpb/v7/decor" ) const ( @@ -100,16 +100,16 @@ } // AddBar creates a bar with default bar filler. Different filler can -// be choosen and applied via `*Progress.Add(...) *Bar` method. +// be chosen and applied via `*Progress.Add(...) *Bar` method. func (p *Progress) AddBar(total int64, options ...BarOption) *Bar { - return p.Add(total, NewBarFiller(BarDefaultStyle), options...) + return p.Add(total, NewBarFiller(BarStyle()), options...) } // AddSpinner creates a bar with default spinner filler. Different -// filler can be choosen and applied via `*Progress.Add(...) *Bar` +// filler can be chosen and applied via `*Progress.Add(...) *Bar` // method. -func (p *Progress) AddSpinner(total int64, alignment SpinnerAlignment, options ...BarOption) *Bar { - return p.Add(total, NewSpinnerFiller(SpinnerDefaultStyle, alignment), options...) +func (p *Progress) AddSpinner(total int64, options ...BarOption) *Bar { + return p.Add(total, NewBarFiller(SpinnerStyle()), options...) } // Add creates a bar which renders itself by provided filler. diff --git a/progress_test.go b/progress_test.go index aa7a27d..86bfdaf 100644 --- a/progress_test.go +++ b/progress_test.go @@ -9,8 +9,8 @@ "testing" "time" - "github.com/vbauerster/mpb/v6" - "github.com/vbauerster/mpb/v6/decor" + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" ) func init() { diff --git a/proxyreader_test.go b/proxyreader_test.go index 71e036b..923226e 100644 --- a/proxyreader_test.go +++ b/proxyreader_test.go @@ -7,7 +7,7 @@ "strings" "testing" - "github.com/vbauerster/mpb/v6" + "github.com/vbauerster/mpb/v7" ) const content = `Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do