From 85251b17b179c5e68f89c560f0e38809961b6ebd Mon Sep 17 00:00:00 2001 From: Stefano Date: Sat, 20 Nov 2021 17:36:52 +0100 Subject: [PATCH] Add progress bar --- pb.go | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 pb.go diff --git a/pb.go b/pb.go new file mode 100644 index 0000000..f0688ab --- /dev/null +++ b/pb.go @@ -0,0 +1,114 @@ +package main + +import ( + "time" + + "github.com/vbauerster/mpb/v7" + "github.com/vbauerster/mpb/v7/decor" +) + +type ProgressState string + +const ( + ProgressStateConnecting ProgressState = "connecting" + ProgressStateDownloading ProgressState = "downloading" + ProgressStateCompleted ProgressState = "done" + ProgressStateAborted ProgressState = "aborted" +) + +type ProgressBar interface { + Increment(n int) + SetTotal(n int) + SetFileName(fileName string) + SetState(state ProgressState) +} + +type progressBarImpl struct { + progress *mpb.Progress + *mpb.Bar + state ProgressState + total int + fileName string +} + +const ( + barRefreshRateDefault = 180 * time.Millisecond + barWidthDefault = 40 + barMaxFileNameWidth = 35 +) + +func createMpbBar(p *mpb.Progress, total int, taskName string, state ProgressState, queueBar *mpb.Bar) *mpb.Bar { + displayName := cutStr(taskName, barMaxFileNameWidth) + + len := len(displayName) + if len != 0 { + displayName += ":" + len += 2 + } + + options := []mpb.BarOption{ + mpb.PrependDecorators( + decor.Name(displayName, decor.WC{W: len, C: decor.DidentRight}), + decor.Name(string(state), decor.WCSyncSpaceR), + decor.CountersKibiByte("% .2f / % .2f"), + ), + mpb.AppendDecorators( + decor.EwmaETA(decor.ET_STYLE_GO, 90), + decor.Name(" ] "), + decor.EwmaSpeed(decor.UnitKiB, "% .2f", 60), + ), + } + + if queueBar != nil { + options = append([]mpb.BarOption{ + mpb.BarQueueAfter(queueBar), + mpb.BarFillerClearOnComplete(), + }, options...) + } + + return p.Add(int64(total), + mpb.NewBarFiller(mpb.BarStyle().Rbound("|")), + options..., + ) +} + +func newProgressBarImpl() *progressBarImpl { + progress := mpb.New( + mpb.WithWidth(barWidthDefault), + mpb.WithRefreshRate(barRefreshRateDefault), + ) + + bar := createMpbBar(progress, 0, "", ProgressStateConnecting, nil) + return &progressBarImpl{ + progress: progress, + total: 0, + state: ProgressStateConnecting, + Bar: bar, + } +} + +func (bar *progressBarImpl) SetTotal(n int) { + bar.total = n + bar.Bar.SetTotal(int64(n), false) +} + +func (bar *progressBarImpl) SetFileName(fileName string) { + bar.fileName = fileName +} + +func (bar *progressBarImpl) Increment(n int) { + bar.IncrBy(n) + bar.DecoratorEwmaUpdate(time.Second) +} + +func (bar *progressBarImpl) SetState(state ProgressState) { + if state != bar.state { + oldBar := bar.Bar + bar.Bar = createMpbBar(bar.progress, bar.total, bar.fileName, state, bar.Bar) + oldBar.SetTotal(0, true) + } +} + +func NewProgressBar() ProgressBar { + return newProgressBarImpl() +}