Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Print usage on input without commands/args/flags #33

Open
lucagrulla opened this issue Jan 28, 2019 · 14 comments
Open

Print usage on input without commands/args/flags #33

lucagrulla opened this issue Jan 28, 2019 · 14 comments

Comments

@lucagrulla
Copy link

In the scenario of app invocation from terminal without any command/flags

> my-app

I'd expect the same output of:

> my-app --help

Instead, I have the error about the missing command.

my-app: error: expected one of "cmd1", "cmd2"

Is there a way/configuration to achieve my expected outcome?

The closest function I've found is kong.UsageOnError(), except it prints usage help for any error (when for any other type of error I'd expect to just print the specific error).

@alecthomas
Copy link
Owner

UsageOnError() is the solution, but what do you mean by "any other type of error"?

@lucagrulla
Copy link
Author

Hey,
Thanks for the quick response!

Let me give you an example to clarify:

if I type:

> my-app

I'd expect to see the equivalent of passing the --help flag.

If instead I type an invalid command:

> my-app invalid-command

I'd expect to print the specific error message about using an invalid command but not the full usage help.

Does it make sense?

The behaviour I'm describing is also present in kingpin.

@alecthomas
Copy link
Owner

For the latter case, Kong should be printing the error followed by the help for that command, right?

But I think what you're suggesting is that if nothing is passed at all, print the help, otherwise just print an error. Kong doesn't have that facility, no. I'm not particularly against it, but I also don't find it that useful. As a user, 99% of the time if I've made an error I want to be able to see the help so I know what to do to fix my error.

@lucagrulla
Copy link
Author

I see.

You are right that often people need the help regardless.

I am also thinking about scenarios where the error is more like a typo; in that case the user just really needs a reminder of the most similar command (something kong already does) rather than the full help that is somewhat visually distracting from the core message (the recommendation).

Anyway thanks for the clarification!
Fell free to close the issue if not relevant/keep if it's worthwhile exploring what we've been discussing.

@alecthomas
Copy link
Owner

I've subsequently moved the error message itself below the help, which makes it much clearer that there's an error.

@alecthomas
Copy link
Owner

Reopening because I think this would be useful as an option.

@hasheddan
Copy link
Contributor

@alecthomas is this a feature you would still consider supporting? I would be happy to add it if so

@alecthomas
Copy link
Owner

Sure, if you'd like to make it an option i'd happily merge it!

@hasheddan
Copy link
Contributor

Awesome, thanks! If you would like to reopen this I'll get started right away.

@Dids
Copy link

Dids commented Aug 7, 2022

There's a simple workaround for this:

// If running without any extra arguments, default to the --help flag
if len(os.Args) < 2 {
    os.Args = append(os.Args, "--help")
}

// Continue your usual Kong initialization
ctx := kong.Parse(&cli)
err := ctx.Run(&commands.Context{Debug: cli.Debug})
ctx.FatalIfErrorf(err)
...

@tommynanny
Copy link

Is there a way I can get the help message in the string, I need to print somewhere else instead of the stdout.

@alex-broad
Copy link
Contributor

The workaround is neat, but I'd like running the program without arguments to return an error code. I tried adding logic to record the fact the flag was added and then quit with an error, but it seems the .Parse() function is the one actually terminating the application - it never reaches the .Run() or .FatalIfErrorF() lines. I could probably do something with hooks but this is making the workaround pretty hacky - anyway, just a note for whomever picks this up that this might be a nice option to include too.

@Madoxen
Copy link

Madoxen commented May 13, 2024

@alex-broad I have other workaround for this:

func PrintHelp(parser *kong.Kong, opts kong.HelpOptions, args []string) error {
	//The kong help function is implemented in a BeforeReset hook, which
	//happens in parser.Parse method. The only thing we need for the help
	//printer is the command trace, so here we construct it
	ctx, err := kong.Trace(parser, args)
	if err != nil {
		return err
	}
	//Despite name looking like a constructor function this will actually
	//print out the help to stdout
	err = kong.DefaultHelpPrinter(opts, ctx)
	return err
}

You will need to create a parser struct first and then error check:

	parser := kong.Must(cli, opts...)
	kctx, err := parser.Parse(os.Args[1:])
        if err != nil {
            PrintHelp(parser, helpOpts, os.Args[1:])
        }

It's a bit more involved than simple kong.Parse function, but at least with this you can react to parsing errors and emit exit code accordingly.

@alex-broad
Copy link
Contributor

Thanks! I probably could have found that if I'd dug into kong.Parse() a bit 😅

It's good to make it visible for others though until there's a neater way to achieve this, thanks! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants