From 108f7bd66c4072e2d43b04931fdd0400982c6abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Fri, 22 May 2020 19:02:34 +0200 Subject: [PATCH] Dirty workaround to display helpful error message on mistyped subcommands When executing `gh pr re` (note the incomplete command name), Cobra would just display the help text for `gh pr` on standard output, exit with status 0, and not print any message that you have mistyped the "re" subcommand. Each part of this behavior is wrong. This workaround makes sure that the helpful error message is printed on stderr: $ gh pr re unknown command "re" for "gh pr" Did you mean this? reopen ready review However, the exit status is still 0, whereas it should be non-zero. Since `HelpFunc` does not return an error argument, we cannot trigger an error status from this workaround. --- command/root.go | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/command/root.go b/command/root.go index 6233be957..51c26afcc 100644 --- a/command/root.go +++ b/command/root.go @@ -249,9 +249,33 @@ func determineBaseRepo(apiClient *api.Client, cmd *cobra.Command, ctx context.Co return baseRepo, nil } -func rootHelpFunc(command *cobra.Command, s []string) { +func rootHelpFunc(command *cobra.Command, args []string) { if command != RootCmd { - cobraDefaultHelpFunc(command, s) + // Display helpful error message in case subcommand name was mistyped. + // This matches Cobra's behavior for root command, which Cobra + // confusingly doesn't apply to nested commands. + if command.Parent() == RootCmd && len(args) >= 2 { + if command.SuggestionsMinimumDistance <= 0 { + command.SuggestionsMinimumDistance = 2 + } + candidates := command.SuggestionsFor(args[1]) + + errOut := command.OutOrStderr() + fmt.Fprintf(errOut, "unknown command %q for %q\n", args[1], "gh "+args[0]) + + if len(candidates) > 0 { + fmt.Fprint(errOut, "\nDid you mean this?\n") + for _, c := range candidates { + fmt.Fprintf(errOut, "\t%s\n", c) + } + fmt.Fprint(errOut, "\n") + } + + oldOut := command.OutOrStdout() + command.SetOut(errOut) + defer command.SetOut(oldOut) + } + cobraDefaultHelpFunc(command, args) return }