annotationParser() {
- return this.annotationParser;
- }
- }
-}
diff --git a/src/main/java/cloud/commandframework/annotations/SyntaxParser.java b/src/main/java/cloud/commandframework/annotations/SyntaxParser.java
deleted file mode 100644
index c3ee3901..00000000
--- a/src/main/java/cloud/commandframework/annotations/SyntaxParser.java
+++ /dev/null
@@ -1,75 +0,0 @@
-//
-// MIT License
-//
-// Copyright (c) 2022 Alexander Söderberg & Contributors
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-package cloud.commandframework.annotations;
-
-import org.checkerframework.checker.nullness.qual.NonNull;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.StringTokenizer;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.regex.Pattern;
-
-/**
- * Parses command syntax into syntax fragments.
- *
- * Public since 1.7.0.
- */
-public final class SyntaxParser implements Function<@NonNull String, @NonNull List<@NonNull SyntaxFragment>> {
-
- private static final Predicate PATTERN_ARGUMENT_LITERAL = Pattern.compile("\\S+").asPredicate();
- private static final Predicate PATTERN_ARGUMENT_REQUIRED = Pattern.compile("<(\\S+)>").asPredicate();
- private static final Predicate PATTERN_ARGUMENT_OPTIONAL = Pattern.compile("\\[(\\S+)]").asPredicate();
-
- @Override
- public @NonNull List<@NonNull SyntaxFragment> apply(final @NonNull String syntax) {
- final StringTokenizer stringTokenizer = new StringTokenizer(syntax, " ");
- final List syntaxFragments = new ArrayList<>();
- while (stringTokenizer.hasMoreTokens()) {
- final String token = stringTokenizer.nextToken();
- String major;
- List minor = new ArrayList<>();
- ArgumentMode mode;
- if (PATTERN_ARGUMENT_REQUIRED.test(token)) {
- major = token.substring(1, token.length() - 1);
- mode = ArgumentMode.REQUIRED;
- } else if (PATTERN_ARGUMENT_OPTIONAL.test(token)) {
- major = token.substring(1, token.length() - 1);
- mode = ArgumentMode.OPTIONAL;
- } else if (PATTERN_ARGUMENT_LITERAL.test(token)) {
- final String[] literals = token.split("\\|");
- /* Actually use the other literals as well */
- major = literals[0];
- minor.addAll(Arrays.asList(literals).subList(1, literals.length));
- mode = ArgumentMode.LITERAL;
- } else {
- throw new IllegalArgumentException(String.format("Unrecognizable syntax token '%s'", syntax));
- }
- syntaxFragments.add(new SyntaxFragment(major, minor, mode));
- }
- return syntaxFragments;
- }
-}
diff --git a/src/main/java/cloud/commandframework/arguments/CommandArgument.java b/src/main/java/cloud/commandframework/arguments/CommandArgument.java
deleted file mode 100644
index 41911ac5..00000000
--- a/src/main/java/cloud/commandframework/arguments/CommandArgument.java
+++ /dev/null
@@ -1,829 +0,0 @@
-//
-// MIT License
-//
-// Copyright (c) 2022 Alexander Söderberg & Contributors
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-//
-package cloud.commandframework.arguments;
-
-import cloud.commandframework.ArgumentDescription;
-import cloud.commandframework.Command;
-import cloud.commandframework.CommandManager;
-import cloud.commandframework.arguments.parser.ArgumentParseResult;
-import cloud.commandframework.arguments.parser.ArgumentParser;
-import cloud.commandframework.arguments.parser.ParserParameters;
-import cloud.commandframework.context.CommandContext;
-import cloud.commandframework.keys.CloudKey;
-import cloud.commandframework.keys.CloudKeyHolder;
-import cloud.commandframework.keys.SimpleCloudKey;
-import io.leangen.geantyref.TypeToken;
-
-import java.util.*;
-import java.util.function.BiFunction;
-import java.util.regex.Pattern;
-
-/**
- * AN argument that belongs to a command
- *
- * @param Command sender type
- * @param The type that the argument parses into
- */
-@SuppressWarnings({"unused", "UnusedReturnValue"})
-public class CommandArgument implements Comparable, CloudKeyHolder {
-
- /**
- * Pattern for command argument names
- */
- private static final Pattern NAME_PATTERN = Pattern.compile("\\S+");
-// private static final Pattern NAME_PATTERN = Pattern.compile("[A-Za-z0-9\\-_]+");
-
- /**
- * A typed key representing this argument
- */
- private final CloudKey key;
- /**
- * Indicates whether the argument is required
- * or not. All arguments prior to any other required
- * argument must also be required, such that the predicate
- * (∀ c_i ∈ required)({c_0, ..., c_i-1} ⊂ required) holds true,
- * where {c_0, ..., c_n-1} is the set of command arguments.
- */
- private final boolean required;
- /**
- * The command argument name. This might be exposed
- * to command senders and so should be chosen carefully.
- */
- private final String name;
- /**
- * The parser that is used to parse the command input
- * into the corresponding command type
- */
- private final ArgumentParser parser;
- /**
- * Default value, will be empty if none was supplied
- */
- private final String defaultValue;
- /**
- * The type that is produces by the argument's parser
- */
- private final TypeToken valueType;
- /**
- * Suggestion provider
- */
- private final BiFunction, String, List> suggestionsProvider;
- /**
- * Argument preprocessors that allows for extensions to exist argument types
- * without having to update all parsers
- */
- private final Collection,
- Queue, ArgumentParseResult>> argumentPreprocessors;
-
- /**
- * A description that will be used when registering this argument if no override is provided.
- */
- private final ArgumentDescription defaultDescription;
-
- /**
- * Whether the argument has been used before
- */
- private boolean argumentRegistered = false;
-
- private Command owningCommand;
-
- /**
- * Construct a new command argument
- *
- * @param required Whether the argument is required
- * @param name The argument name
- * @param parser The argument parser
- * @param defaultValue Default value used when no value is provided by the command sender
- * @param valueType Type produced by the parser
- * @param suggestionsProvider Suggestions provider
- * @param defaultDescription Default description to use when registering
- * @param argumentPreprocessors Argument preprocessors
- * @since 1.4.0
- */
- public CommandArgument(
- final boolean required,
- final String name,
- final ArgumentParser parser,
- final String defaultValue,
- final TypeToken valueType,
- final BiFunction, String, List> suggestionsProvider,
- final ArgumentDescription defaultDescription,
- final Collection, Queue,
- ArgumentParseResult>> argumentPreprocessors
- ) {
- this.required = required;
- this.name = Objects.requireNonNull(name, "Name may not be null");
- if (!NAME_PATTERN.asPredicate().test(name)) {
- throw new IllegalArgumentException("Name must not include space character");
- }
- this.parser = Objects.requireNonNull(parser, "Parser may not be null");
- this.defaultValue = defaultValue;
- this.valueType = valueType;
- this.suggestionsProvider = suggestionsProvider == null
- ? buildDefaultSuggestionsProvider(this)
- : suggestionsProvider;
- this.defaultDescription = Objects.requireNonNull(defaultDescription, "Default description may not be null");
- this.argumentPreprocessors = new LinkedList<>(argumentPreprocessors);
- this.key = SimpleCloudKey.of(this.name, this.valueType);
- }
-
- /**
- * Construct a new command argument
- *
- * @param required Whether the argument is required
- * @param name The argument name
- * @param parser The argument parser
- * @param defaultValue Default value used when no value is provided by the command sender
- * @param valueType Type produced by the parser
- * @param suggestionsProvider Suggestions provider
- * @param argumentPreprocessors Argument preprocessors
- */
- public CommandArgument(
- final boolean required,
- final String name,
- final ArgumentParser parser,
- final String defaultValue,
- final TypeToken valueType,
- final BiFunction, String, List> suggestionsProvider,
- final Collection, Queue,
- ArgumentParseResult>> argumentPreprocessors
- ) {
- this(
- required,
- name,
- parser,
- defaultValue,
- valueType,
- suggestionsProvider,
- ArgumentDescription.empty(),
- argumentPreprocessors
- );
- }
-
- /**
- * Construct a new command argument
- *
- * @param required Whether the argument is required
- * @param name The argument name
- * @param parser The argument parser
- * @param defaultValue Default value used when no value is provided by the command sender
- * @param valueType Type produced by the parser
- * @param suggestionsProvider Suggestions provider
- */
- public CommandArgument(
- final boolean required,
- final String name,
- final ArgumentParser parser,
- final String defaultValue,
- final TypeToken valueType,
- final BiFunction, String, List> suggestionsProvider
- ) {
- this(required, name, parser, defaultValue, valueType, suggestionsProvider, Collections.emptyList());
- }
-
- /**
- * Construct a new command argument
- *
- * @param required Whether the argument is required
- * @param name The argument name
- * @param parser The argument parser
- * @param defaultValue Default value used when no value is provided by the command sender
- * @param valueType Type produced by the parser
- * @param suggestionsProvider Suggestions provider
- * @param defaultDescription Default description to use when registering
- * @since 1.4.0
- */
-
- public CommandArgument(
- final boolean required,
- final String name,
- final ArgumentParser parser,
- final String defaultValue,
- final TypeToken valueType,
- final BiFunction, String, List> suggestionsProvider,
- final ArgumentDescription defaultDescription
- ) {
- this(required, name, parser, defaultValue, valueType, suggestionsProvider, defaultDescription, Collections.emptyList());
- }
-
- /**
- * Construct a new command argument
- *
- * @param required Whether the argument is required
- * @param name The argument name
- * @param parser The argument parser
- * @param defaultValue Default value used when no value is provided by the command sender
- * @param valueType Type produced by the parser
- * @param suggestionsProvider Suggestions provider
- */
- public CommandArgument(
- final boolean required,
- final String name,
- final ArgumentParser parser,
- final String defaultValue,
- final Class valueType,
- final BiFunction,
- String, List> suggestionsProvider
- ) {
- this(required, name, parser, defaultValue, TypeToken.get(valueType), suggestionsProvider);
- }
-
- /**
- * Construct a new command argument
- *
- * @param required Whether the argument is required
- * @param name The argument name
- * @param parser The argument parser
- * @param defaultValue Default value used when no value is provided by the command sender
- * @param valueType Type produced by the parser
- * @param suggestionsProvider Suggestions provider
- * @param defaultDescription Default description to use when registering
- * @since 1.4.0
- */
-
- public CommandArgument(
- final boolean required,
- final String name,
- final ArgumentParser parser,
- final String defaultValue,
- final Class valueType,
- final BiFunction,
- String, List> suggestionsProvider,
- final ArgumentDescription defaultDescription
- ) {
- this(required, name, parser, defaultValue, TypeToken.get(valueType), suggestionsProvider, defaultDescription);
- }
-
- /**
- * Construct a new command argument
- *
- * @param required Whether the argument is required
- * @param name The argument name
- * @param parser The argument parser
- * @param valueType Type produced by the parser
- */
- public CommandArgument(
- final boolean required,
- final String name,
- final ArgumentParser parser,
- final Class valueType
- ) {
- this(required, name, parser, "", valueType, null);
- }
-
- private static BiFunction, String,
- List> buildDefaultSuggestionsProvider(final CommandArgument argument) {
- return new DelegatingSuggestionsProvider<>(argument.getName(), argument.getParser());
- }
-
- /**
- * Create a new command argument
- *
- * @param clazz Argument class
- * @param name Argument name
- * @param Command sender type
- * @param Argument Type. Used to make the compiler happy.
- * @return Argument builder
- */
- public static CommandArgument.Builder ofType(
- final TypeToken clazz,
- final String name
- ) {
- return new Builder<>(clazz, name);
- }
-
- /**
- * Create a new command argument
- *
- * @param clazz Argument class
- * @param name Argument name
- * @param Command sender type
- * @param Argument Type. Used to make the compiler happy.
- * @return Argument builder
- */
- public static CommandArgument.Builder ofType(
- final Class clazz,
- final String name
- ) {
- return new Builder<>(TypeToken.get(clazz), name);
- }
-
- @Override
- public final CloudKey getKey() {
- return this.key;
- }
-
- /**
- * Check whether the command argument is required
- *
- * @return {@code true} if the argument is required, {@code false} if not
- */
- public boolean isRequired() {
- return this.required;
- }
-
- /**
- * Get the command argument name;
- *
- * @return Argument name
- */
- public String getName() {
- return this.name;
- }
-
- /**
- * Get the parser that is used to parse the command input
- * into the corresponding command type
- *
- * @return Command parser
- */
- public ArgumentParser getParser() {
- return this.parser;
- }
-
- @Override
- public final String toString() {
- return String.format("%s{name=%s}", this.getClass().getSimpleName(), this.name);
- }
-
- /**
- * Register a new preprocessor. If all preprocessor has succeeding {@link ArgumentParseResult results}
- * that all return {@code true}, the argument will be passed onto the parser.
- *
- * It is important that the preprocessor doesn't pop any input. Instead, it should only peek.
- *
- * @param preprocessor Preprocessor
- * @return {@code this}
- */
- public CommandArgument addPreprocessor(
- final BiFunction, Queue,
- ArgumentParseResult> preprocessor
- ) {
- this.argumentPreprocessors.add(preprocessor);
- return this;
- }
-
- /**
- * Preprocess command input. This will immediately forward any failed argument parse results.
- * If none fails, a {@code true} result will be returned
- *
- * @param context Command context
- * @param input Remaining command input. None will be popped
- * @return Parsing error, or argument containing {@code true}
- */
- public ArgumentParseResult preprocess(
- final CommandContext context,
- final Queue input
- ) {
- for (final BiFunction, Queue,
- ArgumentParseResult> preprocessor : this.argumentPreprocessors) {
- final ArgumentParseResult result = preprocessor.apply(
- context,
- input
- );
- if (result.getFailure().isPresent()) {
- return result;
- }
- }
- return ArgumentParseResult.success(true);
- }
-
- /**
- * Get the owning command
- *
- * @return Owning command
- */
- public Command getOwningCommand() {
- return this.owningCommand;
- }
-
- /**
- * Set the owning command
- *
- * @param owningCommand Owning command
- */
- public void setOwningCommand(final Command owningCommand) {
- if (this.owningCommand != null) {
- throw new IllegalStateException("Cannot replace owning command");
- }
- this.owningCommand = owningCommand;
- }
-
- /**
- * Get the argument suggestions provider
- *
- * @return Suggestions provider
- */
- public final BiFunction, String,
- List> getSuggestionsProvider() {
- return this.suggestionsProvider;
- }
-
- /**
- * Get the default description to use when registering and no other is provided.
- *
- * @return the default description
- */
- public final ArgumentDescription getDefaultDescription() {
- return this.defaultDescription;
- }
-
- @Override
- public final boolean equals(final Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- final CommandArgument, ?> that = (CommandArgument, ?>) o;
- return this.isRequired() == that.isRequired() && Objects.equals(this.getName(), that.getName());
- }
-
- @Override
- public final int hashCode() {
- return Objects.hash(this.isRequired(), this.getName());
- }
-
- @Override
- public final int compareTo(final CommandArgument o) {
- if (this instanceof StaticArgument) {
- if (o instanceof StaticArgument) {
- return this.getName().compareTo(o.getName());
- } else {
- return -1;
- }
- } else {
- if (o instanceof StaticArgument) {
- return 1;
- } else {
- return 0;
- }
- }
- }
-
- /**
- * Get the default value
- *
- * @return Default value
- */
- public String getDefaultValue() {
- return this.defaultValue;
- }
-
- /**
- * Check if the argument has a default value
- *
- * @return {@code true} if the argument has a default value, {@code false} if not
- */
- public boolean hasDefaultValue() {
- return !this.isRequired()
- && !this.getDefaultValue().isEmpty();
- }
-
- /**
- * Get the type of this argument's value
- *
- * @return Value type
- */
- public TypeToken getValueType() {
- return this.valueType;
- }
-
- /**
- * Create a copy of the command argument
- *
- * @return Copied argument
- */
- public CommandArgument copy() {
- CommandArgument.Builder builder = ofType(this.valueType, this.name);
- builder = builder.withSuggestionsProvider(this.suggestionsProvider);
- builder = builder.withParser(this.parser);
- if (this.isRequired()) {
- builder = builder.asRequired();
- } else if (this.defaultValue.isEmpty()) {
- builder = builder.asOptional();
- } else {
- builder = builder.asOptionalWithDefault(this.defaultValue);
- }
- builder = builder.withDefaultDescription(this.defaultDescription);
-
- return builder.build();
- }
-
- /**
- * Check whether the argument has been used in a command
- *
- * @return {@code true} if the argument has been used in a command, else {@code false}
- */
- public boolean isArgumentRegistered() {
- return this.argumentRegistered;
- }
-
- /**
- * Indicate that the argument has been associated with a command
- */
- public void setArgumentRegistered() {
- this.argumentRegistered = true;
- }
-
-
- /**
- * Mutable builder for {@link CommandArgument} instances
- *
- * @param Command sender type
- * @param Argument value type
- */
- public static class Builder {
-
- private final TypeToken valueType;
- private final String name;
-
- private CommandManager manager;
- private boolean required = true;
- private ArgumentParser parser;
- private String defaultValue = "";
- private BiFunction, String, List> suggestionsProvider;
- private ArgumentDescription defaultDescription = ArgumentDescription.empty();
-
- private final Collection,
- String, ArgumentParseResult>> argumentPreprocessors = new LinkedList<>();
-
- protected Builder(
- final TypeToken valueType,
- final String name
- ) {
- this.valueType = valueType;
- this.name = name;
- }
-
- protected Builder(
- final Class valueType,
- final String name
- ) {
- this(TypeToken.get(valueType), name);
- }
-
- /**
- * Set the command manager. Will be used to create a default parser
- * if none was provided
- *
- * @param manager Command manager
- * @return Builder instance
- */
- public Builder manager(final CommandManager manager) {
- this.manager = manager;
- return this;
- }
-
- /**
- * Indicates that the argument is required.
- * All arguments prior to any other required
- * argument must also be required, such that the predicate
- * (∀ c_i ∈ required)({c_0, ..., c_i-1} ⊂ required) holds true,
- * where {c_0, ..., c_n-1} is the set of command arguments.
- *
- * @return Builder instance
- */
- public Builder asRequired() {
- this.required = true;
- return this;
- }
-
- /**
- * Indicates that the argument is optional.
- * All arguments prior to any other required
- * argument must also be required, such that the predicate
- * (∀ c_i ∈ required)({c_0, ..., c_i-1} ⊂ required) holds true,
- * where {c_0, ..., c_n-1} is the set of command arguments.
- *
- * @return Builder instance
- */
- public Builder asOptional() {
- this.required = false;
- return this;
- }
-
- /**
- * Indicates that the argument is optional.
- * All arguments prior to any other required
- * argument must also be required, such that the predicate
- * (∀ c_i ∈ required)({c_0, ..., c_i-1} ⊂ required) holds true,
- * where {c_0, ..., c_n-1} is the set of command arguments.
- *
- * @param defaultValue Default value that will be used if none was supplied
- * @return Builder instance
- */
- public Builder asOptionalWithDefault(final String defaultValue) {
- this.defaultValue = defaultValue;
- this.required = false;
- return this;
- }
-
- /**
- * Set the argument parser
- *
- * @param parser Argument parser
- * @return Builder instance
- */
- public Builder withParser(final ArgumentParser parser) {
- this.parser = Objects.requireNonNull(parser, "Parser may not be null");
- return this;
- }
-
- /**
- * Set the suggestions provider
- *
- * @param suggestionsProvider Suggestions provider
- * @return Builder instance
- */
- public Builder withSuggestionsProvider(
- final BiFunction,
- String, List> suggestionsProvider
- ) {
- this.suggestionsProvider = suggestionsProvider;
- return this;
- }
-
- /**
- * Set the default description to be used for this argument.
- *
- * The default description is used when no other description is provided for a certain argument.
- *
- * @param defaultDescription The default description
- * @return Builder instance
- * @since 1.4.0
- */
-
- public Builder withDefaultDescription(
- final ArgumentDescription defaultDescription
- ) {
- this.defaultDescription = Objects.requireNonNull(defaultDescription, "Default description may not be null");
- return this;
- }
-
- /**
- * Construct a command argument from the builder settings
- *
- * @return Constructed argument
- */
- public CommandArgument build() {
- if (this.parser == null && this.manager != null) {
- this.parser = this.manager.parserRegistry().createParser(this.valueType, ParserParameters.empty())
- .orElse(null);
- }
- if (this.parser == null) {
- this.parser = (c, i) -> ArgumentParseResult
- .failure(new UnsupportedOperationException("No parser was specified"));
- }
- if (this.suggestionsProvider == null) {
- this.suggestionsProvider = new DelegatingSuggestionsProvider<>(this.name, this.parser);
- }
- return new CommandArgument<>(
- this.required,
- this.name,
- this.parser,
- this.defaultValue,
- this.valueType,
- this.suggestionsProvider,
- this.defaultDescription
- );
- }
-
- protected final String getName() {
- return this.name;
- }
-
- protected final boolean isRequired() {
- return this.required;
- }
-
- protected final ArgumentParser getParser() {
- return this.parser;
- }
-
- protected final String getDefaultValue() {
- return this.defaultValue;
- }
-
- protected final BiFunction, String, List>
- getSuggestionsProvider() {
- return this.suggestionsProvider;
- }
-
- protected final ArgumentDescription getDefaultDescription() {
- return this.defaultDescription;
- }
-
- protected final TypeToken getValueType() {
- return this.valueType;
- }
- }
-
- /**
- * A variant of builders designed for subclassing, that returns a self type.
- *
- * @param sender type
- * @param argument value type
- * @param the subclass type
- * @since 1.5.0
- */
- public abstract static class TypedBuilder> extends Builder {
-
- protected TypedBuilder(
- final TypeToken valueType,
- final String name
- ) {
- super(valueType, name);
- }
-
- protected TypedBuilder(
- final Class valueType,
- final String name
- ) {
- super(valueType, name);
- }
-
- @SuppressWarnings("unchecked")
- protected final B self() {
- return (B) this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public B manager(final CommandManager manager) {
- super.manager(manager);
- return this.self();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public B asRequired() {
- super.asRequired();
- return this.self();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public B asOptional() {
- super.asOptional();
- return this.self();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public B asOptionalWithDefault(final String defaultValue) {
- super.asOptionalWithDefault(defaultValue);
- return this.self();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public B withParser(final ArgumentParser parser) {
- super.withParser(parser);
- return this.self();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Builder withSuggestionsProvider(
- final BiFunction,
- String, List> suggestionsProvider
- ) {
- super.withSuggestionsProvider(suggestionsProvider);
- return this.self();
- }
- }
-}
diff --git a/src/main/java/snw/kookbc/impl/KBCClient.java b/src/main/java/snw/kookbc/impl/KBCClient.java
index 979477a7..58edbee8 100644
--- a/src/main/java/snw/kookbc/impl/KBCClient.java
+++ b/src/main/java/snw/kookbc/impl/KBCClient.java
@@ -32,8 +32,7 @@
import snw.jkook.plugin.UnknownDependencyException;
import snw.jkook.util.Validate;
import snw.kookbc.SharedConstants;
-import snw.kookbc.impl.command.cloud.CloudCommandManagerImpl;
-import snw.kookbc.impl.command.internal.CloudHelpCommand;
+import snw.kookbc.impl.command.CommandManagerImpl;
import snw.kookbc.impl.command.internal.HelpCommand;
import snw.kookbc.impl.command.internal.PluginsCommand;
import snw.kookbc.impl.console.Console;
@@ -129,7 +128,7 @@ public KBCClient(
this.internalPlugin = new InternalPlugin(this);
this.core.init(this);
/*Cloud*/
- this.commandManager = Optional.ofNullable(commandManager).orElseGet(() -> CloudCommandManagerImpl::new).apply(this);
+ this.commandManager = Optional.ofNullable(commandManager).orElseGet(() -> CommandManagerImpl::new).apply(this);
this.networkClient = Optional.ofNullable(networkClient).orElseGet(() -> c -> new NetworkClient(c, token)).apply(this);
this.storage = Optional.ofNullable(storage).orElseGet(() -> EntityStorage::new).apply(this);
this.entityBuilder = Optional.ofNullable(entityBuilder).orElseGet(() -> EntityBuilder::new).apply(this);
@@ -523,17 +522,12 @@ protected void registerPluginsCommand() {
}
protected void registerHelpCommand() {
- if (core.getCommandManager() instanceof CloudCommandManagerImpl) {
- ((CloudCommandManagerImpl) core.getCommandManager())
- .registerCloudCommand(internalPlugin, new CloudHelpCommand(this));
- } else {
- HelpCommand executor = new HelpCommand(this);
- new JKookCommand("help")
- .setDescription("获取此帮助列表。")
- .executesUser(executor)
- .executesConsole(executor)
- .register(getInternalPlugin());
- }
+ HelpCommand executor = new HelpCommand(this);
+ new JKookCommand("help")
+ .setDescription("获取此帮助列表。")
+ .executesUser(executor)
+ .executesConsole(executor)
+ .register(getInternalPlugin());
this.core.getEventManager()
.registerHandlers(this.internalPlugin, new UserClickButtonListener(this));
}
diff --git a/src/main/java/snw/kookbc/impl/command/cloud/CloudBasedCommandManager.java b/src/main/java/snw/kookbc/impl/command/cloud/CloudBasedCommandManager.java
deleted file mode 100644
index 4d1a7e39..00000000
--- a/src/main/java/snw/kookbc/impl/command/cloud/CloudBasedCommandManager.java
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * KookBC -- The Kook Bot Client & JKook API standard implementation for Java.
- * Copyright (C) 2022 - 2023 KookBC contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-package snw.kookbc.impl.command.cloud;
-
-import cloud.commandframework.CloudCapability;
-import cloud.commandframework.Command;
-import cloud.commandframework.CommandManager;
-import cloud.commandframework.arguments.CommandArgument;
-import cloud.commandframework.arguments.standard.StringArrayArgument;
-import cloud.commandframework.context.CommandContext;
-import cloud.commandframework.context.CommandContextFactory;
-import cloud.commandframework.context.StandardCommandContextFactory;
-import cloud.commandframework.exceptions.*;
-import cloud.commandframework.execution.CommandExecutionCoordinator;
-import cloud.commandframework.execution.CommandResult;
-import cloud.commandframework.internal.CommandInputTokenizer;
-import cloud.commandframework.internal.CommandRegistrationHandler;
-import cloud.commandframework.meta.CommandMeta;
-import cloud.commandframework.meta.SimpleCommandMeta;
-import cloud.commandframework.services.State;
-import io.leangen.geantyref.TypeToken;
-import org.checkerframework.checker.nullness.qual.NonNull;
-import org.jetbrains.annotations.NotNull;
-import snw.jkook.command.CommandException;
-import snw.jkook.command.CommandSender;
-import snw.jkook.command.ConsoleCommandSender;
-import snw.jkook.command.JKookCommand;
-import snw.jkook.entity.Guild;
-import snw.jkook.entity.User;
-import snw.jkook.message.Message;
-import snw.jkook.plugin.Plugin;
-import snw.kookbc.impl.KBCClient;
-import snw.kookbc.impl.command.cloud.exception.CommandPluginDisabledException;
-import snw.kookbc.impl.command.cloud.parser.GuildArgumentParser;
-import snw.kookbc.impl.command.cloud.parser.PluginArgumentParser;
-import snw.kookbc.impl.command.cloud.parser.UserArgumentParser;
-
-import java.util.*;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
-
-import static snw.kookbc.impl.command.cloud.CloudConstants.*;
-
-/**
- * @author huanmeng_qwq
- */
-@SuppressWarnings("unused")
-public class CloudBasedCommandManager extends CommandManager {
- protected final KBCClient client;
- private final CloudCommandManagerImpl parent;
- private final CommandContextFactory commandContextFactory = new StandardCommandContextFactory<>();
-
- CloudBasedCommandManager(KBCClient client, @NonNull CloudCommandManagerImpl parent) {
- super(CommandExecutionCoordinator.simpleCoordinator(), CommandRegistrationHandler.nullCommandRegistrationHandler());
- this.client = client;
- this.parent = parent;
- registerCapability(CloudCapability.StandardCapabilities.ROOT_COMMAND_DELETION);
- parserRegistry().registerParserSupplier(TypeToken.get(Plugin.class), p -> new PluginArgumentParser(client));
- parserRegistry().registerParserSupplier(TypeToken.get(User.class), p -> new UserArgumentParser(client));
- parserRegistry().registerParserSupplier(TypeToken.get(Guild.class), p -> new GuildArgumentParser(client));
- registerCommandPostProcessor(context -> {
- Command<@NonNull CommandSender> command = context.getCommand();
- CommandContext<@NonNull CommandSender> commandContext = context.getCommandContext();
- commandContext.set(PLUGIN_KEY, command.getCommandMeta().get(PLUGIN_KEY).orElse(null));
- if (!(commandContext.getSender() instanceof ConsoleCommandSender)) {
- logCommand(commandContext.getSender(), commandContext.getRawInputJoined());
- }
- });
- }
-
- @Override
- public boolean hasPermission(@NonNull CommandSender sender, @NonNull String permission) {
- return true;
- }
-
- @Override
- public @NonNull CommandMeta createDefaultCommandMeta() {
- return SimpleCommandMeta.empty();
- }
-
- public void registerJKookCommand(Plugin plugin, JKookCommand jKookCommand) {
- StringArrayArgument args = StringArrayArgument.optional("args", (commandSenderCommandContext, s) -> Collections.emptyList());
- List commands = withPrefix(jKookCommand, jKookCommand.getRootName());
- commands.addAll(withPrefixes(jKookCommand, jKookCommand.getAliases()));
- Iterator iterator = commands.iterator();
- if (!iterator.hasNext()) {
- return;
- }
- List alias = new ArrayList<>();
- String mainCommand = iterator.next();
- while (iterator.hasNext()) {
- alias.add(iterator.next());
- }
- Collection prefixes = jKookCommand.getPrefixes();
- command(
- commandBuilder(
- mainCommand,
- alias,
- SimpleCommandMeta.builder()
- .with(CommandMeta.DESCRIPTION, jKookCommand.getDescription())
- .with(PLUGIN_KEY, plugin)
- .with(PREFIX_KEY, prefixes)
- .with(ALIAS_KEY, alias)
- .with(JKOOK_COMMAND_KEY, true)
- .with(HELP_CONTENT_KEY, jKookCommand.getHelpContent())
- .build()
- )
- .handler(new CloudWrappedCommandExecutionHandler(client, parent, jKookCommand))
- .argument(args)
- .build()
- );
- }
-
- public void unregisterJKookCommand(JKookCommand jKookCommand) {
- for (String commandName : withPrefix(jKookCommand, jKookCommand.getRootName())) {
- deleteRootCommand(commandName);
- }
- }
-
- protected List withPrefixes(JKookCommand jKookCommand, Collection commands) {
- return commands.stream().flatMap(command -> withPrefix(jKookCommand, command).stream()).collect(Collectors.toList());
- }
-
- protected List withPrefix(JKookCommand jKookCommand, String cmd) {
- Collection prefixes = jKookCommand.getPrefixes();
- ArrayList list = new ArrayList<>(prefixes.size());
- for (String prefix : prefixes) {
- list.add(prefix + cmd);
- }
- return list;
- }
-
- protected List removePrefix(String[] prefixes, String... commands) {
- if (prefixes.length == 0) {
- return Arrays.asList(commands);
- }
- List list = new ArrayList<>(commands.length);
- for (String command : commands) {
- boolean match = false;
- for (String prefix : prefixes) {
- if (command.startsWith(prefix)) {
- match = true;
- list.add(command.substring(prefix.length()));
- }
- }
- if (!match) {
- list.add(command);
- }
- }
- return list;
- }
-
- public boolean executeCommandNow(@NonNull CommandSender commandSender, @NonNull String input, Message message) throws CommandException {
- AtomicReference unhandledException = new AtomicReference<>();
- AtomicBoolean foundCommand = new AtomicBoolean(true);
- try {
- executeCommand(commandSender, input, message)
- .whenComplete((commandResult, throwable) -> handleThrowable(commandSender, message, unhandledException, foundCommand, throwable)).get();
- } catch (InterruptedException | ExecutionException ignored) { // impossible
- }
- if (unhandledException.get() != null) {
- throw new CommandException("Something unexpected happened.", unhandledException.get());
- }
- return foundCommand.get();
- }
-
- protected void handleThrowable(@NotNull CommandSender commandSender, Message message, AtomicReference unhandledException, AtomicBoolean foundCommand, Throwable throwable) {
- if (throwable instanceof CompletionException) {
- throwable = throwable.getCause();
- }
- if (throwable instanceof CommandExecutionException) {
- throwable = throwable.getCause();
- }
- final Throwable finalThrowable = throwable;
- if (throwable instanceof InvalidSyntaxException) {
- handleException(commandSender,
- InvalidSyntaxException.class,
- (InvalidSyntaxException) throwable, (c, e) -> {
- if (message != null) {
- message.sendToSource("指令语法错误。正确的用法: "
- + ((InvalidSyntaxException) finalThrowable)
- .getCorrectSyntax());
- } else {
- client.getCore().getLogger().info("指令语法错误。正确的用法: "
- + ((InvalidSyntaxException) finalThrowable)
- .getCorrectSyntax());
- }
- }
- );
- } else if (throwable instanceof InvalidCommandSenderException) {
- handleException(commandSender,
- InvalidCommandSenderException.class,
- (InvalidCommandSenderException) throwable, (c, e) -> {
- if (message != null) {
- message.sendToSource(finalThrowable.getMessage());
- } else {
- client.getCore().getLogger().info(finalThrowable.getMessage());
- }
- }
- );
- } else if (throwable instanceof NoPermissionException) {
- handleException(commandSender,
- NoPermissionException.class,
- (NoPermissionException) throwable, (c, e) -> {
- if (message != null) {
- message.sendToSource("您没有执行此命令的权限");
- } else {
- client.getCore().getLogger().info("您没有执行此命令的权限");
- }
- }
- );
- } else if (throwable instanceof NoSuchCommandException) {
- handleException(commandSender,
- NoSuchCommandException.class,
- (NoSuchCommandException) throwable, (c, e) -> foundCommand.set(false)
- );
- } else if (throwable instanceof ArgumentParseException) {
- handleException(commandSender,
- ArgumentParseException.class,
- (ArgumentParseException) throwable, (c, e) -> {
- if (message != null) {
- message.sendToSource("无效的命令参数: "
- + finalThrowable.getCause().getMessage());
- } else {
- client.getCore().getLogger().info("无效的命令参数: "
- + finalThrowable.getCause().getMessage());
- }
- }
- );
- } else if (throwable instanceof CommandPluginDisabledException) {
- handleException(commandSender,
- CommandPluginDisabledException.class,
- (CommandPluginDisabledException) throwable, (c, e) -> {
- if (message != null) {
- message.sendToSource("无法执行命令: 注册此命令的插件现已被禁用。");
- } else {
- client.getCore().getLogger().info("Unable to execute command: The owner plugin: ({}) of this command was disabled.", e.getPlugin() == null ? "null" : e.getPlugin().getDescription().getName());
- }
- }
- );
- } else if (throwable != null) {
- if (message != null) {
- message.sendToSource("尝试执行此命令时发生内部错误");
- } else {
- client.getCore().getLogger().info("尝试执行此命令时发生内部错误");
- }
- unhandledException.set(throwable); // provide the unhandled exception
- }
- }
-
- @Override
- public final @NonNull CompletableFuture> executeCommand(@NonNull CommandSender commandSender, @NonNull String input) {
- throw new UnsupportedOperationException();
- }
-
- @NonNull
- public CompletableFuture> executeCommand(@NonNull CommandSender commandSender, @NonNull String input, Message message) {
- return executeCommand(commandSender, input, message, commandSender instanceof ConsoleCommandSender);
- }
-
- // prefix:full_command_name
- public Map> collectCommands() {
- LinkedHashMap> map = new LinkedHashMap<>();
- map.put("", new LinkedHashSet<>());
- for (Command command : commands()) {
- map.get("").add(command.getArguments().get(0).getName());
- Collection prefixes = command.getCommandMeta().get(PREFIX_KEY).orElse(null);
- if (prefixes == null) {
- continue;
- }
- Collection aliases = command.getCommandMeta().get(ALIAS_KEY).orElse(Collections.emptyList());
- checkPrefix(map, prefixes.toArray(new String[0]));
- for (String prefix : prefixes) {
- map.get(prefix).addAll(aliases);
- map.get(prefix).add(command.getArguments().get(0).getName());
- }
- }
- return map;
- }
-
- private void checkPrefix(Map> map, String... prefixes) {
- for (String prefix : prefixes) {
- if (!map.containsKey(prefix)) {
- map.put(prefix, new LinkedHashSet<>());
- }
- }
- }
-
- @NonNull
- public CompletableFuture