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

Improve (shorter) error message on invalid input #480

Closed
remkop opened this issue Sep 13, 2018 · 2 comments
Closed

Improve (shorter) error message on invalid input #480

remkop opened this issue Sep 13, 2018 · 2 comments

Comments

@remkop
Copy link
Owner

remkop commented Sep 13, 2018

Improve the error message shown on invalid input:

  • print the command name before the error message
  • instead of showing the full usage help after the error message, show only the synopsis plus an optional help hint.

Example:

$ grep -d recurese sibling_crontabs_glob inventory/
grep: invalid argument ‘recurese’ for ‘--directories’
Valid arguments are:
  - ‘read’
  - ‘recurse’
  - ‘skip’
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.

The help hint should be configurable with something like @Command(invalidInputMessage = { “Try 'grep --help' for more information.” }).

Then, if invalidInputMessage is set, the default Exception handler would show only the synopsis followed by this message. If not set, the full usage help message is shown.

TBD: how to make this available to applications that do their own error handling? For example:

CommandLine cmd = new CommandLine(new App());
try {
    cmd.parseArgs(args);
} catch (ParseException invalidInput) {
    System.err.println(invalidInput.getMessage());
    System.err.println(cmd.getUsageSynopsis()); // TODO
    System.err.printf("Try '%s --help' for more information.%n", cmd.getCommandName());
}
@remkop
Copy link
Owner Author

remkop commented Jun 14, 2019

Update: from 4.0, the code that handles this lives in the default IParameterExceptionHandler.

Current implementation:

public int handleParseException(ParameterException ex, String[] args) {
    CommandLine cmd = ex.getCommandLine();
    DefaultExceptionHandler.internalHandleParseException(ex, cmd.getErr(), cmd.getColorScheme());
    return mappedExitCode(ex, cmd.getExitCodeExceptionMapper(), cmd.getCommandSpec().exitCodeOnInvalidInput());
}

...
    class DefaultExceptionHandler {
        static void internalHandleParseException(ParameterException ex, PrintWriter writer, Help.ColorScheme colorScheme) {
            writer.println(ex.getMessage());
            if (!UnmatchedArgumentException.printSuggestions(ex, writer)) {
                ex.getCommandLine().usage(writer, colorScheme);
            }
        }
    }
...
    private static int mappedExitCode(Throwable t, IExitCodeExceptionMapper mapper, int defaultExitCode) {
        try {
            return (mapper != null) ? mapper.getExitCode(t) : defaultExitCode;
        } catch (Exception ex) {
            ex.printStackTrace();
            return defaultExitCode;
        }
    }

@remkop
Copy link
Owner Author

remkop commented Jun 18, 2019

From 4.0, custom code to accomplish this would look something like this:

static class ShortErrorMessageHandler implements IParameterExceptionHandler {

    public int handleParseException(ParameterException ex, String[] args) {
        CommandLine cmd = ex.getCommandLine();
        PrintWriter writer = cmd.getErr();

        writer.println(ex.getMessage());
        UnmatchedArgumentException.printSuggestions(ex, writer);
        writer.print(cmd.getHelp().fullSynopsis()); // since 4.1

        CommandSpec spec = cmd.getCommandSpec();
        writer.printf("Try '%s --help' for more information.%n", spec.qualifiedName());

        return cmd.getExitCodeExceptionMapper() != null 
                    ? cmd.getExitCodeExceptionMapper().getExitCode(ex)
                    : spec.exitCodeOnInvalidInput();
    }
}

Install the custom handler like this:

new CommandLine(new MyApp())
    .setParameterExceptionHandler(new ShortErrorMessageHandler())
    .execute(args);

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

No branches or pull requests

1 participant