diff --git a/internal/cli/blog.go b/internal/cli/blog.go index 81772cc..f0c1e1c 100644 --- a/internal/cli/blog.go +++ b/internal/cli/blog.go @@ -139,24 +139,15 @@ func newBlogShowCmd() *cobra.Command { } // blogNotFound builds the exit-3 error for a missing slug, with a did-you-mean -// hint when the gallery has a plausible neighbor. A failing suggestion fetch -// never masks the original not-found. Mirrors soulNotFound. +// hint when the gallery has a plausible neighbor. The entity is a "post" but it +// is listed under the `blog` command. See notFoundWithSuggestion. func blogNotFound(ctx context.Context, client *api.Client, slug string) error { - hint := "Run: positronick blog list" - if posts, err := client.Posts(ctx, ""); err == nil { - slugs := make([]string, len(posts)) - for i, post := range posts { - slugs[i] = post.Slug - } - if match := closestSlug(slug, slugs); match == slug { - // The list knows the slug but the detail fetch 404'd: an older server, - // not a typo — say so rather than suggesting the input back. - hint = "the server lists this post but could not return its details — positronick.com may be running an older API" - } else if match != "" { - hint = fmt.Sprintf("did you mean %q? %s", match, hint) - } + posts, err := client.Posts(ctx, "") + slugs := make([]string, len(posts)) + for i, post := range posts { + slugs[i] = post.Slug } - return output.NotFoundError(fmt.Sprintf("post %q not found", slug), hint) + return notFoundWithSuggestion("post", "blog", slug, slugs, err) } func renderBlogDetail(p *output.Printer, post *api.Post) { diff --git a/internal/cli/listing.go b/internal/cli/listing.go index 2979d6c..d680fd0 100644 --- a/internal/cli/listing.go +++ b/internal/cli/listing.go @@ -202,7 +202,7 @@ func listingNotFound(ctx context.Context, client *api.Client, listingType, slug for i, l := range listings { slugs[i] = l.Slug } - return notFoundWithSuggestion(listingType, slug, slugs, err) + return notFoundWithSuggestion(listingType, listingType, slug, slugs, err) } // renderListingDetail prints the human field view. For loops it also renders diff --git a/internal/cli/read.go b/internal/cli/read.go index 76d1582..c73a821 100644 --- a/internal/cli/read.go +++ b/internal/cli/read.go @@ -117,14 +117,17 @@ func applyLimit[T any](items []T, limit int) []T { } // notFoundWithSuggestion builds the exit-3 error for a slug the detail endpoint -// 404'd on, shared by `soul show` and `listing show`. When the catalog list -// holds a plausible neighbor it appends a did-you-mean hint; when the list -// holds the exact slug, the detail miss means the server is older than this CLI -// (no JSON detail endpoint yet), so it says that instead of suggesting the input -// back. A failing catalog fetch (fetchErr != nil) is ignored so it never masks -// the original not-found — the caller passes the fetch result verbatim. -func notFoundWithSuggestion(noun, slug string, catalog []string, fetchErr error) error { - hint := fmt.Sprintf("Run: positronick %s list", noun) +// 404'd on, shared by `soul show`, `listing show`, and `blog show`. noun names +// the entity in the message ("soul"/"post"); listCmd is the subcommand in the +// "Run: positronick list" hint — usually equal to noun, but `blog show` +// lists "post" entities under the `blog` command. When the catalog list holds a +// plausible neighbor it appends a did-you-mean hint; when the list holds the +// exact slug, the detail miss means the server is older than this CLI (no JSON +// detail endpoint yet), so it says that instead of suggesting the input back. A +// failing catalog fetch (fetchErr != nil) is ignored so it never masks the +// original not-found — the caller passes the fetch result verbatim. +func notFoundWithSuggestion(noun, listCmd, slug string, catalog []string, fetchErr error) error { + hint := fmt.Sprintf("Run: positronick %s list", listCmd) if fetchErr == nil { if match := closestSlug(slug, catalog); match == slug { hint = "the server lists this " + noun + " but could not return its details — positronick.com may be running an older API" diff --git a/internal/cli/soul.go b/internal/cli/soul.go index 1938dbb..a91998e 100644 --- a/internal/cli/soul.go +++ b/internal/cli/soul.go @@ -190,7 +190,7 @@ func soulNotFound(ctx context.Context, client *api.Client, slug string) error { for i, s := range souls { slugs[i] = s.Slug } - return notFoundWithSuggestion("soul", slug, slugs, err) + return notFoundWithSuggestion("soul", "soul", slug, slugs, err) } func renderSoulDetail(p *output.Printer, s *api.Soul) {