Improved pandalib-cli
- Custom class to represent command sender - Abstract class to use as a base for CLI application main class - /stop and /admin command that are common to every CLI apps
This commit is contained in:
parent
d5c9876734
commit
efcb155b3d
@ -0,0 +1,103 @@
|
|||||||
|
package fr.pandacube.lib.cli;
|
||||||
|
|
||||||
|
import fr.pandacube.lib.cli.commands.CommandAdmin;
|
||||||
|
import fr.pandacube.lib.cli.commands.CommandStop;
|
||||||
|
import fr.pandacube.lib.util.Log;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main class of a CLI application.
|
||||||
|
*/
|
||||||
|
public abstract class CLIApplication {
|
||||||
|
|
||||||
|
private static CLIApplication instance;
|
||||||
|
|
||||||
|
public static CLIApplication getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public final CLI cli;
|
||||||
|
|
||||||
|
protected CLIApplication() {
|
||||||
|
instance = this;
|
||||||
|
CLI tmpCLI = null;
|
||||||
|
try {
|
||||||
|
tmpCLI = new CLI();
|
||||||
|
Log.setLogger(tmpCLI.getLogger());
|
||||||
|
} catch (Throwable t) {
|
||||||
|
System.err.println("Unable to start application " + getName() + " version " + getClass().getPackage().getImplementationVersion());
|
||||||
|
t.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
cli = tmpCLI;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Log.info("Starting " + getName() + " version " + getClass().getPackage().getImplementationVersion());
|
||||||
|
|
||||||
|
start();
|
||||||
|
|
||||||
|
new CommandAdmin();
|
||||||
|
new CommandStop();
|
||||||
|
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(this::end));
|
||||||
|
|
||||||
|
cli.start(); // actually starts the CLI thread
|
||||||
|
|
||||||
|
Log.info("Application started.");
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.severe("Unable to start application " + getName() + " version " + getClass().getPackage().getImplementationVersion(), t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Logger getLogger() {
|
||||||
|
return cli.getLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final Object stopLock = new Object();
|
||||||
|
private final AtomicBoolean stopping = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
public final void stop() {
|
||||||
|
synchronized (stopLock) {
|
||||||
|
synchronized (stopping) {
|
||||||
|
if (stopping.get())
|
||||||
|
return;
|
||||||
|
stopping.set(true);
|
||||||
|
}
|
||||||
|
Log.info("Stopping " + getName() + " version " + getClass().getPackage().getImplementationVersion());
|
||||||
|
try {
|
||||||
|
end();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.severe("Error stopping application " + getName() + " version " + getClass().getPackage().getImplementationVersion(), t);
|
||||||
|
} finally {
|
||||||
|
Log.info("Bye bye.");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStopping() {
|
||||||
|
return stopping.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public abstract String getName();
|
||||||
|
|
||||||
|
protected abstract void start() throws Exception;
|
||||||
|
|
||||||
|
public abstract void reload();
|
||||||
|
|
||||||
|
protected abstract void end();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -12,13 +12,13 @@ import java.util.function.Predicate;
|
|||||||
/**
|
/**
|
||||||
* Abstract class that holds the logic of a specific command to be registered in {@link CLIBrigadierDispatcher}.
|
* Abstract class that holds the logic of a specific command to be registered in {@link CLIBrigadierDispatcher}.
|
||||||
*/
|
*/
|
||||||
public abstract class CLIBrigadierCommand extends BrigadierCommand<Object> {
|
public abstract class CLIBrigadierCommand extends BrigadierCommand<CLICommandSender> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instanciate this command instance.
|
* Instanciate this command instance.
|
||||||
*/
|
*/
|
||||||
public CLIBrigadierCommand() {
|
public CLIBrigadierCommand() {
|
||||||
LiteralCommandNode<Object> commandNode = buildCommand().build();
|
LiteralCommandNode<CLICommandSender> commandNode = buildCommand().build();
|
||||||
postBuildCommand(commandNode);
|
postBuildCommand(commandNode);
|
||||||
String[] aliases = getAliases();
|
String[] aliases = getAliases();
|
||||||
if (aliases == null)
|
if (aliases == null)
|
||||||
@ -37,7 +37,7 @@ public abstract class CLIBrigadierCommand extends BrigadierCommand<Object> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract LiteralArgumentBuilder<Object> buildCommand();
|
protected abstract LiteralArgumentBuilder<CLICommandSender> buildCommand();
|
||||||
|
|
||||||
protected String[] getAliases() {
|
protected String[] getAliases() {
|
||||||
return new String[0];
|
return new String[0];
|
||||||
@ -47,16 +47,16 @@ public abstract class CLIBrigadierCommand extends BrigadierCommand<Object> {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public boolean isPlayer(Object sender) {
|
public boolean isPlayer(CLICommandSender sender) {
|
||||||
return false;
|
return sender.isPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConsole(Object sender) {
|
public boolean isConsole(CLICommandSender sender) {
|
||||||
return true;
|
return sender.isConsole();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Predicate<Object> hasPermission(String permission) {
|
public Predicate<CLICommandSender> hasPermission(String permission) {
|
||||||
return sender -> true;
|
return sender -> sender.hasPermission(permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ public abstract class CLIBrigadierCommand extends BrigadierCommand<Object> {
|
|||||||
* @param suggestions the suggestions to wrap.
|
* @param suggestions the suggestions to wrap.
|
||||||
* @return a {@link SuggestionProvider} generating the suggestions from the provided {@link SuggestionsSupplier}.
|
* @return a {@link SuggestionProvider} generating the suggestions from the provided {@link SuggestionsSupplier}.
|
||||||
*/
|
*/
|
||||||
protected SuggestionProvider<Object> wrapSuggestions(SuggestionsSupplier<Object> suggestions) {
|
protected SuggestionProvider<CLICommandSender> wrapSuggestions(SuggestionsSupplier<CLICommandSender> suggestions) {
|
||||||
return wrapSuggestions(suggestions, Function.identity());
|
return wrapSuggestions(suggestions, Function.identity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,17 @@
|
|||||||
package fr.pandacube.lib.cli.commands;
|
package fr.pandacube.lib.cli.commands;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.mojang.brigadier.suggestion.Suggestion;
|
import com.mojang.brigadier.suggestion.Suggestion;
|
||||||
import com.mojang.brigadier.suggestion.Suggestions;
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
|
|
||||||
import fr.pandacube.lib.chat.Chat;
|
|
||||||
import fr.pandacube.lib.commands.BrigadierDispatcher;
|
import fr.pandacube.lib.commands.BrigadierDispatcher;
|
||||||
import fr.pandacube.lib.util.Log;
|
|
||||||
import jline.console.completer.Completer;
|
import jline.console.completer.Completer;
|
||||||
import net.kyori.adventure.text.ComponentLike;
|
import net.kyori.adventure.text.ComponentLike;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link BrigadierDispatcher} that integrates the commands into the JLine CLI interface.
|
* Implementation of {@link BrigadierDispatcher} that integrates the commands into the JLine CLI interface.
|
||||||
*/
|
*/
|
||||||
public class CLIBrigadierDispatcher extends BrigadierDispatcher<Object> implements Completer {
|
public class CLIBrigadierDispatcher extends BrigadierDispatcher<CLICommandSender> implements Completer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The instance of {@link CLIBrigadierDispatcher}.
|
* The instance of {@link CLIBrigadierDispatcher}.
|
||||||
@ -22,16 +19,16 @@ public class CLIBrigadierDispatcher extends BrigadierDispatcher<Object> implemen
|
|||||||
public static final CLIBrigadierDispatcher instance = new CLIBrigadierDispatcher();
|
public static final CLIBrigadierDispatcher instance = new CLIBrigadierDispatcher();
|
||||||
|
|
||||||
|
|
||||||
private static final Object sender = new Object();
|
private static final CLICommandSender CLI_CONSOLE_COMMAND_SENDER = new CLIConsoleCommandSender();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the provided command.
|
* Executes the provided command as the console.
|
||||||
* @param commandWithoutSlash the command, without the eventual slash at the begining.
|
* @param commandWithoutSlash the command, without the eventual slash at the begining.
|
||||||
* @return the value returned by the executed command.
|
* @return the value returned by the executed command.
|
||||||
*/
|
*/
|
||||||
public int execute(String commandWithoutSlash) {
|
public int execute(String commandWithoutSlash) {
|
||||||
return execute(sender, commandWithoutSlash);
|
return execute(CLI_CONSOLE_COMMAND_SENDER, commandWithoutSlash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -50,17 +47,17 @@ public class CLIBrigadierDispatcher extends BrigadierDispatcher<Object> implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the suggestions for the currently being typed command.
|
* Gets the suggestions for the currently being typed command, as the console.
|
||||||
* @param buffer the command that is being typed.
|
* @param buffer the command that is being typed.
|
||||||
* @return the suggestions for the currently being typed command.
|
* @return the suggestions for the currently being typed command.
|
||||||
*/
|
*/
|
||||||
public Suggestions getSuggestions(String buffer) {
|
public Suggestions getSuggestions(String buffer) {
|
||||||
return getSuggestions(sender, buffer);
|
return getSuggestions(CLI_CONSOLE_COMMAND_SENDER, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void sendSenderMessage(Object sender, ComponentLike message) {
|
protected void sendSenderMessage(CLICommandSender sender, ComponentLike message) {
|
||||||
Log.info(Chat.chatComponent(message).getLegacyText());
|
sender.sendMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
package fr.pandacube.lib.cli.commands;
|
||||||
|
|
||||||
|
import net.kyori.adventure.audience.Audience;
|
||||||
|
import net.kyori.adventure.audience.MessageType;
|
||||||
|
import net.kyori.adventure.identity.Identity;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A command sender.
|
||||||
|
*/
|
||||||
|
public interface CLICommandSender extends Audience {
|
||||||
|
/**
|
||||||
|
* Gets the name of the sender.
|
||||||
|
* @return The name of the sender.
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if the sender is a player.
|
||||||
|
* @return true if the sender is a player, false otherwise.
|
||||||
|
*/
|
||||||
|
boolean isPlayer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if the sender is on the console.
|
||||||
|
* @return true if the sender is on the console, false otherwise.
|
||||||
|
*/
|
||||||
|
boolean isConsole();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if the sender has the specified permission.
|
||||||
|
* @param permission the permission to test on the sender.
|
||||||
|
* @return true if the sender has the specified permission.
|
||||||
|
*/
|
||||||
|
boolean hasPermission(String permission);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the provided message to the sender.
|
||||||
|
* @param message the message to send.
|
||||||
|
*/
|
||||||
|
void sendMessage(String message);
|
||||||
|
|
||||||
|
@Override // force implementation of super-interface default method
|
||||||
|
void sendMessage(Identity source, Component message, MessageType type);
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package fr.pandacube.lib.cli.commands;
|
||||||
|
|
||||||
|
import fr.pandacube.lib.chat.Chat;
|
||||||
|
import fr.pandacube.lib.util.Log;
|
||||||
|
import net.kyori.adventure.audience.MessageType;
|
||||||
|
import net.kyori.adventure.identity.Identity;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command sender.
|
||||||
|
*/
|
||||||
|
public class CLIConsoleCommandSender implements CLICommandSender {
|
||||||
|
public String getName() {
|
||||||
|
return "Console";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPlayer() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConsole() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPermission(String permission) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendMessage(String message) {
|
||||||
|
Log.info(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessage(Identity source, Component message, MessageType type) {
|
||||||
|
sendMessage(Chat.chatComponent(message).getLegacyText());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,273 @@
|
|||||||
|
package fr.pandacube.lib.cli.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.BoolArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.DoubleArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.FloatArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.LongArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.mojang.brigadier.tree.ArgumentCommandNode;
|
||||||
|
import com.mojang.brigadier.tree.CommandNode;
|
||||||
|
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||||
|
import com.mojang.brigadier.tree.RootCommandNode;
|
||||||
|
import fr.pandacube.lib.chat.Chat;
|
||||||
|
import fr.pandacube.lib.chat.Chat.FormatableChat;
|
||||||
|
import fr.pandacube.lib.chat.ChatTreeNode;
|
||||||
|
import fr.pandacube.lib.cli.CLIApplication;
|
||||||
|
import fr.pandacube.lib.util.Log;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static fr.pandacube.lib.chat.ChatStatic.chat;
|
||||||
|
import static fr.pandacube.lib.chat.ChatStatic.failureText;
|
||||||
|
import static fr.pandacube.lib.chat.ChatStatic.successText;
|
||||||
|
import static fr.pandacube.lib.chat.ChatStatic.text;
|
||||||
|
|
||||||
|
public class CommandAdmin extends CLIBrigadierCommand {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LiteralArgumentBuilder<CLICommandSender> buildCommand() {
|
||||||
|
return literal("admin")
|
||||||
|
.executes(this::version)
|
||||||
|
.then(literal("version")
|
||||||
|
.executes(this::version)
|
||||||
|
)
|
||||||
|
.then(literal("reload")
|
||||||
|
.executes(this::reload)
|
||||||
|
)
|
||||||
|
.then(literal("debug")
|
||||||
|
.executes(this::debug)
|
||||||
|
)
|
||||||
|
.then(literal("commandstruct")
|
||||||
|
.executes(this::commandStruct)
|
||||||
|
.then(argument("path", StringArgumentType.greedyString())
|
||||||
|
.executes(this::commandStruct)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int version(CommandContext<CLICommandSender> context) {
|
||||||
|
Log.info(chat()
|
||||||
|
.console(context.getSource().isConsole())
|
||||||
|
.infoColor()
|
||||||
|
.thenCenterText(text(CLIApplication.getInstance().getName()))
|
||||||
|
.thenNewLine()
|
||||||
|
.thenText("- Implem. version: ")
|
||||||
|
.thenData(CLIApplication.getInstance().getClass().getPackage().getImplementationVersion())
|
||||||
|
.thenNewLine()
|
||||||
|
.thenText("- Spec. version: ")
|
||||||
|
.thenData(CLIApplication.getInstance().getClass().getPackage().getSpecificationVersion())
|
||||||
|
.getLegacyText());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private int reload(CommandContext<CLICommandSender> context) {
|
||||||
|
CLIApplication.getInstance().reload();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int debug(CommandContext<CLICommandSender> context) {
|
||||||
|
Log.setDebug(!Log.isDebugEnabled());
|
||||||
|
Log.info(successText("Mode débug "
|
||||||
|
+ (Log.isDebugEnabled() ? "" : "dés") + "activé").getLegacyText());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int commandStruct(CommandContext<CLICommandSender> context) {
|
||||||
|
CLICommandSender sender = context.getSource();
|
||||||
|
String[] tokens = tryGetArgument(context, "path", String.class, s -> s.split(" "), new String[0]);
|
||||||
|
|
||||||
|
CommandNode<CLICommandSender> node = CLIBrigadierDispatcher.instance.getDispatcher().findNode(Arrays.asList(tokens));
|
||||||
|
|
||||||
|
if (node == null) {
|
||||||
|
Log.severe(failureText("La commande spécifiée n’a pas été trouvée.").getLegacyText());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<CommandNode<CLICommandSender>> scannedNodes = new HashSet<>();
|
||||||
|
DisplayCommandNode displayNode = new DisplayCommandNode();
|
||||||
|
|
||||||
|
// find parent nodes of scanned node to avoid displaying them after redirection and stuff
|
||||||
|
for (int i = 1; i < tokens.length; i++) {
|
||||||
|
CommandNode<CLICommandSender> ignoredNode = CLIBrigadierDispatcher.instance.getDispatcher().findNode(Arrays.asList(Arrays.copyOf(tokens, i)));
|
||||||
|
if (ignoredNode != null) {
|
||||||
|
displayNode.addInline(ignoredNode);
|
||||||
|
scannedNodes.add(ignoredNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildDisplayCommandTree(displayNode, scannedNodes, node);
|
||||||
|
|
||||||
|
ChatTreeNode displayTreeNode = buildDisplayTree(displayNode, sender);
|
||||||
|
for (Chat comp : displayTreeNode.render(true))
|
||||||
|
Log.info(comp.getLegacyText());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void buildDisplayCommandTree(DisplayCommandNode displayNode, Set<CommandNode<CLICommandSender>> scannedNodes, CommandNode<CLICommandSender> node) {
|
||||||
|
displayNode.addInline(node);
|
||||||
|
|
||||||
|
scannedNodes.add(node);
|
||||||
|
|
||||||
|
if (node.getRedirect() != null) {
|
||||||
|
if (scannedNodes.contains(node.getRedirect()) || node.getRedirect() instanceof RootCommandNode) {
|
||||||
|
displayNode.addInline(node.getRedirect());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buildDisplayCommandTree(displayNode, scannedNodes, node.getRedirect());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node.getChildren().size() == 1) {
|
||||||
|
buildDisplayCommandTree(displayNode, scannedNodes, node.getChildren().iterator().next());
|
||||||
|
}
|
||||||
|
else if (node.getChildren().size() >= 2) {
|
||||||
|
for (CommandNode<CLICommandSender> child : node.getChildren()) {
|
||||||
|
DisplayCommandNode dNode = new DisplayCommandNode();
|
||||||
|
buildDisplayCommandTree(dNode, scannedNodes, child);
|
||||||
|
displayNode.addChild(dNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private ChatTreeNode buildDisplayTree(DisplayCommandNode displayNode, CLICommandSender sender) {
|
||||||
|
Chat d = chat().then(displayCurrentNode(displayNode.nodes.get(0), false, sender));
|
||||||
|
|
||||||
|
CommandNode<CLICommandSender> prevNode = displayNode.nodes.get(0);
|
||||||
|
for (int i = 1; i < displayNode.nodes.size(); i++) {
|
||||||
|
CommandNode<CLICommandSender> currNode = displayNode.nodes.get(i);
|
||||||
|
if (currNode.equals(prevNode.getRedirect())) {
|
||||||
|
d.then(text(" → ")
|
||||||
|
.hover("Redirects to path: " + CLIBrigadierDispatcher.instance.getDispatcher().getPath(currNode))
|
||||||
|
);
|
||||||
|
d.then(displayCurrentNode(currNode, true, sender));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d.thenText(" ");
|
||||||
|
d.then(displayCurrentNode(currNode, false, sender));
|
||||||
|
}
|
||||||
|
prevNode = currNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ChatTreeNode dispTree = new ChatTreeNode(d);
|
||||||
|
|
||||||
|
for (DisplayCommandNode child : displayNode.children) {
|
||||||
|
dispTree.addChild(buildDisplayTree(child, sender));
|
||||||
|
}
|
||||||
|
|
||||||
|
return dispTree;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private BaseComponent displayCurrentNode(CommandNode<CLICommandSender> node, boolean redirectTarget, CLICommandSender sender) {
|
||||||
|
if (node == null)
|
||||||
|
throw new IllegalArgumentException("node must not be null");
|
||||||
|
FormatableChat d;
|
||||||
|
if (node instanceof RootCommandNode) {
|
||||||
|
d = text("(root)").italic()
|
||||||
|
.hover("Root command node");
|
||||||
|
}
|
||||||
|
else if (node instanceof ArgumentCommandNode) {
|
||||||
|
ArgumentType<?> type = ((ArgumentCommandNode<?, ?>) node).getType();
|
||||||
|
String typeStr = type.getClass().getSimpleName();
|
||||||
|
if (type instanceof IntegerArgumentType
|
||||||
|
|| type instanceof LongArgumentType
|
||||||
|
|| type instanceof FloatArgumentType
|
||||||
|
|| type instanceof DoubleArgumentType) {
|
||||||
|
typeStr = type.toString();
|
||||||
|
}
|
||||||
|
else if (type instanceof BoolArgumentType) {
|
||||||
|
typeStr = "bool()";
|
||||||
|
}
|
||||||
|
else if (type instanceof StringArgumentType) {
|
||||||
|
typeStr = "string(" + ((StringArgumentType) type).getType().name().toLowerCase() + ")";
|
||||||
|
}
|
||||||
|
String t = "<" + node.getName() + ">";
|
||||||
|
String h = "Argument command node"
|
||||||
|
+ "\nType: " + typeStr;
|
||||||
|
|
||||||
|
if (node.getCommand() != null) {
|
||||||
|
t += "®";
|
||||||
|
h += "\nThis node has a command";
|
||||||
|
}
|
||||||
|
|
||||||
|
d = text(t);
|
||||||
|
|
||||||
|
if (!node.canUse(sender)) {
|
||||||
|
d.gray();
|
||||||
|
h += "\nPermission not granted for you";
|
||||||
|
}
|
||||||
|
|
||||||
|
d.hover(h);
|
||||||
|
}
|
||||||
|
else if (node instanceof LiteralCommandNode) {
|
||||||
|
String t = node.getName();
|
||||||
|
String h = "Literal command node";
|
||||||
|
|
||||||
|
if (node.getCommand() != null) {
|
||||||
|
t += "®";
|
||||||
|
h += "\nThis node has a command";
|
||||||
|
}
|
||||||
|
|
||||||
|
d = text(t);
|
||||||
|
|
||||||
|
if (!node.canUse(sender)) {
|
||||||
|
d.gray();
|
||||||
|
h += "\nPermission not granted for you";
|
||||||
|
}
|
||||||
|
|
||||||
|
d.hover(h);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException("Unknown command node type: " + node.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (redirectTarget)
|
||||||
|
d.gray();
|
||||||
|
return d.get();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static class DisplayCommandNode {
|
||||||
|
List<CommandNode<CLICommandSender>> nodes = new ArrayList<>();
|
||||||
|
List<DisplayCommandNode> children = new ArrayList<>();
|
||||||
|
|
||||||
|
void addInline(CommandNode<CLICommandSender> node) {
|
||||||
|
nodes.add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addChild(DisplayCommandNode child) {
|
||||||
|
children.add(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package fr.pandacube.lib.cli.commands;
|
||||||
|
|
||||||
|
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import fr.pandacube.lib.cli.CLIApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /stop (/end) command.
|
||||||
|
*/
|
||||||
|
public class CommandStop extends CLIBrigadierCommand {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LiteralArgumentBuilder<CLICommandSender> buildCommand() {
|
||||||
|
return literal("stop")
|
||||||
|
.executes(context -> {
|
||||||
|
CLIApplication.getInstance().stop();
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getAliases() {
|
||||||
|
return new String[] { "end" };
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user