summaryrefslogtreecommitdiffstats
path: root/progress-bar.go
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2025-04-05 08:03:18 -0700
committerRose Hogenson <rosehogenson@posteo.net>2025-04-05 08:03:18 -0700
commit2fec8a20fb8f485f2107deb00d29c99dfdfbde47 (patch)
treedaf28f9b60a4af3266754fc92aeb8eb6f77d7426 /progress-bar.go
downloadprogress-bar-2fec8a20fb8f485f2107deb00d29c99dfdfbde47.tar.zst
Initial commit
Diffstat (limited to 'progress-bar.go')
-rw-r--r--progress-bar.go76
1 files changed, 76 insertions, 0 deletions
diff --git a/progress-bar.go b/progress-bar.go
new file mode 100644
index 0000000..0b1cefe
--- /dev/null
+++ b/progress-bar.go
@@ -0,0 +1,76 @@
+package main
+
+import (
+ "bytes"
+ "errors"
+ "flag"
+ "fmt"
+ "os"
+ "os/exec"
+ "strconv"
+ "strings"
+ "time"
+
+ "golang.org/x/term"
+)
+
+var n = flag.Duration("n", 2*time.Minute, "polling interval")
+
+func run() error {
+ cols, _, err := term.GetSize(int(os.Stdout.Fd()))
+ if err != nil {
+ return err
+ }
+ args := flag.Args()
+ if len(args) < 2 {
+ return errors.New("usage error")
+ }
+ maxStr := args[0]
+ maxVal, err := strconv.Atoi(maxStr)
+ if err != nil {
+ return fmt.Errorf("max: %s", err)
+ }
+ cmd := args[1:]
+ type measurement struct {
+ t time.Time
+ i int
+ }
+ var measurements []measurement
+ for i := 0; ; i++ {
+ outputBytes, err := exec.Command(cmd[0], cmd[1:]...).Output()
+ if err != nil {
+ fmt.Println(err)
+ continue
+ }
+ output, err := strconv.Atoi(string(bytes.TrimSuffix(outputBytes, []byte("\n"))))
+ if err != nil {
+ fmt.Println(err)
+ continue
+ }
+ p := output * cols / maxVal
+ if i > 0 {
+ fmt.Print("\033[2F\033[J")
+ }
+ fmt.Printf("%s>\n", strings.Repeat("=", max(p-1, 0)))
+ measurements = append(measurements, measurement{time.Now(), output})
+ if len(measurements) > 20 {
+ measurements = measurements[1:]
+ }
+ deltaT := measurements[len(measurements)-1].t.Sub(measurements[0].t)
+ delta := measurements[len(measurements)-1].i - measurements[0].i
+ if delta == 0 {
+ fmt.Println()
+ } else {
+ fmt.Printf("ETA: %s\n", time.Duration(float64(maxVal-output)/float64(delta)*float64(deltaT)).Round(time.Second))
+ }
+ time.Sleep(*n)
+ }
+}
+
+func main() {
+ flag.Parse()
+ if err := run(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}