summaryrefslogtreecommitdiffstats
path: root/progress.go
diff options
context:
space:
mode:
Diffstat (limited to 'progress.go')
-rw-r--r--progress.go63
1 files changed, 63 insertions, 0 deletions
diff --git a/progress.go b/progress.go
new file mode 100644
index 0000000..7660605
--- /dev/null
+++ b/progress.go
@@ -0,0 +1,63 @@
+package progress
+
+import (
+ "fmt"
+ "os"
+ "strings"
+ "time"
+
+ "gitlab.com/rhogenson/vecdeque"
+ "golang.org/x/term"
+)
+
+const measurements = 20
+
+type measurement struct {
+ t time.Time
+ i int
+}
+
+type Bar struct {
+ max int
+ measurements vecdeque.DQ[measurement]
+ cols int
+}
+
+func New(max int) *Bar {
+ b := &Bar{max: max}
+ b.measurements.Grow(measurements)
+ return b
+}
+
+func (b *Bar) Set(i int) {
+ if b.measurements.Len() == measurements {
+ b.measurements.PopFront()
+ }
+ b.measurements.PushBack(measurement{time.Now(), i})
+}
+
+func (b *Bar) Print() {
+ first := b.measurements.Get(0)
+ last := b.measurements.Get(b.measurements.Len() - 1)
+ deltaT := last.t.Sub(first.t)
+ delta := last.i - first.i
+ eta := time.Duration(-1)
+ if delta != 0 {
+ eta = time.Duration(float64(b.max-last.i) / float64(delta) * float64(deltaT))
+ }
+
+ if b.cols == 0 {
+ var err error
+ if b.cols, _, err = term.GetSize(int(os.Stderr.Fd())); err != nil {
+ fmt.Fprintf(os.Stderr, "Warning: unable to determine terminal size: %s\n", err)
+ }
+ } else {
+ p := last.i * b.cols / b.max
+ fmt.Fprintf(os.Stderr, "\033[2F\033[J%s>\n", strings.Repeat("=", max(p-1, 0)))
+ }
+ if eta < 0 {
+ fmt.Fprintln(os.Stderr, "ETA: calculating...")
+ } else {
+ fmt.Fprintf(os.Stderr, "ETA: %s\n", eta.Round(time.Second))
+ }
+}