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 {
229229 lines := FeedLines(events)
230230 activityRows := make([][]cell, len(lines))
231231 for i, l := range lines {
232 sentence := fmt.Sprintf("%s %s %s%s", l.Actor, l.Verb, l.Repo, l.Ref)
233 if l.Extra != "" {
234 sentence += " " + l.Extra
235 }
236 activityRows[i] = []cell{cAge(l.When), cFlex(sentence)}
232 activityRows[i] = []cell{cAge(l.When), cFlex(l.Sentence())}
237233 }
238234 section("recent activity:", []string{"WHEN", "EVENT"}, activityRows)
239235
@@ -352,11 +348,7 @@ func runFeed(c *Ctx, args []string) int {
352348 return c.emitPage(p, ds, next, func(w io.Writer) {
353349 tb := c.table(w, "WHEN", "EVENT")
354350 for _, l := range lines {
355 sentence := fmt.Sprintf("%s %s %s%s", l.Actor, l.Verb, l.Repo, l.Ref)
356 if l.Extra != "" {
357 sentence += " " + l.Extra
358 }
359 tb.row(cAge(l.When), cFlex(sentence))
351 tb.row(cAge(l.When), cFlex(l.Sentence()))
360352 }
361353 tb.flush()
362354 })
internal/control/feedline.go +10
@@ -27,6 +27,16 @@ type FeedLine struct {
2727 sha string // the commit a build event fired on, for fold-matching
2828}
2929
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
3040// FeedLines turns stored events into readable lines. An unknown kind
3141// still shows: the feed says what happened even for events added later.
3242// 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) {
231231 t.Errorf("second line jobs: %+v, want the schedule and the push folded", lines[1].Jobs)
232232 }
233233}
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}