Skip to content

Commit 2e2c419

Browse files
committed
Show full task error on continuation lines below the task row
The inline error was hardcoded to 28 chars which was already tight inside the 48-char left pane. Instead, inject rowKindErrorLine rows in visibleRows() after each failed task, word-wrapping the full error to fit the available width. The task row itself no longer shows a truncated inline error.
1 parent dcab190 commit 2e2c419

1 file changed

Lines changed: 39 additions & 9 deletions

File tree

actions/view.go

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ const (
127127
rowKindNamespace // namespace path segment
128128
rowKindProjectHeader // project label when it has >1 group
129129
rowKindTask // selectable leaf
130+
rowKindErrorLine // non-selectable continuation line showing a task's error
130131
)
131132

132133
type treeRow struct {
@@ -593,13 +594,48 @@ func (m *actionsModel) updateCollapsed() {
593594
}
594595

595596
// visibleRows returns the rows that should be shown (honouring collapsed state).
597+
// Failed tasks have their error message injected as one or more rowKindErrorLine
598+
// rows immediately below the task row.
596599
func (m *actionsModel) visibleRows() []treeRow {
600+
leftW := 48
601+
if m.width > 0 && m.width < 80 {
602+
leftW = m.width / 2
603+
}
604+
597605
visible := make([]treeRow, 0, len(m.rows))
598606
for _, row := range m.rows {
599607
if row.kind != rowKindAction && m.collapsed[row.action] {
600608
continue
601609
}
602610
visible = append(visible, row)
611+
if row.kind == rowKindTask {
612+
e, ok := m.taskState[row.taskName]
613+
if !ok || e.state != actionFailed || e.err == nil {
614+
continue
615+
}
616+
// Indent: same as task row prefix (depth*2 spaces + cursor + icon+space)
617+
// but without cursor/icon — just depth*2 + 4 spaces so text aligns under the label.
618+
prefixLen := row.depth*2 + 4
619+
availW := leftW - prefixLen
620+
if availW < 10 {
621+
availW = 10
622+
}
623+
runes := []rune(e.err.Error())
624+
for len(runes) > 0 {
625+
n := availW
626+
if n > len(runes) {
627+
n = len(runes)
628+
}
629+
visible = append(visible, treeRow{
630+
kind: rowKindErrorLine,
631+
label: string(runes[:n]),
632+
depth: row.depth,
633+
taskName: row.taskName,
634+
action: row.action,
635+
})
636+
runes = runes[n:]
637+
}
638+
}
603639
}
604640
return visible
605641
}
@@ -1306,19 +1342,13 @@ func (m *actionsModel) renderTree(width, height int) []string {
13061342
case actionOK:
13071343
extra = actDimStyle.Render(" " + fmtActionDuration(e.elapsed))
13081344
case actionFailed:
1309-
msg := " FAILED"
1310-
if e.err != nil {
1311-
short := e.err.Error()
1312-
if len([]rune(short)) > 28 {
1313-
short = string([]rune(short)[:28]) + "…"
1314-
}
1315-
msg += ": " + short
1316-
}
1317-
extra = actFailStyle.Render(msg)
1345+
// Error text is shown on rowKindErrorLine rows injected by visibleRows.
13181346
}
13191347
}
13201348

13211349
line = indent + cursor + iconSty.Render(icon+" ") + labelSty.Render(label) + extra
1350+
case rowKindErrorLine:
1351+
line = strings.Repeat(" ", row.depth) + " " + actFailStyle.Render(row.label)
13221352
}
13231353
lines = append(lines, truncateANSILine(line, width))
13241354
}

0 commit comments

Comments
 (0)