Subcommands

Subcommands is another method for registering commands that makes use of creating multiple different CommandAPICommand instances. Given a CommandAPICommand, we can add a subcommand by using the following method:

CommandAPICommand withSubcommand(CommandAPICommand subcommand);
CommandAPICommand withSubcommands(CommandAPICommand... subcommands);

Using subcommands has no disadvantages to using regular commands with the LiteralArgument or MultiLiteralArgument, and should be slightly more intuitive to implement if you've used other command frameworks before.

Example - Permission system with subcommands

Say we wanted to write a permission management system. To do this, we'll use the following command structsyntaxure:

/perm group add <permission> <groupName>
/perm group remove <permission> <groupName>
/perm user add <permission> <userName>
/perm user remove <permission> <userName>

Let's start with the simplest example - the /perm group ... command. We have one command which is the following:

add <permission> <groupName>

We can implement this by creating a CommandAPICommand with the command name add:

CommandAPICommand groupAdd = new CommandAPICommand("add")
    .withArguments(new StringArgument("permission"))
    .withArguments(new StringArgument("groupName"))
    .executes((sender, args) -> {
        // perm group add code
    });
val groupAdd = CommandAPICommand("add")
    .withArguments(StringArgument("permission"))
    .withArguments(StringArgument("groupName"))
    .executes(CommandExecutor { sender, args ->
        // perm group add code
    })
val groupAdd = subcommand("add") {
    stringArgument("permission")
    stringArgument("groupName")
    anyExecutor { sender, args ->
        // perm group add code
    }
}

Similarly, we have another part remove <permission> <groupName>. We can declare this similar to our add command. Once we've done that, we can now join everything up together. Here, we create a command group which adds the two other subcommands:

CommandAPICommand groupRemove = new CommandAPICommand("remove")
    .withArguments(new StringArgument("permission"))
    .withArguments(new StringArgument("groupName"))
    .executes((sender, args) -> {
        // perm group remove code
    });

CommandAPICommand group = new CommandAPICommand("group")
    .withSubcommand(groupAdd)
    .withSubcommand(groupRemove);
val groupRemove = CommandAPICommand("remove")
    .withArguments(StringArgument("permission"))
    .withArguments(StringArgument("groupName"))
    .executes(CommandExecutor { sender, args ->
        // perm group remove code
    })

val group = CommandAPICommand("group")
    .withSubcommand(groupAdd)
    .withSubcommand(groupRemove)
val groupRemove = subcommand("remove") {
    stringArgument("permission")
    stringArgument("groupName")
    anyExecutor { sender, args ->
        // perm group remove code
    }
}

val group = subcommand("group") {
    subcommand(groupAdd)
    subcommand(groupRemove)
}

Finally, we can link everything up together to the perm command and register the whole thing together:

new CommandAPICommand("perm")
    .withSubcommand(group)
    .register();
CommandAPICommand("perm")
    .withSubcommand(group)
    .register()
commandAPICommand("perm") {
    subcommand(group)
}

Another, more intuitive method, is to shove everything in one go without creating lots of variables all over the place:

new CommandAPICommand("perm")
    .withSubcommand(new CommandAPICommand("group")
        .withSubcommand(new CommandAPICommand("add")
            .withArguments(new StringArgument("permission"))
            .withArguments(new StringArgument("groupName"))
            .executes((sender, args) -> {
                // perm group add code
            })
        )
        .withSubcommand(new CommandAPICommand("remove")
            .withArguments(new StringArgument("permission"))
            .withArguments(new StringArgument("groupName"))
            .executes((sender, args) -> {
                // perm group remove code
            })
        )
    )
    .withSubcommand(new CommandAPICommand("user")
        .withSubcommand(new CommandAPICommand("add")
            .withArguments(new StringArgument("permission"))
            .withArguments(new StringArgument("userName"))
            .executes((sender, args) -> {
                // perm user add code
            })
        )
        .withSubcommand(new CommandAPICommand("remove")
            .withArguments(new StringArgument("permission"))
            .withArguments(new StringArgument("userName"))
            .executes((sender, args) -> {
                // perm user remove code
            })
        )
    )
    .register();
CommandAPICommand("perm")
    .withSubcommand(CommandAPICommand("group")
        .withSubcommand(CommandAPICommand("add")
            .withArguments(StringArgument("permission"))
            .withArguments(StringArgument("groupName"))
            .executes(CommandExecutor { sender, args ->
                // perm group add code
            })
        )
        .withSubcommand(CommandAPICommand("remove")
            .withArguments(StringArgument("permission"))
            .withArguments(StringArgument("groupName"))
            .executes(CommandExecutor { sender, args ->
                // perm group remove code
            })
        )
    )
    .withSubcommand(CommandAPICommand("user")
        .withSubcommand(CommandAPICommand("add")
            .withArguments(StringArgument("permission"))
            .withArguments(StringArgument("userName"))
            .executes(CommandExecutor { sender, args ->
                // perm user add code
            })
        )
        .withSubcommand(CommandAPICommand("remove")
            .withArguments(StringArgument("permission"))
            .withArguments(StringArgument("userName"))
            .executes(CommandExecutor { sender, args ->
                // perm user remove code
            })
        )
    )
    .register()
commandAPICommand("perm") {
    subcommand("group") {
        subcommand("add") {
            stringArgument("permission")
            stringArgument("groupName")
            anyExecutor { sender, args ->
                // perm group add code
            }
        }
        subcommand("remove") {
            stringArgument("permission")
            stringArgument("groupName")
            anyExecutor { sender, args ->
                // perm group remove code
            }
        }
    }
    subcommand("user") {
        subcommand("add") {
            stringArgument("permission")
            stringArgument("userName")
            anyExecutor { sender, args ->
                // perm user add code
            }
        }
        subcommand("remove") {
            stringArgument("permission")
            stringArgument("userName")
            anyExecutor { sender, args ->
                // perm user add code
            }
        }
    }
}