blob: 766060512cc0de5affbc9fdfa58bb7dcb9096f1b (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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))
}
}
|