From 9ca7be9f7351f7519368098ae83dd81e0669c09d Mon Sep 17 00:00:00 2001 From: Andrew Kallmeyer Date: Wed, 25 Aug 2021 19:24:55 -0700 Subject: [PATCH] Here it is! I wanted a progress the other night so I wrote this up. --- in.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 in.go diff --git a/in.go b/in.go new file mode 100644 index 0000000..a8e1432 --- /dev/null +++ b/in.go @@ -0,0 +1,66 @@ +// in is a commandline utility that sleeps for a specified amount of time +// while displaying a progress bar. +// +// Ex: in 2m30s && run_a_command +// +// Author: Andrew Kallmeyer +// Copyright 2021 Google LLC. +// SPDX-License-Identifier: Apache-2.0 +package main + +import ( + "os" + "fmt" + "time" + "strings" +) + +const ( + BarLen = 40 + BarFilled = '=' + BarEmpty = '-' + Step = time.Second +) + +const ClearLine = "\033[K" // ESC[K, the ECMA-48 CSI code for Erase line. See man 4 console_codes + +func progressbar(elapsed, total int64) string { + const realBarLen = BarLen-2 // to account for the [ and ] + + // Solve for progress: total / BarLen = elapsed / progress + progress := int(elapsed / (total / realBarLen)) + if progress < 0 || progress > realBarLen { + fmt.Fprintln(os.Stderr, "Bad miscaculation:", progress, elapsed, total, realBarLen) + os.Exit(2) + } + + var b strings.Builder + b.WriteRune('[') + for i := 0; i < progress; i+=1 { + b.WriteRune(BarFilled) + } + for i := 0; i < (realBarLen - progress); i+=1 { + b.WriteRune(BarEmpty) + } + b.WriteRune(']') + return b.String() +} + +func main() { + if len(os.Args) < 2 { + fmt.Fprintf(os.Stderr, "Usage example: %v 2m30s\n", os.Args[0]) + os.Exit(127) + } + sleeptime, err := time.ParseDuration(os.Args[1]) + if err != nil { + fmt.Fprintln(os.Stderr, "Invalid duration:", os.Args[1]) + os.Exit(1) + } + for elapsed := 0*time.Second; elapsed < sleeptime; elapsed += Step { + fmt.Fprintf(os.Stderr, "\r%s %v/%v%s", + progressbar(elapsed.Milliseconds(), sleeptime.Milliseconds()), + elapsed, sleeptime, ClearLine) + time.Sleep(Step) + } + fmt.Fprintf(os.Stderr, "\rDing!%s\n", ClearLine) +}