Module org.refcodes.cli

Package org.refcodes.cli

Getting started:

Consider you have a tool called "foo-bar" to be invoked with the below allowed argument combinations (syntax):

foo-bar [{ -a | -d }] -f <file>

"foo-bar" can be invoked either with an optional "-a" or with an optional "-d" switch, but not both of them at the same time, and a file "-f <file>" must be provided, else the passed arguments are rejected as not being valid.

Valid arguments would be:

Invalid arguments would be: This means that additional switches not supported are not valid. The parser detects such situations and you can print out a help message in such cases.

Construct your parser:

First build your syntax using Flages , Options and Conditions. You actually build the syntax tree for your command line tool's supported arguments:

Option<String> theFile = new StringOption( "-f", "--file", "file", "A file" ); Flag theAdd = new Flag( "-a", null, "Add the specified file" ); Flag theDelete = new Flag( "-d", null, "Delete the specified file" ); Condition theXor = new XorCondition( theAdd, theDelete ); Syntaxable theOptional = new OptionalCondition( theXor ); Condition theAnd = new AndCondition( theOptional, theFile ); ArgsParser theArgsParser = new ArgsParserImpl( theAnd ); theArgsParser.printUsage(); // theArgsParser.printHelp();

Using syntactic sugar

The [`TinyRestfulServer`](https://bitbucket.org/refcodes/funcodes-tinyrestful/raw /master/src/main/java/club/funcodes/tinyrestful/TinyRestfulServer.java) demo application uses `syntactic sugar` for setting up the command line arguments parser:

import static org.refcodes.cli.CliSugar.*; ... public static void main( String args[] ) { Option<Integer> theWidth = intOption( "-w", "--width", "width", "Sets the console width" ); Option<Integer> thePort = intOption( "-p", "--port", "port", "Sets the port for the server" ); Option<Integer> theMaxConns = intOption( "-c", "--connections", "connections", "Sets the number of max. connections" ); Option<String> theUsername = stringOption( "-u", "--user", "username", "The username for HTTP Basic-Authentication" ); Option<String> theSecret = stringOption( "-s", "--secret", "secret", "The password for HTTP Basic-Authentication" ); Flag theHelp = helpSwitch( "Shows this help" ); Condition theRootCondition = xor( and( thePort, optional( theMaxConns ), optional( and( theUsername, theSecret ) ), optional( theWidth ) ), theHelp ); ArgsParser theArgsParser = new ArgsParserImpl( theRootCondition ); theArgsParser.withSyntaxNotation( SyntaxNotation.REFCODES ); theArgsParser.withName( "TinyRestful" ).withTitle( "TINYRESTFUL" ).withCopyrightNote( "Copyright (c) by FUNCODES.CLUB, Munich, Germany." ).withLicenseNote( "Licensed under GNU General Public License, v3.0 and Apache License, v2.0" ); theArgsParser.withBannerFont( new FontImpl( FontFamily.DIALOG, FontStyle.BOLD, 14 ) ).withBannerFontPalette( AsciiColorPalette.MAX_LEVEL_GRAY.getPalette() ); theArgsParser.setDescription( "Tiny evil RESTful server. TinyRestfulServer makes heavy use of the REFCODES.ORG artifacts found together with the FUNCODES.CLUB sources at http://bitbucket.org/refcodes." ); List<? extends Operand<?>> theResult = theArgsParser.evalArgs( args ); ... } ...

Most obvious is the missing new statement for instantiating the parts of your command line parser as this is done by the statically imported methods. ### Under the hood As seen above, you pass your root Condition to the ArgsParser which then already can print out your command line tool's usage string:

Test (invoke) your parser:

In real live you would pass your main-method's args[] array to the parser. Now just for a test-run, pass a String array to your parser and let it parse it:

String[] args = new String[] { "-f", "someFile", "-d" }; List<? extends Operand<?>> theResult = theArgsParser.evalArgs( args ); File theConfigFile = new File( theFile.getValue() );

Now the leaves of your syntax tree are filled with the argument's values according to the syntax you have been setting up: Your StringOption instance aliased "theFile" now contains the value "someFile".

The "theResult" contains the parsed arguments for you to use in your business logic.

In case of argument rejection, a sub-type of the ArgsMismatchException is being thrown; actually one of the exceptions UnknownArgsException, AmbiguousArgsException, SuperfluousArgsException or ParseArgsException is being thrown, according to the cause of the rejection. So you can either catch the ArgsMismatchException or, if you need more details on the cause, the other sub-exceptions.

Syntaxable:

Syntaxable defines the methods at least required when building a command line arguments syntax tree for traversing the syntax tree; either for parsing command line arguments or for constructing the command line arguments syntax.

By providing various implementations of the Syntaxable's subclasses such as Operand, Option or Condition, a command line arguments syntax tree can be constructed. This syntax tree can be use to create a human readable (verbose) command line arguments syntax and to parse an array of command line arguments for determining the Operands', the Flages' or the Options' values.

Operand:

An Operand represents a value parsed from command line arguments. An Operand has a state which changes with each invocation of the ArgsParser.evalArgs(String[]) method.

It is recommended to put your Operand instance(s) at the end of your top Condition to enforce it to be the last Syntaxable(s) when parsing the command line arguments - this makes sure that any Options pick their option arguments so that the Operand(s) will correctly be left over for parsing command line argument(s); the Operand will not pick by mistake an Option argument.

Option:

An Option represents a command line option with the according option's value. An Option can be seen as a key/value(s) pair defined in the command line arguments parsed via the ArgsParser.evalArgs(String[]) method.

An Option has a state which changes with each invocation of the ArgsParser.evalArgs(String[]) method.

Flag:

A Flag is an Option with a Boolean state. Usually switches are just set or omitted in the command line arguments with no value provided; former representing a true status and latter representing a false status.

Operation:

The Operation is an argument representing a function or a method and is either provided or not provided as of Operation.isEnabled(). It must neither be prefixed with "-" nor with "--" in contrast to the Option or the Flag type.

Condition:

The Condition interface represents a node in the command line arguments syntax tree; simply extending the Syntaxable interface and adding the functionality of providing access to the added Operands (leafs). In future extensions, a Condition might provide access to the child Syntaxable elements contained in a Condition instance. As of the current findings, access to the children of the Condition node is not required and would make the interface unnecessarily complicated.

See also:

Skip navigation links

Copyright © 2021. All rights reserved.