From 764a931dca59999138753d2b2830dc2fbaeb9ecb Mon Sep 17 00:00:00 2001 From: David Norton Date: Wed, 13 May 2026 17:45:26 -0500 Subject: [PATCH 1/2] wip --- cmd/exec.go | 24 ++++++++++++++++++------ cmd/exec_test.go | 7 ++++++- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/cmd/exec.go b/cmd/exec.go index 520fd42..51cb229 100644 --- a/cmd/exec.go +++ b/cmd/exec.go @@ -27,13 +27,19 @@ func stderrIsTerminal() bool { return term.IsTerminal(int(os.Stderr.Fd())) } -const progressBarWidth = 30 - var partialBlocks = []string{" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"} const lerpFactor = 0.15 const lerpSnap = 0.05 +func terminalWidth() int { + w, _, err := term.GetSize(int(os.Stderr.Fd())) + if err != nil || w <= 0 { + return 80 + } + return w +} + func lerp(display, target float64) float64 { display += (target - display) * lerpFactor if math.Abs(target-display) < lerpSnap { @@ -47,11 +53,17 @@ func renderProgressBar(displayStarted, displayCompleted float64, total int) stri return "" } - cEighths := int(displayCompleted * float64(progressBarWidth) * 8 / float64(total)) - sEighths := int(displayStarted * float64(progressBarWidth) * 8 / float64(total)) + suffix := fmt.Sprintf(" %d/%d complete", int(displayCompleted), total) + barWidth := terminalWidth() - 1 - len(suffix) + if barWidth < 10 { + barWidth = 10 + } + + cEighths := int(displayCompleted * float64(barWidth) * 8 / float64(total)) + sEighths := int(displayStarted * float64(barWidth) * 8 / float64(total)) var bar strings.Builder - for i := 0; i < progressBarWidth; i++ { + for i := 0; i < barWidth; i++ { left := i * 8 right := (i + 1) * 8 @@ -70,7 +82,7 @@ func renderProgressBar(displayStarted, displayCompleted float64, total int) stri } bar.WriteString(colorReset) - return fmt.Sprintf("\r\033[K %s %d/%d complete", bar.String(), int(displayCompleted), total) + return fmt.Sprintf("\r\033[K %s%s", bar.String(), suffix) } func clearProgress() { diff --git a/cmd/exec_test.go b/cmd/exec_test.go index 5f853bd..13f883e 100644 --- a/cmd/exec_test.go +++ b/cmd/exec_test.go @@ -308,7 +308,12 @@ func TestRenderProgressBar(t *testing.T) { func TestRenderProgressBarWidth(t *testing.T) { result := renderProgressBar(30, 30, 30) - assert.Equal(t, strings.Count(result, "█"), progressBarWidth, "fully completed bar should have exactly progressBarWidth full blocks") + suffix := fmt.Sprintf(" %d/%d complete", 30, 30) + expectedBarWidth := terminalWidth() - 1 - len(suffix) + if expectedBarWidth < 10 { + expectedBarWidth = 10 + } + assert.Equal(t, expectedBarWidth, strings.Count(result, "█"), "fully completed bar should fill the terminal width") assert.NotContains(t, result, "░") } From 2497799d14aff12a0c1f5aa051f39b3000a220ec Mon Sep 17 00:00:00 2001 From: David Norton Date: Wed, 13 May 2026 17:58:35 -0500 Subject: [PATCH 2/2] wip --- cmd/exec.go | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/cmd/exec.go b/cmd/exec.go index 51cb229..7013002 100644 --- a/cmd/exec.go +++ b/cmd/exec.go @@ -63,26 +63,45 @@ func renderProgressBar(displayStarted, displayCompleted float64, total int) stri sEighths := int(displayStarted * float64(barWidth) * 8 / float64(total)) var bar strings.Builder + currentColor := "" + setColor := func(c string) { + if c != currentColor { + bar.WriteString(c) + currentColor = c + } + } + for i := 0; i < barWidth; i++ { left := i * 8 right := (i + 1) * 8 switch { case right <= cEighths: - bar.WriteString(colorWhite + "█") + setColor(colorWhite) + bar.WriteString("█") case left >= sEighths: - bar.WriteString(colorGray + "░") + setColor(colorGray) + bar.WriteString("░") case left >= cEighths && right <= sEighths: - bar.WriteString(colorGray + "█") + setColor(colorGray) + bar.WriteString("█") case left < cEighths: - bar.WriteString(colorWhite + partialBlocks[cEighths-left]) + setColor(colorWhite) + bar.WriteString(partialBlocks[cEighths-left]) default: - bar.WriteString(colorGray + partialBlocks[sEighths-left]) + setColor(colorGray) + bar.WriteString(partialBlocks[sEighths-left]) } } bar.WriteString(colorReset) - return fmt.Sprintf("\r\033[K %s%s", bar.String(), suffix) + line := fmt.Sprintf(" %s%s", bar.String(), suffix) + // Pad to terminal width so \r overwrites the previous line without an erase sequence. + visibleLen := 1 + barWidth + len(suffix) + if pad := terminalWidth() - visibleLen; pad > 0 { + line += strings.Repeat(" ", pad) + } + return "\r" + line } func clearProgress() {