From 4cba342aaec67ced332759edf58970d58528b910 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Fri, 12 Jan 2024 08:49:07 +0100 Subject: [PATCH 1/2] feat: Add the `WithUsage` function. --- args.go | 13 +++++++++++++ args_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/args.go b/args.go index ed1e70cea..08f92f1ce 100644 --- a/args.go +++ b/args.go @@ -129,3 +129,16 @@ func MatchAll(pargs ...PositionalArgs) PositionalArgs { func ExactValidArgs(n int) PositionalArgs { return MatchAll(ExactArgs(n), OnlyValidArgs) } + +// WithUsage wraps another PositionalArgs function. If the function fails +// (returns a non-nil error), the error is supplemented with the command's +// usage message, providing the user with the information required to run the +// command correctly. +func WithUsage(wrapped PositionalArgs) PositionalArgs { + return func(cmd *Command, args []string) error { + if err := wrapped(cmd, args); err != nil { + return fmt.Errorf("%w\n\n%s", err, cmd.UsageString()) + } + return nil + } +} diff --git a/args_test.go b/args_test.go index 90d174cce..077a2f3f2 100644 --- a/args_test.go +++ b/args_test.go @@ -539,3 +539,27 @@ func TestLegacyArgsSubcmdAcceptsArgs(t *testing.T) { t.Fatalf("Unexpected error: %v", err) } } + +// WithUsage + +func TestWithUsage(t *testing.T) { + c := getCommand(WithUsage(ExactArgs(1)), false) + + _, err := executeCommand(c /* no args */) + if err == nil { + t.Fatalf("Expected error, got nil") + } + + got, want := err.Error(), c.UsageString() + if !strings.Contains(got, want) { + t.Errorf("Expected error containing %q, got %q", want, got) + } +} + +func ExampleWithUsage() { + cmd := &Command{ + Use: "example ", + Args: WithUsage(ExactArgs(1)), + } + _ = cmd // ignore unused +} From 399779240ee4fd3565dfc8dd826b160c3e7e5734 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Fri, 12 Jan 2024 09:13:41 +0100 Subject: [PATCH 2/2] doc: Improve the `WithUsage` example. --- args_test.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/args_test.go b/args_test.go index 077a2f3f2..ec17fdc7c 100644 --- a/args_test.go +++ b/args_test.go @@ -560,6 +560,21 @@ func ExampleWithUsage() { cmd := &Command{ Use: "example ", Args: WithUsage(ExactArgs(1)), + Run: func(*Command, []string) { + panic("not reached") + }, } - _ = cmd // ignore unused + + cmd.SetArgs([]string{"1", "2"}) + err := cmd.Execute() + fmt.Print(err) + + // Output: + // accepts 1 arg(s), received 2 + // + // Usage: + // example [flags] + // + // Flags: + // -h, --help help for example }