Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 7 additions & 16 deletions internal/cli/blog.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/listing.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 11 additions & 8 deletions internal/cli/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 <cmd> 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"
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/soul.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down