From 97f083810f4699d51094937d30fbdb979dd61588 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 28 Feb 2024 12:10:17 -0600 Subject: [PATCH] chore: provide usage instruction for CLI argument failures (#12309) * chore: add usage to # cli arg failures --- cli/clibase/cmd.go | 15 +++++++++++++-- cli/errors.go | 14 ++++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/cli/clibase/cmd.go b/cli/clibase/cmd.go index 1830d75059..d1d03b45fd 100644 --- a/cli/clibase/cmd.go +++ b/cli/clibase/cmd.go @@ -562,6 +562,16 @@ func Chain(ms ...MiddlewareFunc) MiddlewareFunc { return chain(reversed...) } +func ShowUsageOnError(next HandlerFunc) HandlerFunc { + return func(i *Invocation) error { + err := next(i) + if err != nil { + return xerrors.Errorf("Usage: %s\nError: %w", i.Command.FullUsage(), err) + } + return nil + } +} + func RequireNArgs(want int) MiddlewareFunc { return RequireRangeArgs(want, want) } @@ -574,7 +584,8 @@ func RequireRangeArgs(start, end int) MiddlewareFunc { panic("start must be >= 0") } return func(next HandlerFunc) HandlerFunc { - return func(i *Invocation) error { + // ShowUsageOnError will add the command usage before the error message. + return ShowUsageOnError(func(i *Invocation) error { got := len(i.Args) switch { case start == end && got != start: @@ -614,7 +625,7 @@ func RequireRangeArgs(start, end int) MiddlewareFunc { default: return next(i) } - } + }) } } diff --git a/cli/errors.go b/cli/errors.go index ee12ca036a..cbcf4f2224 100644 --- a/cli/errors.go +++ b/cli/errors.go @@ -45,7 +45,8 @@ func (RootCmd) errorExample() *clibase.Cmd { apiError.(*codersdk.Error).Helper = "Have you tried turning it off and on again?" //nolint:errorlint,forcetypeassert - apiErrorNoHelper := apiError.(*codersdk.Error) + cpy := *apiError.(*codersdk.Error) + apiErrorNoHelper := &cpy apiErrorNoHelper.Helper = "" // Some flags @@ -94,7 +95,6 @@ func (RootCmd) errorExample() *clibase.Cmd { ) }, }, - { Use: "validation", Options: clibase.OptionSet{ @@ -114,6 +114,16 @@ func (RootCmd) errorExample() *clibase.Cmd { return nil }, }, + { + Use: "arg-required ", + Middleware: clibase.Chain( + clibase.RequireNArgs(1), + ), + Handler: func(i *clibase.Invocation) error { + _, _ = fmt.Fprint(i.Stdout, "Try running this without an argument\n") + return nil + }, + }, }, }