summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-26 22:11:15 +0200
committerPaul Buetow <paul@buetow.org>2026-03-26 22:11:15 +0200
commitc8108deb77f1872e6a55925d5abf9c0ae12813c6 (patch)
treee6c0ae91926f0cf68c7dfb89ce46ab1d8facf933
parentc9d96d4c1918881f771165e97e71de49917d4181 (diff)
ask: align list header columns for task da6d3d36
-rw-r--r--internal/askcli/formatter.go92
-rw-r--r--internal/askcli/formatter_test.go44
2 files changed, 125 insertions, 11 deletions
diff --git a/internal/askcli/formatter.go b/internal/askcli/formatter.go
index 886e819..828588b 100644
--- a/internal/askcli/formatter.go
+++ b/internal/askcli/formatter.go
@@ -7,23 +7,93 @@ import (
)
func FormatTaskList(tasks []TaskExport) string {
+ widths := taskListWidthsFor(tasks)
var b strings.Builder
- io.WriteString(&b, "Urgency | Priority | UUID | Status | Tags | Description\n")
- io.WriteString(&b, strings.Repeat("-", 120)+"\n")
+ writeTaskListHeader(&b, widths)
+ writeTaskListSeparator(&b, widths)
for _, t := range tasks {
- tags := strings.Join(t.Tags, ",")
- if tags == "" {
- tags = "-"
- }
- desc := t.Description
- if len(desc) > 50 {
- desc = desc[:47] + "..."
- }
- fmt.Fprintf(&b, "%.1f | %s | %s | %s | %s | %s\n", t.Urgency, t.Priority, t.UUID, t.Status, tags, desc)
+ writeTaskListRow(&b, widths, t)
}
return b.String()
}
+type taskListWidths struct {
+ Urgency int
+ Priority int
+ UUID int
+ Status int
+ Tags int
+ Description int
+}
+
+func taskListWidthsFor(tasks []TaskExport) taskListWidths {
+ widths := taskListWidths{
+ Urgency: len("Urgency"),
+ Priority: len("Priority"),
+ UUID: len("UUID"),
+ Status: len("Status"),
+ Tags: len("Tags"),
+ Description: len("Description"),
+ }
+ for _, t := range tasks {
+ widths.Urgency = maxInt(widths.Urgency, len(fmt.Sprintf("%.1f", t.Urgency)))
+ widths.Priority = maxInt(widths.Priority, len(t.Priority))
+ widths.UUID = maxInt(widths.UUID, len(t.UUID))
+ widths.Status = maxInt(widths.Status, len(t.Status))
+ widths.Tags = maxInt(widths.Tags, len(formatTaskTags(t.Tags)))
+ widths.Description = maxInt(widths.Description, len(formatTaskDescription(t.Description)))
+ }
+ return widths
+}
+
+func writeTaskListHeader(b *strings.Builder, widths taskListWidths) {
+ fmt.Fprintf(b, "%-*s | %-*s | %-*s | %-*s | %-*s | %-*s\n",
+ widths.Urgency, "Urgency",
+ widths.Priority, "Priority",
+ widths.UUID, "UUID",
+ widths.Status, "Status",
+ widths.Tags, "Tags",
+ widths.Description, "Description",
+ )
+}
+
+func writeTaskListSeparator(b *strings.Builder, widths taskListWidths) {
+ total := widths.Urgency + widths.Priority + widths.UUID + widths.Status + widths.Tags + widths.Description + 15
+ io.WriteString(b, strings.Repeat("-", total)+"\n")
+}
+
+func writeTaskListRow(b *strings.Builder, widths taskListWidths, t TaskExport) {
+ fmt.Fprintf(b, "%-*s | %-*s | %-*s | %-*s | %-*s | %-*s\n",
+ widths.Urgency, fmt.Sprintf("%.1f", t.Urgency),
+ widths.Priority, t.Priority,
+ widths.UUID, t.UUID,
+ widths.Status, t.Status,
+ widths.Tags, formatTaskTags(t.Tags),
+ widths.Description, formatTaskDescription(t.Description),
+ )
+}
+
+func formatTaskTags(tags []string) string {
+ if len(tags) == 0 {
+ return "-"
+ }
+ return strings.Join(tags, ",")
+}
+
+func formatTaskDescription(desc string) string {
+ if len(desc) > 50 {
+ return desc[:47] + "..."
+ }
+ return desc
+}
+
+func maxInt(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+
func FormatTaskInfo(t TaskExport) string {
var b strings.Builder
fmt.Fprintf(&b, "UUID: %s\n", t.UUID)
diff --git a/internal/askcli/formatter_test.go b/internal/askcli/formatter_test.go
index 50d6ae3..adb1e6e 100644
--- a/internal/askcli/formatter_test.go
+++ b/internal/askcli/formatter_test.go
@@ -1,6 +1,7 @@
package askcli
import (
+ "fmt"
"strings"
"testing"
)
@@ -27,6 +28,49 @@ func TestFormatTaskList(t *testing.T) {
}
}
+func TestFormatTaskList_AlignsHeaderAndSeparator(t *testing.T) {
+ tasks := []TaskExport{
+ {
+ UUID: "uuid-short",
+ Description: "Short task",
+ Status: "pending",
+ Priority: "H",
+ Tags: []string{"cli"},
+ Urgency: 1.0,
+ },
+ {
+ UUID: "uuid-with-a-longer-value",
+ Description: strings.Repeat("x", 60),
+ Status: "completed",
+ Priority: "M",
+ Tags: []string{"agent", "cli"},
+ Urgency: 12.3,
+ },
+ }
+
+ output := FormatTaskList(tasks)
+ lines := strings.Split(strings.TrimSuffix(output, "\n"), "\n")
+ if len(lines) != 4 {
+ t.Fatalf("FormatTaskList produced %d lines, want 4: %q", len(lines), output)
+ }
+
+ widths := taskListWidthsFor(tasks)
+ wantHeader := fmt.Sprintf("%-*s | %-*s | %-*s | %-*s | %-*s | %-*s",
+ widths.Urgency, "Urgency",
+ widths.Priority, "Priority",
+ widths.UUID, "UUID",
+ widths.Status, "Status",
+ widths.Tags, "Tags",
+ widths.Description, "Description",
+ )
+ if lines[0] != wantHeader {
+ t.Fatalf("header = %q, want %q", lines[0], wantHeader)
+ }
+ if len(lines[1]) != len(wantHeader) {
+ t.Fatalf("separator length = %d, want %d", len(lines[1]), len(wantHeader))
+ }
+}
+
func TestFormatTaskInfo(t *testing.T) {
task := TaskExport{
UUID: "test-uuid",