diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/tui/dashboard/overview.go | 41 | ||||
| -rw-r--r-- | internal/tui/dashboard/overview_test.go | 35 |
2 files changed, 73 insertions, 3 deletions
diff --git a/internal/tui/dashboard/overview.go b/internal/tui/dashboard/overview.go index 990e36d..5b8fab8 100644 --- a/internal/tui/dashboard/overview.go +++ b/internal/tui/dashboard/overview.go @@ -34,9 +34,10 @@ func renderOverview(snap *statsengine.Snapshot, width, height int) string { ) panelInner := panelInnerWidth(width) - latencySpark := renderOverviewSparkline("Latency:", snap.LatencySeriesNs(), panelInner) - gapSpark := renderOverviewSparkline("Gap:", snap.GapSeriesNs(), panelInner) - throughputSpark := renderOverviewSparkline("Throughput:", snap.ThroughputSeriesB(), panelInner) + labelWidth := maxLabelWidth("Latency:", "Gap:", "Throughput:") + latencySpark := renderOverviewSparklineAligned("Latency:", snap.LatencySeriesNs(), panelInner, labelWidth) + gapSpark := renderOverviewSparklineAligned("Gap:", snap.GapSeriesNs(), panelInner, labelWidth) + throughputSpark := renderOverviewSparklineAligned("Throughput:", snap.ThroughputSeriesB(), panelInner, labelWidth) topSyscalls := "Top syscalls: " + summarizeTopSyscalls(snap) topFiles := "Top files: " + summarizeTopFiles(snap) topProcesses := "Top processes: " + summarizeTopProcesses(snap) @@ -221,12 +222,46 @@ func summaryBoxInnerWidth(width int) int { func renderOverviewSparkline(label string, data []float64, panelInner int) string { w := panelInner - utf8.RuneCountInString(label) - 1 - sparklineSafetyMargin + if w > sparklineMaxWidth { + w = sparklineMaxWidth + } if w < 8 { w = 8 } return renderLabeledSparkline(label, data, w) } +func renderOverviewSparklineAligned(label string, data []float64, panelInner int, labelWidth int) string { + paddedLabel := padLabelRight(label, labelWidth) + w := panelInner - labelWidth - 1 - sparklineSafetyMargin + if w > sparklineMaxWidth { + w = sparklineMaxWidth + } + if w < 8 { + w = 8 + } + return renderLabeledSparkline(paddedLabel, data, w) +} + +func maxLabelWidth(labels ...string) int { + max := 0 + for _, label := range labels { + w := utf8.RuneCountInString(label) + if w > max { + max = w + } + } + return max +} + +func padLabelRight(label string, width int) string { + pad := width - utf8.RuneCountInString(label) + if pad <= 0 { + return label + } + return label + strings.Repeat(" ", pad) +} + func panelInnerWidth(width int) int { if width <= 0 { width = 80 diff --git a/internal/tui/dashboard/overview_test.go b/internal/tui/dashboard/overview_test.go index 706661e..9895490 100644 --- a/internal/tui/dashboard/overview_test.go +++ b/internal/tui/dashboard/overview_test.go @@ -129,3 +129,38 @@ func TestRenderOverviewSparklineHasSafetyMargin(t *testing.T) { t.Fatalf("expected sparkline width <= %d with safety margin, got %d", max, got) } } + +func TestRenderOverviewSparklineCapsWidth(t *testing.T) { + out := renderOverviewSparkline("Latency:", make([]float64, 120), 400) + lines := strings.Split(out, "\n") + if len(lines) != 2 { + t.Fatalf("expected 2-line sparkline, got %q", out) + } + if got := lipgloss.Width(lines[0]) - len("Latency: "); got > sparklineMaxWidth { + t.Fatalf("expected capped sparkline width <= %d, got %d", sparklineMaxWidth, got) + } +} + +func TestRenderOverviewSparklineAlignedUsesSameSparkStartColumn(t *testing.T) { + const panelInner = 80 + labelWidth := maxLabelWidth("Latency:", "Gap:", "Throughput:") + lat := renderOverviewSparklineAligned("Latency:", []float64{1, 2, 3}, panelInner, labelWidth) + gap := renderOverviewSparklineAligned("Gap:", []float64{1, 2, 3}, panelInner, labelWidth) + thr := renderOverviewSparklineAligned("Throughput:", []float64{1, 2, 3}, panelInner, labelWidth) + + latTop := strings.Split(lat, "\n")[0] + gapTop := strings.Split(gap, "\n")[0] + thrTop := strings.Split(thr, "\n")[0] + + prefix := strings.Repeat(" ", labelWidth-len("Latency:")) + if !strings.HasPrefix(latTop, "Latency:"+prefix+" ") { + t.Fatalf("unexpected latency prefix: %q", latTop) + } + prefix = strings.Repeat(" ", labelWidth-len("Gap:")) + if !strings.HasPrefix(gapTop, "Gap:"+prefix+" ") { + t.Fatalf("unexpected gap prefix: %q", gapTop) + } + if !strings.HasPrefix(thrTop, "Throughput: ") { + t.Fatalf("unexpected throughput prefix: %q", thrTop) + } +} |
