From 470e777457d8b535f7970c761f3879067c742d13 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Fri, 18 Apr 2025 15:51:49 -0700 Subject: [PATCH 1/3] Adding NoPercent config option and Suffix / UpdateSuffix --- examples/simple/example.go | 6 ++++++ progressbar.go | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/examples/simple/example.go b/examples/simple/example.go index 73f6b15..94476cf 100644 --- a/examples/simple/example.go +++ b/examples/simple/example.go @@ -28,10 +28,13 @@ func main() { everyFlag := flag.Duration("every", 1*time.Second, "Print extra stuff every") noAnsiFlag := flag.Bool("no-ansi", false, "Disable ANSI escape codes (colors and cursor movement)") moveUpFlag := flag.Bool("moveup", false, "Demo in place move instead of writer") + noPercent := flag.Bool("no-percent", false, "Disable percent display") + noSuffix := flag.Bool("no-suffix", false, "Disable suffix display") flag.Parse() cfg := progressbar.DefaultConfig() cfg.UseColors = *colorFlag cfg.NoAnsi = *noAnsiFlag + cfg.NoPercent = *noPercent cfg.ScreenWriter = os.Stdout // For playground, defaults to stderr otherwise. pb := cfg.NewBar() w := pb.Writer() @@ -46,6 +49,9 @@ func main() { // exact number of 'pixels', just to demo every smooth step: n := pb.Width * 8 for i := 0; i <= n; i++ { + if !*noSuffix { + pb.UpdateSuffix(fmt.Sprintf(" %d/%d", i, n)) + } pb.Progress(100. * float64(i) / float64(n)) if moveUpMode && i%63 == 0 { pb.MoveCursorUp(1) diff --git a/progressbar.go b/progressbar.go index 580304e..aafd96b 100644 --- a/progressbar.go +++ b/progressbar.go @@ -60,6 +60,10 @@ type Config struct { Spinner bool // Prefix to show before the progress bar (can be updated while running using UpdatePrefix() or through Extra()). Prefix string + // Suffix to show after the percentage information on the bar (can be updated while running using UpdateSuffix()). + Suffix string + // If NoPercent is true, the percentage is not shown on the bar (if the default %.1f%% format is not adequate). + NoPercent bool // Minimum duration between updates (0 to update every time). UpdateInterval time.Duration // Option to avoid all ANSI sequences (useful for non terminal output/test/go playground), @@ -96,6 +100,14 @@ func (bar *Bar) UpdatePrefix(p string) { bar.out.Unlock() } +// UpdateSuffix changes the suffix while the progress bar is running. +// This is thread safe / acquires a shared lock to avoid issues on the output. +func (bar *Bar) UpdateSuffix(s string) { + bar.out.Lock() + bar.Suffix = s + bar.out.Unlock() +} + // Progress shows a progress bar percentage (0-100%). On the same line as current line, // so when call repeatedly it will overwrite/update itself. // Use MoveCursorUp to move up to update other lines as needed or use Writer() @@ -137,7 +149,9 @@ func (bar *Bar) Progress(progressPercent float64) { reset = "▻" // "◣" } barStr = color + strings.Repeat(Full, fullCount) + FractionalBlocks[remainder] + strings.Repeat(Space, spaceCount) + reset - progressPercentStr = fmt.Sprintf(" %.1f%%", progressPercent) + if !bar.NoPercent { + progressPercentStr = fmt.Sprintf(" %.1f%%", progressPercent) + } } spinner := "" if bar.Spinner { @@ -157,6 +171,7 @@ func (bar *Bar) Progress(progressPercent float64) { bar.out.buf = append(bar.out.buf, spinner...) bar.out.buf = append(bar.out.buf, barStr...) bar.out.buf = append(bar.out.buf, progressPercentStr...) + bar.out.buf = append(bar.out.buf, bar.Suffix...) bar.out.buf = append(bar.out.buf, extra...) bar.out.buf = append(bar.out.buf, bar.indexBasedMoveUp()...) // bar.out.buf = append(bar.out.buf, '\n') // Uncomment to debug/see all the incremental updates. From 9f95ca480e268831b465488351165a34575cc81d Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Fri, 18 Apr 2025 15:54:40 -0700 Subject: [PATCH 2/3] linter --- progressbar.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/progressbar.go b/progressbar.go index aafd96b..d8d7333 100644 --- a/progressbar.go +++ b/progressbar.go @@ -130,7 +130,7 @@ func (bar *Bar) Progress(progressPercent float64) { } barStr := "" progressPercentStr := "" - if progressPercent >= 0 && progressPercent <= 100 { + if progressPercent >= 0 && progressPercent <= 100 { //nolint:nestif // it's not that bad here width := float64(bar.Width) if width == 0 { width = DefaultWidth From 093ce509fc07dc0513c496b23025993cb6ef06da Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Fri, 18 Apr 2025 15:58:30 -0700 Subject: [PATCH 3/3] add more links to examples --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 0395da4..bce5200 100644 --- a/README.md +++ b/README.md @@ -133,3 +133,7 @@ If you have more advanced needs for TUI including raw mode input or readline, yo [github.com/fortio/terminal](https://github.com/fortio/terminal#terminal) And still use this for a progress bar part. + +It is used for instance in [github.com/fortio/fps's web mode progress update](https://github.com/fortio/fps#web-serving-fire-mode) + +And [grol](https://github.com/grol-io/grol#grol)'s multi file processing progress info (`make grol-tests`)