diff --git a/src/main/java/de/kencommand/Main.java b/src/main/java/de/kencommand/Main.java new file mode 100644 index 0000000..98252b8 --- /dev/null +++ b/src/main/java/de/kencommand/Main.java @@ -0,0 +1,27 @@ +package de.kencommand; + +import de.kencommand.api.KenCommandApi; +import de.kencommand.api.structure.argument.types.IntegerArgumentType; +import de.kencommand.impl.KenCommandApiImpl; + +import java.io.PrintStream; + +public class Main { + + public static void main(String[] args) { + KenCommandApi api = new KenCommandApiImpl<>(); + + var root = api.createNode("coins"); + + var addNode = api.createNode("add", "deposit"); + addNode.setExecutor(ctx -> { + int amount = ctx.getArg("amount"); + + ctx.getSender().println("adding " + amount + "$ to your balance"); + }); + + addNode.addArgument(api.createArgument("amount", IntegerArgumentType.create())); + root.addLiteral(addNode); + api.invoke(root, System.out, new String[] { "add", "100" }); + } +} diff --git a/src/main/java/de/kencommand/api/KenCommandApi.java b/src/main/java/de/kencommand/api/KenCommandApi.java index bdea91a..bcc8dd2 100644 --- a/src/main/java/de/kencommand/api/KenCommandApi.java +++ b/src/main/java/de/kencommand/api/KenCommandApi.java @@ -1,17 +1,14 @@ package de.kencommand.api; -import de.kencommand.api.processing.CommandExecutor; -import de.kencommand.api.processing.ParsedArgument; +import de.kencommand.api.structure.argument.ArgumentType; +import de.kencommand.api.structure.argument.CommandArgument; import de.kencommand.api.structure.node.CommandNode; -import java.util.Iterator; -import java.util.Map; - public interface KenCommandApi { + CommandNode createNode(String... name); + + CommandArgument createArgument(String id, ArgumentType type); + void invoke(CommandNode node, T sender, String[] args); - - CommandExecutor processLiterals(CommandNode node, Iterator argsIterator); - - Map> parseArguments(CommandNode node, Iterator argsIterator); } diff --git a/src/main/java/de/kencommand/api/structure/argument/CommandArgument.java b/src/main/java/de/kencommand/api/structure/argument/CommandArgument.java index 3b6a0f8..ba4bcf2 100644 --- a/src/main/java/de/kencommand/api/structure/argument/CommandArgument.java +++ b/src/main/java/de/kencommand/api/structure/argument/CommandArgument.java @@ -1,6 +1,5 @@ package de.kencommand.api.structure.argument; -import de.kencommand.api.processing.CommandContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/de/kencommand/api/structure/argument/suggestion/NoSuggestionProvider.java b/src/main/java/de/kencommand/api/structure/argument/suggestion/NoSuggestionProvider.java new file mode 100644 index 0000000..18e4a6e --- /dev/null +++ b/src/main/java/de/kencommand/api/structure/argument/suggestion/NoSuggestionProvider.java @@ -0,0 +1,25 @@ +package de.kencommand.api.structure.argument.suggestion; + +import de.kencommand.api.processing.CommandContext; +import de.kencommand.api.structure.argument.SuggestionProvider; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Set; + +@NoArgsConstructor(access = AccessLevel.NONE) +public class NoSuggestionProvider implements SuggestionProvider { + + @Getter(value = AccessLevel.PRIVATE, lazy = true) + private static final SuggestionProvider instance = new NoSuggestionProvider(); + + public static SuggestionProvider create() { + return getInstance(); + } + + @Override + public Set suggest(CommandContext context) { + return Set.of(); + } +} diff --git a/src/main/java/de/kencommand/api/structure/argument/types/IntegerArgumentType.java b/src/main/java/de/kencommand/api/structure/argument/types/IntegerArgumentType.java new file mode 100644 index 0000000..8e91e8c --- /dev/null +++ b/src/main/java/de/kencommand/api/structure/argument/types/IntegerArgumentType.java @@ -0,0 +1,25 @@ +package de.kencommand.api.structure.argument.types; + +import de.kencommand.api.structure.argument.ArgumentType; +import de.kencommand.api.structure.argument.SuggestionProvider; +import de.kencommand.api.structure.argument.suggestion.NoSuggestionProvider; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class IntegerArgumentType implements ArgumentType { + + @Override + public Integer parseInput(String string) { + return Integer.parseInt(string); + } + + @Override + public SuggestionProvider defaultSuggestionProvider() { + return NoSuggestionProvider.create(); + } + + public static IntegerArgumentType create() { + return new IntegerArgumentType(); + } +} diff --git a/src/main/java/de/kencommand/impl/KenCommandApiImpl.java b/src/main/java/de/kencommand/impl/KenCommandApiImpl.java index a6918db..cc28dd8 100644 --- a/src/main/java/de/kencommand/impl/KenCommandApiImpl.java +++ b/src/main/java/de/kencommand/impl/KenCommandApiImpl.java @@ -3,10 +3,13 @@ package de.kencommand.impl; import de.kencommand.api.KenCommandApi; import de.kencommand.api.processing.CommandExecutor; import de.kencommand.api.processing.ParsedArgument; +import de.kencommand.api.structure.argument.ArgumentType; import de.kencommand.api.structure.argument.CommandArgument; import de.kencommand.api.structure.node.CommandNode; import de.kencommand.impl.processing.CommandContextImpl; import de.kencommand.impl.processing.ParsedArgumentImpl; +import de.kencommand.impl.structure.argument.CommandArgumentImpl; +import de.kencommand.impl.structure.node.CommandNodeImpl; import lombok.RequiredArgsConstructor; import java.util.Arrays; @@ -17,6 +20,16 @@ import java.util.Map; @RequiredArgsConstructor public class KenCommandApiImpl implements KenCommandApi { + @Override + public CommandNode createNode(String... name) { + return new CommandNodeImpl<>(name); + } + + @Override + public CommandArgument createArgument(String id, ArgumentType type) { + return new CommandArgumentImpl<>(id, type); + } + @Override public void invoke(CommandNode node, T sender, String[] args) { var iter = Arrays.stream(args).iterator(); @@ -26,17 +39,18 @@ public class KenCommandApiImpl implements KenCommandApi { executor.execute(new CommandContextImpl<>(sender, parsedArguments)); } - @Override - public CommandExecutor processLiterals(CommandNode commandNode, Iterator iter) { + private CommandExecutor processLiterals(CommandNode commandNode, Iterator iter) { if (!iter.hasNext()) { // literals/arguments are optional if the node itself is executable if (commandNode.getExecutor() == null) throw new RuntimeException("no literal given but required"); - // TODO parse arguments for executor ig, or rather do that in a separate method + return commandNode.getExecutor(); + } + + if (commandNode.getLiterals().isEmpty()) { return commandNode.getExecutor(); } final var arg = iter.next(); - // TODO rethink final var literal = commandNode.getLiteral(arg); if (literal == null) { throw new RuntimeException("Invalid literal: " + arg); @@ -44,10 +58,9 @@ public class KenCommandApiImpl implements KenCommandApi { return processLiterals(literal, iter); } - @Override - public Map> parseArguments(CommandNode commandNode, Iterator iter) { + private Map> parseArguments(CommandNode commandNode, Iterator iter) { Map> parsedArguments = new HashMap<>(); - for (CommandArgument argument : commandNode.getArguments()) { + for (var argument : commandNode.getArguments()) { @SuppressWarnings("unchecked") var arg = ((CommandArgument) argument); diff --git a/src/main/java/de/kencommand/impl/structure/argument/CommandArgumentImpl.java b/src/main/java/de/kencommand/impl/structure/argument/CommandArgumentImpl.java index 995e3d9..d17f3f8 100644 --- a/src/main/java/de/kencommand/impl/structure/argument/CommandArgumentImpl.java +++ b/src/main/java/de/kencommand/impl/structure/argument/CommandArgumentImpl.java @@ -1,6 +1,5 @@ package de.kencommand.impl.structure.argument; -import de.kencommand.api.processing.CommandContext; import de.kencommand.api.structure.argument.ArgumentType; import de.kencommand.api.structure.argument.CommandArgument; import de.kencommand.api.structure.argument.SuggestionProvider; @@ -10,7 +9,7 @@ import lombok.Setter; import org.jetbrains.annotations.Nullable; @RequiredArgsConstructor -public class CommandArgumentImpl, V> implements CommandArgument { +public class CommandArgumentImpl implements CommandArgument { @Getter private final String id; @@ -23,5 +22,5 @@ public class CommandArgumentImpl, V> implements C @Getter @Setter - private @Nullable SuggestionProvider suggestionProvider; + private @Nullable SuggestionProvider suggestionProvider; } diff --git a/src/main/java/de/kencommand/impl/structure/node/CommandNodeImpl.java b/src/main/java/de/kencommand/impl/structure/node/CommandNodeImpl.java index 7476547..d816334 100644 --- a/src/main/java/de/kencommand/impl/structure/node/CommandNodeImpl.java +++ b/src/main/java/de/kencommand/impl/structure/node/CommandNodeImpl.java @@ -1,11 +1,10 @@ package de.kencommand.impl.structure.node; -import de.kencommand.api.processing.CommandContext; import de.kencommand.api.processing.CommandExecutor; import de.kencommand.api.structure.argument.CommandArgument; import de.kencommand.api.structure.node.CommandNode; +import de.kencommand.api.structure.node.LiteralNode; import lombok.Getter; -import lombok.RequiredArgsConstructor; import lombok.Setter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -13,12 +12,16 @@ import org.jetbrains.annotations.Nullable; import java.util.HashSet; import java.util.Set; -@RequiredArgsConstructor public class CommandNodeImpl implements CommandNode { @Getter private final String[] names; + public CommandNodeImpl(String[] names) { + if (names.length == 0) throw new IllegalArgumentException("at least one name is required"); + this.names = names; + } + @Getter private final Set> literals = new HashSet<>(); @Getter