Command

Picocli Command

Reactant integrated Picocli into PicocliCommandService. You can create a command class and extend ReactantCommand, then you can declare your own command just like a normal Picocli command. For more usage of Picocli, please refer to Picocli Documentation

Also, you can add internal keyword to the command class to avoid exposing it.

@CommandLine.Command(
name = "poke",
mixinStandardHelpOptions = true, // come with default --help option
description = ["Poke someone"]
)
internal class PokeCommand : ReactantCommand() {
@Option(names = {"-a", "--anonymous"}, description = "Hide your name from the poke message")
var anonymous = false;
@CommandLine.Parameters(arity = "1", paramLabel = "PLAYER_NAME",
description = ["The player you want to poke"])
var playerName: String = "";
override fun run() {
Bukkit.getPlayer(playerName)
?.sendMessage("${ if (anonymous) "Someone" else sender.name } poke you!")
?: stderr.out("Player not found: ${playerName}")
}
}

PicocliCommandService

Now, we can register the command we just created with the PicocliCommandService.

import dev.reactant.reactant.extra.command.PicocliCommandService
@Component
class MyCommandRegister(
private val commandService: PicocliCommandService
) : LifeCycleHook {
override fun onEnable(){
commandService {
command({ PokeCommand() })
}
}
}

Injectables for Command

Since only Component can get the injections of objects, if your command needs to inject other objects, you can inject in the Command Register and pass it through the command class constructor.

@Component
class MyCommandRegister(
private val commandService: PicocliCommandService,
private val someExtraInjectables: SomeObject
) : LifeCycleHook {
override fun onEnable(){
commandService {
command({ PokeCommand(someExtraInjectables) })
}
}
}

Nested Command

Sometimes we might need to create multi-level command, following is an example of how it works.

@CommandLine.Command(name = "main", mixinStandardHelpOptions = true)
internal class MainCommand : ReactantCommand() {
override fun run() { showUsage() } // show usage when main command being called
}
@CommandLine.Command(name = "sub1", mixinStandardHelpOptions = true)
internal class Sub1Command : ReactantCommand() {
override fun run() { MyFirstPlugin.log.info("Testing: sub 1") }
}
@CommandLine.Command(name = "sub2", mixinStandardHelpOptions = true)
internal class Sub2Command : ReactantCommand() {
override fun run() { MyFirstPlugin.log.info("Testing: sub 2") }
}

Then register them all commands in your register component with the correct nesting structure.

override fun onEnable(){
commandService {
command({ MainCommand() }){
command({ Sub1Command() })
command({ Sub2Command() })
}
}
}

You should be able to call the command with /main sub1 and /main sub2 after registered the command.

Permissions