Skip to content

Commit 8a3a83c

Browse files
committed
fix(cli): account for the page offset in the structured truncation note
The note fired whenever total > count, which misjudges the last page: --limit 20 --page 2 against a total of 40 printed "use --page for the rest" even though page 2 is the end. PrintList now takes the page size and computes hasMore as (page-1)*limit+count < total, so the note only appears when rows actually remain beyond the current page.
1 parent 5491bdf commit 8a3a83c

8 files changed

Lines changed: 51 additions & 13 deletions

File tree

internal/cli/alert.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func newAlertListCmd() *cobra.Command {
9393
if err != nil {
9494
return err
9595
}
96-
return ctx.PrintList(proj, nil, len(result.Items), page, int(result.Total))
96+
return ctx.PrintList(proj, nil, len(result.Items), page, limit, int(result.Total))
9797
}
9898

9999
cols := []output.Column{
@@ -106,7 +106,7 @@ func newAlertListCmd() *cobra.Command {
106106
{Header: "STARTED", Field: func(v any) string { return output.FormatTime(v.(flashduty.AlertItem).StartTime) }},
107107
}
108108

109-
return ctx.PrintList(result.Items, cols, len(result.Items), page, int(result.Total))
109+
return ctx.PrintList(result.Items, cols, len(result.Items), page, limit, int(result.Total))
110110
})
111111
},
112112
}

internal/cli/alert_event.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@ func newAlertEventListCmd() *cobra.Command {
102102
return err
103103
}
104104
noteProjectionShortening(cmd.ErrOrStderr(), note)
105-
return ctx.PrintList(proj, nil, len(result.Items), page, int(result.Total))
105+
return ctx.PrintList(proj, nil, len(result.Items), page, limit, int(result.Total))
106106
}
107107

108-
return ctx.PrintList(result.Items, cols, len(result.Items), page, int(result.Total))
108+
return ctx.PrintList(result.Items, cols, len(result.Items), page, limit, int(result.Total))
109109
})
110110
},
111111
}

internal/cli/audit.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func newAuditSearchCmd() *cobra.Command {
9696
}},
9797
}
9898

99-
return ctx.PrintList(result.Docs, cols, len(result.Docs), page, int(result.Total))
99+
return ctx.PrintList(result.Docs, cols, len(result.Docs), page, limit, int(result.Total))
100100
})
101101
},
102102
}

internal/cli/change.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func newChangeListCmd() *cobra.Command {
8686
{Header: "TIME", Field: func(v any) string { return output.FormatTime(v.(flashduty.ChangeItem).StartTime) }},
8787
}
8888

89-
return ctx.PrintList(result.Items, cols, len(result.Items), page, int(result.Total))
89+
return ctx.PrintList(result.Items, cols, len(result.Items), page, limit, int(result.Total))
9090
})
9191
},
9292
}

internal/cli/command.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,17 @@ func runCommand(cmd *cobra.Command, args []string, fn func(ctx *RunContext) erro
4949

5050
// PrintList prints items as a table and appends a "Showing N results (page P, total T)." footer.
5151
// In structured mode the footer is suppressed to keep stdout byte-pure for
52-
// jq/toon pipelines, so a page that doesn't cover the total is announced on
52+
// jq/toon pipelines, so a page with more rows beyond it is announced on
5353
// stderr instead — without it a consumer sees a partial page
54-
// (e.g. the default --limit 20 of a far larger total) as the whole set.
55-
func (ctx *RunContext) PrintList(items any, cols []output.Column, count, page, total int) error {
54+
// (e.g. the default --limit 20 of a far larger total) as the whole set. The
55+
// judgment accounts for the page offset: on the last page
56+
// ((page-1)*limit+count reaches total) there is no rest, so no note.
57+
func (ctx *RunContext) PrintList(items any, cols []output.Column, count, page, limit, total int) error {
5658
if err := ctx.Printer.Print(items, cols); err != nil {
5759
return err
5860
}
5961
if ctx.Structured() {
60-
if total > count {
62+
if (page-1)*limit+count < total {
6163
_, _ = fmt.Fprintf(ctx.Cmd.ErrOrStderr(), "note: showing %d of %d total results (page %d); raise --limit or use --page for the rest\n", count, total, page)
6264
}
6365
return nil

internal/cli/command_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,42 @@ func TestCommandAlertListStructuredAnnouncesTruncation(t *testing.T) {
16571657
t.Errorf("table mode already footers the count; no stderr note wanted, got:\n%s", stderrText)
16581658
}
16591659
})
1660+
1661+
// The truncation judgment must account for the page offset: page 2 of a
1662+
// total 40 at --limit 20 IS the last page — there is no rest, so no note.
1663+
fullPage := make([]any, 20)
1664+
for i := range fullPage {
1665+
fullPage[i] = alertRow()
1666+
}
1667+
lastPage := map[string]any{"items": fullPage, "total": 40}
1668+
1669+
t.Run("json last page prints no note", func(t *testing.T) {
1670+
saveAndResetGlobals(t)
1671+
stub := newGFStub(t)
1672+
stub.data = lastPage
1673+
1674+
_, stderrText, err := execCommandSplit("alert", "list", "--limit", "20", "--page", "2", "--output-format", "json")
1675+
if err != nil {
1676+
t.Fatalf("execCommandSplit: %v", err)
1677+
}
1678+
if strings.Contains(stderrText, "note: showing") {
1679+
t.Errorf("the last page has no rest to page for; no note wanted, got:\n%s", stderrText)
1680+
}
1681+
})
1682+
1683+
t.Run("json first page of same total still notes", func(t *testing.T) {
1684+
saveAndResetGlobals(t)
1685+
stub := newGFStub(t)
1686+
stub.data = lastPage
1687+
1688+
_, stderrText, err := execCommandSplit("alert", "list", "--limit", "20", "--page", "1", "--output-format", "json")
1689+
if err != nil {
1690+
t.Fatalf("execCommandSplit: %v", err)
1691+
}
1692+
if !strings.Contains(stderrText, "note: showing 20 of 40 total results (page 1)") {
1693+
t.Errorf("page 1 with a page 2 beyond it should announce itself on stderr, got:\n%s", stderrText)
1694+
}
1695+
})
16601696
}
16611697

16621698
// ---------------------------------------------------------------------------

internal/cli/incident.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,10 @@ func newIncidentListCmd() *cobra.Command {
142142
return err
143143
}
144144
noteProjectionShortening(cmd.ErrOrStderr(), note)
145-
return ctx.PrintList(proj, nil, len(result.Items), page, int(result.Total))
145+
return ctx.PrintList(proj, nil, len(result.Items), page, limit, int(result.Total))
146146
}
147147

148-
return ctx.PrintList(result.Items, incidentColumns(), len(result.Items), page, int(result.Total))
148+
return ctx.PrintList(result.Items, incidentColumns(), len(result.Items), page, limit, int(result.Total))
149149
})
150150
},
151151
}

internal/cli/insight.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ func newInsightIncidentsCmd() *cobra.Command {
131131
}},
132132
}
133133

134-
return ctx.PrintList(result.Items, cols, len(result.Items), page, int(result.Total))
134+
return ctx.PrintList(result.Items, cols, len(result.Items), page, limit, int(result.Total))
135135
})
136136
},
137137
}

0 commit comments

Comments
 (0)