Add support for no-op node

It cannot be executed, just displays help text - after I implement displaying help text
This commit is contained in:
Norbi Peti 2022-10-29 23:21:40 +02:00
parent 8f20ca9b5a
commit 519a632636
3 changed files with 21 additions and 12 deletions

View file

@ -28,11 +28,13 @@ import java.lang.reflect.Parameter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static buttondevteam.lib.chat.CoreCommandBuilder.literal; import static buttondevteam.lib.chat.CoreCommandBuilder.literal;
import static buttondevteam.lib.chat.CoreCommandBuilder.literalNoOp;
/** /**
* The method name is the subcommand, use underlines (_) to add further subcommands. * The method name is the subcommand, use underlines (_) to add further subcommands.
@ -242,7 +244,7 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
* @return The processed command node * @return The processed command node
* @throws Exception Something broke * @throws Exception Something broke
*/ */
protected LiteralCommandNode<TP> processSubcommand(TC command, Method method) throws Exception { protected LiteralCommandNode<TP> processSubcommand(TC command, Method method, Subcommand subcommand) throws Exception {
val params = new ArrayList<Object>(method.getParameterCount()); val params = new ArrayList<Object>(method.getParameterCount());
Class<?>[] parameterTypes = method.getParameterTypes(); Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 0) if (parameterTypes.length == 0)
@ -254,8 +256,8 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
var pdata = getParameterData(method, i1); var pdata = getParameterData(method, i1);
arguments.put(pdata.name, new CommandArgument(pdata.name, cl, pdata.description)); arguments.put(pdata.name, new CommandArgument(pdata.name, cl, pdata.description));
} }
var sd = new SubcommandData<TC>(parameterTypes[0], arguments, command, command.getHelpText(method, method.getAnnotation(Subcommand.class)), null); // TODO: Help text // TODO: Dynamic help text
return getSubcommandNode(method, sd); // TODO: Integrate with getCommandNode and store SubcommandData instead of help text return getSubcommandNode(method, parameterTypes[0], command).helps(command.getHelpText(method, subcommand)).build();
} }
/** /**
@ -291,27 +293,28 @@ public abstract class Command2<TC extends ICommand2<TP>, TP extends Command2Send
var path = command.getCommandPath().split(" "); var path = command.getCommandPath().split(" ");
if (path.length == 0) if (path.length == 0)
throw new IllegalArgumentException("Attempted to register a command with no command path!"); throw new IllegalArgumentException("Attempted to register a command with no command path!");
CoreCommandBuilder<TP> inner = literal(path[0]); CoreCommandBuilder<TP, TC> inner = literalNoOp(path[0]);
var outer = inner; var outer = inner;
for (int i = path.length - 1; i >= 0; i--) { for (int i = path.length - 1; i >= 0; i--) {
CoreCommandBuilder<TP> literal = literal(path[i]); // TODO: This looks like it will duplicate the first node
outer = (CoreCommandBuilder<TP>) literal.executes(this::executeHelpText).then(outer); CoreCommandBuilder<TP, TC> literal = literalNoOp(path[i]);
outer = (CoreCommandBuilder<TP, TC>) literal.executes(this::executeHelpText).then(outer);
} }
var subcommandMethods = command.getClass().getMethods(); var subcommandMethods = command.getClass().getMethods();
for (var subcommandMethod : subcommandMethods) { for (var subcommandMethod : subcommandMethods) {
var ann = subcommandMethod.getAnnotation(Subcommand.class); var ann = subcommandMethod.getAnnotation(Subcommand.class);
if (ann == null) continue; if (ann == null) continue; // TODO: Replace def nodes with executing ones if needed
inner.then(getSubcommandNode(subcommandMethod, ann.helpText())); inner.then(getSubcommandNode(subcommandMethod, ann.helpText()));
} }
return outer; return outer;
} }
private LiteralArgumentBuilder<TP> getSubcommandNode(Method method, String[] helpText) { private CoreCommandBuilder<TP, TC> getSubcommandNode(Method method, Class<?> senderType, TC command) {
CoreCommandBuilder<TP> ret = literal(method.getName()); CoreCommandBuilder<TP, TC> ret = literal(method.getName(), senderType, getCommandParameters(method.getParameters()), command);
return ret.helps(helpText).executes(this::executeCommand); return (CoreCommandBuilder<TP, TC>) ret.executes(this::executeCommand);
} }
private CoreArgumentBuilder<TP, ?> getCommandParameters(Parameter[] parameters) { private Map<String, CommandArgument> getCommandParameters(Parameter[] parameters) {
return null; // TODO return null; // TODO
} }

View file

@ -25,6 +25,10 @@ public class CoreCommandBuilder<S, TC extends ICommand2<?>> extends LiteralArgum
return new CoreCommandBuilder<>(name, senderType, arguments, command); return new CoreCommandBuilder<>(name, senderType, arguments, command);
} }
public static <S, TC extends ICommand2<?>> CoreCommandBuilder<S, TC> literalNoOp(String name) {
return literal(name, Command2Sender.class, Map.of(), null);
}
/** /**
* Static help text added through annotations. May be overwritten with the getter. * Static help text added through annotations. May be overwritten with the getter.
* *

View file

@ -4,6 +4,7 @@ import buttondevteam.lib.chat.ICommand2;
import lombok.Builder; import lombok.Builder;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import javax.annotation.Nullable;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
@ -27,8 +28,9 @@ public final class SubcommandData<TC extends ICommand2<?>> {
*/ */
public final Map<String, CommandArgument> arguments; public final Map<String, CommandArgument> arguments;
/** /**
* The original command class that this data belongs to. * The original command class that this data belongs to. If null, that meaans only the help text can be used.
*/ */
@Nullable
public final TC command; public final TC command;
/** /**