Child Commands

The CommandSpec builder supports hierarchical command structures like this:

  • /mail (parent command)
    • /mail send (child command)
    • /mail read (child command)

Every child command is a separate CommandSpec and can be created in the same way a regular command is.

import org.spongepowered.api.text.Text;
import org.spongepowered.api.command.spec.CommandSpec;

// /mail read
CommandSpec readCmd = CommandSpec.builder()
    .permission("myplugin.mail.read")
    .description(Text.of("Read your inbox"))
    .executor(...)
    .build();

// /mail send
CommandSpec sendCmd = CommandSpec.builder()
    .permission("myplugin.mail.send")
    .description(Text.of("Send a mail"))
    .arguments(...)
    .executor(...)
    .build();

Instead of registering them to the command service, child commands are registered on their parent command using the CommandSpec.Builder#child(CommandCallable, String…) method. They are registered with a list of aliases. The first alias supplied is the primary one and will appear in the usage message.

import org.spongepowered.api.Sponge;

PluginContainer plugin = ...;

CommandSpec mailCommandSpec = CommandSpec.builder()
    .permission("myplugin.mail")
    .description(Text.of("Send and receive mails"))
    .child(readCmd, "read", "r", "inbox")
    .child(sendCmd, "send", "s", "write")
    .build();

Sponge.getCommandManager().register(plugin, mailCommandSpec, "mail", "email");

Fallback Behavior

If a command has child commands, a CommandExecutor, set through CommandSpec.Builder#executor(CommandExecutor) and their associated CommandSpec.Builder#arguments(CommandElement) are optional. The behavior of error in selection and argument parsing of child commands is dependent on whether this parent executor exists.

If a parent executor has not been set, then if the requested child command could not be found or the arguments cannot be parsed, then an ArgumentParseException will be thrown.

If a parent executor has been set for the parent command, it is used as a fallback if the first argument does not match one of the child command aliases. If a child command is selected but the arguments do not parse, one of the following will happen based on what CommandSpec.Builder#childArgumentParseExceptionFallback(boolean) is set to:

  • If true (the default), the ArgumentParseException is discarded and the arguments from the parent commands are parsed. If they fail, the exception for the parent command will be displayed. This is the same behavior as previous API revisions, where child command argument parsing exceptions will not be displayed.
  • If false, the parent executor is not executed and the ArgumentParseException is thrown, returning the exception from the child command argument that failed to parse, but may prevent some combination of parent commands and arguments from being executed (if the first argument of the fallback could be the same as the child command).

In all cases, if the arguments parse successfully but the child executor throws an exception, the fallback executor (if any) is not executed and the error message from the child executor is displayed.