aboutsummaryrefslogtreecommitdiff
path: root/internal/progress/render.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-06-08 06:24:06 +0000
committerGravatar Runxi Yu2026-06-08 06:24:06 +0000
commite4cf4b6152bf05387828dda44bd73d7ec12a7ed6 (patch)
tree157e92eaabd9c910f9a83b53dc9c26754dcce12d /internal/progress/render.go
parentcommon/iowrap: Remove in favor of lgo (diff)
signatureNo signature
internal/progress: Add
Diffstat (limited to 'internal/progress/render.go')
-rw-r--r--internal/progress/render.go79
1 files changed, 79 insertions, 0 deletions
diff --git a/internal/progress/render.go b/internal/progress/render.go
new file mode 100644
index 00000000..f51852eb
--- /dev/null
+++ b/internal/progress/render.go
@@ -0,0 +1,79 @@
+package progress
+
+import (
+ "fmt"
+ "strings"
+ "time"
+
+ "lindenii.org/go/furgit/internal/utils"
+ "lindenii.org/go/lgo/fmt/humanize"
+ "lindenii.org/go/lgo/intconv"
+)
+
+func (meter *Meter) render(now time.Time, eol string) {
+ if meter.delay > 0 && now.Sub(meter.startedAt) < meter.delay && eol == "\r" {
+ return
+ }
+
+ meter.refreshThroughput(now)
+
+ counters := meter.renderCounters()
+
+ clear1 := 0
+ if len(counters) < meter.lastCounterW {
+ clear1 = meter.lastCounterW - len(counters) + 1
+ }
+
+ meter.lastCounterW = len(counters)
+
+ line := meter.title + ": " + counters
+ if clear1 > 0 {
+ line += strings.Repeat(" ", clear1)
+ }
+
+ line += eol
+
+ utils.BestEffortFprintf(meter.writer, "%s", line)
+
+ if meter.writer != nil {
+ _ = meter.writer.Flush()
+ }
+}
+
+func (meter *Meter) renderCounters() string {
+ if meter.total > 0 {
+ u, err := intconv.Uint64ToInt(meter.lastDone * 100 / meter.total)
+ if err != nil {
+ return "overflow"
+ // TODO
+ }
+
+ meter.lastPercent = u
+
+ return fmt.Sprintf("%3d%% (%d/%d)%s", meter.lastPercent, meter.lastDone, meter.total, meter.throughputSuffix)
+ }
+
+ return fmt.Sprintf("%d%s", meter.lastDone, meter.throughputSuffix)
+}
+
+func (meter *Meter) refreshThroughput(now time.Time) {
+ if !meter.throughput {
+ return
+ }
+
+ if meter.nextThroughput.After(now) && meter.throughputSuffix != "" {
+ return
+ }
+
+ for !now.Before(meter.nextThroughput) {
+ meter.nextThroughput = meter.nextThroughput.Add(throughputInterval)
+ }
+
+ elapsed := now.Sub(meter.startedAt)
+ if elapsed <= 0 {
+ return
+ }
+
+ rate := uint64(float64(meter.lastBytes) / elapsed.Seconds())
+ meter.throughputSuffix = ", " + humanize.Bytes(meter.lastBytes) + " | " + humanize.Bytes(rate) + "/s"
+}