Command templates
Command templates are classes that, with the help of annotations, allow you to define commands and arguments in a type-safe and less verbose way.
Define a command
To define a command, you need to create a new class that extends CommandTemplate
and annotate it with @Command.Define
.
The @Command.Define
annotation
Values may be provided to the annotation to specify the names and description of the command. If no name is provided, the name of the class will be used instead.
The description is also optional, and it will be used to provide a summary of the purpose of the command in the help message.
The @Argument.Define
annotation
To define an argument, you need to add a property to the command template class and annotate it with @Argument.Define
.
Read more about defining arguments.
The annotation allows to specify most of the properties of the argument, such as the names()
, description()
, type()
, etc.
Setting the name
The names()
property is used to specify the names of the argument. If no name is provided, the name of the property will be used instead.
How the argument type is set
If an argument type class (Class<ArgumentType>
) is provided in the type()
property of the annotation, an instance of that class will be used as the type of the argument.
If no type is provided, Lanat will attempt to infer the argument type from the type of the property that the argument is assigned to. For example, if the property is of type int
, Lanat will use the IntegerArgumentType
as the type of the argument. See more about argument type inference here.
Examples
Here, the argument type is inferred from the type of the property. (
StringArgumentType
)@Argument.Define public String arg;Here, the argument type is explicitly set to
IntegerArgumentType
.@Argument.Define(type = IntegerArgumentType.class) public int arg;Since
Optional
wraps the type, it is necessary to explicitly set the type of the argument. (Integer
)@Argument.Define(type = Integer.class) // or IntegerArgumentType.class public Optional<Integer> arg;
Setting a group()
You can also specify a group in which this argument will be placed in. By using the group()
property, you can specify the name of the group. If the group does not exist, it will be created.
Multiple arguments can be placed in the same group by specifying the same name for the group.
The @InitDef
methods
Sometimes it is not possible to define all the properties of a command or argument by only using annotations, since in some cases you may need to use a more complex logic to define them. For example, you may need to specify an argument type that requires a constructor with parameters.
In these cases, you can use either the beforeInit
or afterInit
static methods, which are explained below. When added to a command template class, these methods are called by Lanat when it is creating the command instance from the command template class. They must be annotated with @InitDef
.
The beforeInit
method
This method is called before the arguments are added to the command. It receives a CommandBuildContext
instance, which allows to access the argument builders. At the point of this method being called, the argument builders have already been created with the properties defined by the annotations, except for the type()
property, which is not yet set.
This allows you to properly set the type of the argument by using the ArgumentBuilder#type
method, which is exactly what we need for the example mentioned above.
ctx.argWithType(name, type)
is logically equivalent to ctx.arg(name).type(type)
.
These methods allow you to select the argument builder by the name of the arguments defined in the command template. As mentioned before, any property of them may be altered at this point.
The afterInit
method
This method is called right after all the argument builders have been built into argument instances, and they have been added to the command instance. It receives the actual command object.
At this point it is possible to do things such as creating a group and adding arguments to it. Example:
Note that this can be greatly simplified by using the group()
property of the @Argument.Define
annotation:
The @CommandAccessor
annotation
This annotation is used to specify a property that will hold an instance of a sub-command once it is parsed.
Once SubCommand
is instantiated by Lanat, it will be automatically assigned to the subCmd
property of MyCommand
upon instantiation. This will later allow you to access the inner command's properties.
Read more about instantiating a command template class.