Skip to content

Utility library to provide support for commandline parsing

License

Notifications You must be signed in to change notification settings

hypfvieh/cli-parser

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build/Test JDK 11 Build/Test JDK 17

Maven Central Javadoc

cli-parser

Utility library to provide support for commandline parsing. It supports long (e.g. --my-option) and short options (e.g. -o) as well as Equal-Style options (.e.g. --my-option=value or -o=value).

It is possible to change the long and short option prefix (withLongOptPrefix(String) / withShortOptPrefix(String)). You can set various options to handle unknown, incomplete or wrong parameters.

You may register type converters (registerConverter(Class<T>, IValueConverter<T>)) to support conversion from input parameter value to a certain java type. The cli-parser provides some default converters for LocalDate/LocalDateTime/LocalTime, Double, Integer and Long.

Requirements

Requires Java 11 or higher.

Since 1.1.x no additional dependencies required. For cli-parser 1.0.x: Slf4j is required, should be used in 2.0.x (1.x should work as well).

Usage

Include dependency in your project

<dependency>
    <groupId>com.github.hypfvieh.cli</groupId>
    <artifactId>cli-parser</artifactId>
    <version>1.0.3</version>
</dependency>

Code Usage

Simple Usage looks like this:

public class MyMainApp {
  public void main(String[] _args) {
     CommandLine cl = new CommandLine()
                .addOption(CmdArgOption.builder(String.class)
                        .name("optionWithValue")
                        .shortName('f')
                        .required(true)
                        .description("descr")
                        .build())
                .parse(_args);

        Object val = cl.getArg('f');

        System.out.println("Given value was: " + val);
  }
}

Using options value type looks like this:

public class MyMainApp {
  public void main(String[] _args) {
     CmdArgOption<String> stringOption = CmdArgOption.builder(String.class)
                .name("optionWithValue")
                .shortName('f')
                .required(true)
                .description("descr")
                .build();
        CommandLine cl = new CommandLine()
                .addOption(stringOption)
                .parse(_args);

        String val = cl.getArg(stringOption);

        System.out.println("Given value was: " + val);
  }
}

Using options by name with a custom value type looks like this (since 1.0.1):

public class MyMainApp {
  public void main(String[] _args) {
     CommandLine cl = new CommandLine()
                .addOption(CmdArgOption.builder(String.class)
                        .name("optionWithValue")
                        .shortName('f')
                        .required(true)
                        .description("descr")
                        .build())
                .parse(_args);

        String byShortName = cl.getArg('f', String.class);
        String byLongName = cl.getArg("optionWithValue", String.class);

        System.out.println("Given value was: " + val);
  }
}

Checking if a option was used by long or shortname (since 1.0.2):

public class MyMainApp {
  public void main(String[] _args) {
     CommandLine cl = new CommandLine()
                .addOption(CmdArgOption.builder(String.class)
                        .name("optionWithValue")
                        .shortName('f')
                        .required(true)
                        .description("descr")
                        .build())
                .parse(_args);

        // it doesn't matter which variant (-f or --optionWithValue) was found in _args, both booleans will be true if any was found
        boolean optUsedByShortName = cl.hasArg('f'); // lookup by short name
        String optUsedByLongName = cl.getArg("optionWithValue"); // lookup by long name

        System.out.println("Option was set: " + optUsedByShortName); // this will print true if the option was set
  }
}

Using a map of predefined values for an option (since 1.0.4):
If the provided value is not any of the defined values, an exception is thrown.

Note:
Key type of the map is the type used for the CmdArgOption. Sort and compare behavior is based on the provided map. If you use Strings and want to compare case-insensitive use a TreeMap with proper comparator.

public class MyMainApp {
  public void main(String[] _args) {
     CommandLine cl = new CommandLine()
                .addOption(CmdArgOption.builder(String.class)
                        .name("optionWithPredefinedValue")
                        .shortName('f')
                        .required(true)
                        .description("descr")
                        .possibleValues(Map.of("foo", "The Foo Value", "bar", "The bar value"))
                        .build())
                .parse(_args);

        String optUsedByLongName = cl.getArg("optionWithPredefinedValue"); // lookup by long name
  }
}

Options

Options define a supported parameter with an optional value and return type. The CmdArgOption uses the builder pattern to create options.

Options can be repeatable which means that they may be used multiple times. When the option is repeatable and requires a value, all received values can be retrieved by using getArgs(Option<T>). If you use getArg(Option<T>) when multiple values are set, you will only get the first given value.

If an option is repeatable but does not take any value, you can get the "repeat count" by using getArgCount().

Options can be optional or required. If an option is required and is missing CommandLine will throw a RuntimeException (CommandLineException by default). The exception type can be changed on the CommandLine object.

Usage Formatter

CommandLine supports custom usage formatters. The Usage formatter will be used to print the supported options (required or optional) when the given command line was invalid.

If the default usage formatter does not fit your needs, you can implement your own. Create a class implementing IUsageFormatter and set a new instance of this formatter in your CommandLine object using withUsageFormatter(IUsageFormatter).

Help Formatter (since 1.0.4)

CommandLine supports custom help formatters. The HelpFormatter will be used when getArgumentHelp(String) is called on the CommandLine instance.

The default implementation will print the output in unix command line manor. It tries to handle linebreaks in descriptions and value descriptions and will care about indentation.

Here is an example output:

-f, --optionWithValue   Optional Option which takes a value
--optWithValue          Required long option which takes a value
-o                      Required option with only short option name and a value
-p, --optVal            Required repeatable option with value
-n, --noVal             Required Option without a value
                        This also has a long
                        description with multiple
                        linebreaks
-v, --possVal           Value with option list
                           'one': The First Value
                           'two': The Second Value
                                  This may have
                                  some sort of special
                                  meaning

Sample usage:

public class MyMainApp {
  public void main(String[] _args) {
     CommandLine cl = new CommandLine()
                .addOption(CmdArgOption.builder(String.class)
                        .name("anOption")
                        .shortName('o')
                        .required(true)
                        .description("My option description")
                        .build())
                .addOption(CmdArgOption.builder(String.class)
                        .name("help")
                        .shortName('h')
                        .description("Shows some help")
                        .build())
                .parse(_args);
        if (cl.hasArg('h')) {
                System.out.println("Here is some help for " + MyMainApp.class.getSimpleName());
                System.out.println(cl.getArgumentHelp(null));
                System.exit(1);
        }
  }
}

If the default help formatter does not fit your needs, you can implement your own. Create a class implementing IUsageFormatter and set a new instance of this formatter in your CommandLine object using withHelpFormatter(IUsageFormatter).

Creating Converters

To create a converter you have to create a class which implements IValueConverter. When conversion fails, the converter should throw a CommandLineException (or a subclass of it). The new convert has to be registered using registerConverter(Class<T>, IValueConverter<T>) on the CommandLine object.

Sample converter:

public class FloatConverter implements IValueConverter<Float> {

    @Override
    public Double convert(String _string) {
        try {
            return Float.parseFloat(_string);
        } catch (NumberFormatException _ex) {
            throw new CommandLineException("Unable to parse input '" + _string + "' as float");
        }
    }

}

Logging in Versions > 1.0.x

Since 1.1.0 cli-parser uses JPL (Java Platform Logger) a.k.a. System.Logger. If you want to see the logging of cli-parser in your logging framework, please add a proper bridge.

For Slf4j there is org.slf4j:slf4j-jdk-platform-logging which will redirect all JPL logging calls to Slf4j. Slf4j will then use the available logging backend (e.g. Logback) to do the actual logging.

For Log4j2 there is org.apache.logging.log4j:log4j-jpl to redirect JPL to Log4j - then Log4j will take care of logging.

About

Utility library to provide support for commandline parsing

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages