|
This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Shell 4.0.3! |
Command Syntax
Options and arguments
Command options and arguments can be defined using method parameters:
@Component
class GreetingCommands {
@Command(name = "hi", description = "Say hi to a given name", group = "greetings",
help = "A command that greets the user with 'Hi ${name}!' with a configurable suffix. Example usage: hi -s=! John")
public void sayHi(
@Argument(index = 0, description = "the name of the person to greet",
defaultValue = "world") String name,
@Option(shortName = 's', longName = "suffix", description = "the suffix of the greeting message",
defaultValue = "!") String suffix) {
System.out.println("Hi " + name + suffix);
}
}
Options are defined using @Option annotation, while arguments are defined using @Argument annotation.
Options are named, while arguments are positional. Options can have short names (single character) and long names (multi-character).
Options can be validated using the Bean Validation API by adding validation annotations to the method parameters, see the Validating Command Options section for more details.
Multi-valued arguments can be defined by using the @Arguments annotation on an array or a collection type (e.g., List, Set) as the method parameter type. In this case, all the remaining command line tokens will be collected into the collection:
@Component
class ArgumentsCommands {
@Command(name = "hi", description = "Say hi to given names", group = "greetings",
help = "A command that greets users with a configurable suffix. Example usage: hi -s=! Foo Bar")
public void sayHi(
@Option(shortName = 's', longName = "suffix", description = "the suffix of the greeting message",
defaultValue = "!") String suffix,
@Arguments(description = "the names of the persons to greet") String[] names) {
System.out.println("Hi " + String.join(", ", names) + suffix);
}
}
Like @Argument, @Arguments accepts a description attribute. It is reported in the help output for the command, both in the SYNOPSIS line (as (ElementType…), using the collection’s or array’s element type rather than the declared parameter type) and as a dedicated entry in the ARGUMENTS section.
The @Arguments annotation provides an attribute called arity that allows you to specify the number of arguments to be collected into the collection.
By default, the arity is not bound, which means that all remaining tokens will be collected. If you set the arity to a specific number, only that many tokens will be collected, and the rest will be treated as separate arguments or options.
Here is an example of using the arity attribute:
@Component
class ArgumentsWithArityCommands {
/**
* Real part of (a + bi)(c + di) = ac − bd.
*/
@Command(name = "real-part", description = "Calculate the real part of the product of two complex numbers",
group = "math",
help = "Calculate the real part of the product of two complex numbers. Example usage: real-part 1 2 3 4")
public double realPartOfComplexProduct(@Arguments(arity = 2) double[] realParts,
@Arguments(arity = 2) double[] imaginaryParts) {
return realParts[0] * realParts[1] - imaginaryParts[0] * imaginaryParts[1];
}
}
Parsing rules
Spring Shell follows the same parsing rules as Spring Boot, with enhanced capabilities following the POSIX style.
Options can be specified in the long form of --key=value or --key value as well in the short form of -k=value or -k value.
Options and arguments can be specified in any order. Arguments are 0-based indexed among other arguments:
CommandSyntax ::= CommandName [SubCommandName]* [Option | Argument]*
CommandName ::= String
SubCommandName ::= String
Option ::= ShortOption | LongOption
ShortOption ::= '-' Char ['='|' ']? String
LongOption ::= '--' String ['='|' ']? String
Argument ::= String
For example:
$>mycommand mysubcommand --optionA=value1 arg1 -b=value2 arg2 --optionC value3 -d value4
When an option is specified, it is always expected to have a value for that option, even if it is a boolean one. This is necessary to be able to distinguish option values from arguments. Moreover, short options cannot be grouped (e.g., -abc is not supported).
|
| To avoid ambiguity, named options should be preferred over positional arguments whenever possible, especially when subcommands are involved (see Command Line Interface Guidelines). |
Quoting and escaping
The input is split into words on whitespace. To provide an option value or an argument that contains whitespace,
the value needs to be quoted. Both single (') and double (") quotes are supported, and the enclosing quotes
will not be part of the value:
$>mycommand --message='Hello World' (1)
$>mycommand --message="Hello World" (2)
$>mycommand "arg1 with spaces" (3)
| 1 | option value is Hello World |
| 2 | option value is Hello World |
| 3 | argument value is arg1 with spaces |
Supporting both types of quotes allows one type of quote to be embedded in a value quoted with the other type:
$>mycommand --message="I'm here!" (1)
$>mycommand --message='He said "Hi!"' (2)
| 1 | option value is I’m here! |
| 2 | option value is He said "Hi!" |
To embed the same kind of quote that was used to quote the whole value, escape it with the backslash (\)
character. A literal backslash inside a quoted value can be escaped as \\:
$>mycommand --message="He said \"Hi!\"" (1)
$>mycommand --message='I\'m here!' (2)
| 1 | option value is He said "Hi!" |
| 2 | option value is I’m here! |
Quotes are only removed when the whole value is enclosed in them. Quote characters in the middle of a value
are kept as-is (e.g., value1"inside"value2 stays unchanged), and escape sequences are only resolved inside
quoted values. An input with an unbalanced quote is rejected with an error.
Customizing parsing rules
Spring Shell 4 provides a new API called CommandParser that allows you to customize the command parsing rules.
If the default parsing rules do not fit your needs, you can implement your own parser by implementing the CommandParser interface.
Once the custom parser is implemented, you can register it as a bean in the application context, and Spring Shell will use it for parsing commands.