Commit 6dae104c0c

6dae104c0cac2ca5eda9745619b92ae7a685b50f

parent: cf66fc30be

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-28 06:38 UTC

feedline: extract FeedLine.Sentence, dedupe runDashboard/runFeed

Ref #265

Layout: unified · split

internal/control/dashboard.go +2 −10
@@ -229,11 +229,7 @@ func runDashboard(c *Ctx, args []string) int {
229 lines := FeedLines(events) 229 lines := FeedLines(events)
230 activityRows := make([][]cell, len(lines)) 230 activityRows := make([][]cell, len(lines))
231 for i, l := range lines { 231 for i, l := range lines {
232 sentence := fmt.Sprintf("%s %s %s%s", l.Actor, l.Verb, l.Repo, l.Ref) 232 activityRows[i] = []cell{cAge(l.When), cFlex(l.Sentence())}
233 if l.Extra != "" {
234 sentence += " " + l.Extra
235 }
236 activityRows[i] = []cell{cAge(l.When), cFlex(sentence)}
237 } 233 }
238 section("recent activity:", []string{"WHEN", "EVENT"}, activityRows) 234 section("recent activity:", []string{"WHEN", "EVENT"}, activityRows)
239 235
@@ -352,11 +348,7 @@ func runFeed(c *Ctx, args []string) int {
352 return c.emitPage(p, ds, next, func(w io.Writer) { 348 return c.emitPage(p, ds, next, func(w io.Writer) {
353 tb := c.table(w, "WHEN", "EVENT") 349 tb := c.table(w, "WHEN", "EVENT")
354 for _, l := range lines { 350 for _, l := range lines {
355 sentence := fmt.Sprintf("%s %s %s%s", l.Actor, l.Verb, l.Repo, l.Ref) 351 tb.row(cAge(l.When), cFlex(l.Sentence()))
356 if l.Extra != "" {
357 sentence += " " + l.Extra
358 }
359 tb.row(cAge(l.When), cFlex(sentence))
360 } 352 }
361 tb.flush() 353 tb.flush()
362 }) 354 })
internal/control/feedline.go +10
@@ -27,6 +27,16 @@ type FeedLine struct {
27 sha string // the commit a build event fired on, for fold-matching 27 sha string // the commit a build event fired on, for fold-matching
28} 28}
29 29
30// Sentence renders the line the way the CLI shows it: "<actor> <verb>
31// <repo><ref>", with Extra (a label list) appended when set.
32func (l FeedLine) Sentence() string {
33 s := fmt.Sprintf("%s %s %s%s", l.Actor, l.Verb, l.Repo, l.Ref)
34 if l.Extra != "" {
35 s += " " + l.Extra
36 }
37 return s
38}
39
30// FeedLines turns stored events into readable lines. An unknown kind 40// FeedLines turns stored events into readable lines. An unknown kind
31// still shows: the feed says what happened even for events added later. 41// still shows: the feed says what happened even for events added later.
32// Build events on the same commit, adjacent in the input, fold into one 42// Build events on the same commit, adjacent in the input, fold into one
internal/control/feedline_test.go +12
@@ -231,3 +231,15 @@ func TestFeedLinesScheduleAbsorbsPushJobs(t *testing.T) {
231 t.Errorf("second line jobs: %+v, want the schedule and the push folded", lines[1].Jobs) 231 t.Errorf("second line jobs: %+v, want the schedule and the push folded", lines[1].Jobs)
232 } 232 }
233} 233}
234
235func TestFeedLineSentence(t *testing.T) {
236 l := FeedLine{Actor: "cmc", Verb: "opened issue", Repo: "krz/gitbay", Ref: "#1"}
237 if got, want := l.Sentence(), "cmc opened issue krz/gitbay#1"; got != want {
238 t.Errorf("Sentence() = %q, want %q", got, want)
239 }
240
241 l.Extra = "ops, security"
242 if got, want := l.Sentence(), "cmc opened issue krz/gitbay#1 ops, security"; got != want {
243 t.Errorf("Sentence() with Extra = %q, want %q", got, want)
244 }
245}