From cecb55b83a0bc38dd088d2d448281d253948cba1 Mon Sep 17 00:00:00 2001 From: Samarth Verma Date: Thu, 12 Mar 2026 15:55:50 -0400 Subject: [PATCH 1/2] Fix TTY timer alignment leaving stale suffix Signed-off-by: Samarth Verma --- cmd/display/tty.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cmd/display/tty.go b/cmd/display/tty.go index 0726ce27049..4f437e22d2a 100644 --- a/cmd/display/tty.go +++ b/cmd/display/tty.go @@ -339,6 +339,18 @@ func (w *ttyWriter) printWithDimensions(terminalWidth, terminalHeight int) { } } + // pad timers so they all have the same visible width + for i := range lines { + l := &lines[i] + if l.timer == "" { + continue + } + timerWidth := utf8.RuneCountInString(l.timer) + if timerWidth < timerLen { + l.timer = l.timer + strings.Repeat(" ", timerLen-timerWidth) + } + } + // shorten details/taskID to fit terminal width w.adjustLineWidth(lines, timerLen, terminalWidth) From d10613fc79383e932aca98ccce37c676b8423fb8 Mon Sep 17 00:00:00 2001 From: Samarth Verma Date: Fri, 20 Mar 2026 09:16:06 -0400 Subject: [PATCH 2/2] cmd/display: left-pad timers for right-aligned column Signed-off-by: Samarth Verma --- cmd/display/tty.go | 5 +++- cmd/display/tty_test.go | 61 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/cmd/display/tty.go b/cmd/display/tty.go index 4f437e22d2a..14dfc1c1f4b 100644 --- a/cmd/display/tty.go +++ b/cmd/display/tty.go @@ -347,7 +347,10 @@ func (w *ttyWriter) printWithDimensions(terminalWidth, terminalHeight int) { } timerWidth := utf8.RuneCountInString(l.timer) if timerWidth < timerLen { - l.timer = l.timer + strings.Repeat(" ", timerLen-timerWidth) + // Left-pad so the timer's right edge stays aligned on the terminal. + // This also prevents stale suffix characters from visually “sticking” + // when a previously-rendered timer was wider (e.g. "10.6s" -> "0.0s"). + l.timer = strings.Repeat(" ", timerLen-timerWidth) + l.timer } } diff --git a/cmd/display/tty_test.go b/cmd/display/tty_test.go index 0bbd35f2a29..3b1814a34c2 100644 --- a/cmd/display/tty_test.go +++ b/cmd/display/tty_test.go @@ -403,6 +403,67 @@ func TestPrintWithDimensions_PulledAndPullingWithLongIDs(t *testing.T) { } } +func TestPrintWithDimensions_TimerIsRightAligned(t *testing.T) { + w, buf := newTestWriter() + + base := time.Unix(0, 0) + + // Long timer: "10.6s" (length 5) + longTask := &task{ + ID: "task-long", + parents: make(map[string]struct{}), + startTime: base, + endTime: base.Add(10*time.Second + 600*time.Millisecond), + text: "Pulled", + status: api.Done, + spinner: NewSpinner(), + } + longTask.spinner.Stop() + w.tasks[longTask.ID] = longTask + w.ids = append(w.ids, longTask.ID) + + // Short timer: "0.0s" (length 4) + shortTask := &task{ + ID: "task-short", + parents: make(map[string]struct{}), + startTime: base, + endTime: base, + text: "Pulled", + status: api.Done, + spinner: NewSpinner(), + } + shortTask.spinner.Stop() + w.tasks[shortTask.ID] = shortTask + w.ids = append(w.ids, shortTask.ID) + + terminalWidth := 80 + w.printWithDimensions(terminalWidth, 24) + + // Strip ANSI codes from output and split by newline + stripped := stripAnsi(buf.String()) + lines := strings.Split(stripped, "\n") + + var nonEmptyLines []string + for _, line := range lines { + if strings.TrimSpace(line) != "" { + nonEmptyLines = append(nonEmptyLines, line) + } + } + + // Find the line containing the shorter timer. + var shortLine string + for _, line := range nonEmptyLines { + if strings.Contains(line, "0.0s") { + shortLine = line + break + } + } + assert.Assert(t, shortLine != "", "expected to find a rendered line containing \"0.0s\"") + assert.Assert(t, strings.HasSuffix(shortLine, "0.0s"), + "short timer should be left-padded (no trailing spaces after the timer); got: %q", + shortLine) +} + func TestLenAnsi(t *testing.T) { testCases := []struct { input string