diff --git a/cloud-core/src/main/java/cloud/commandframework/arguments/compound/FlagArgument.java b/cloud-core/src/main/java/cloud/commandframework/arguments/compound/FlagArgument.java index 0f680aec..18c7146a 100644 --- a/cloud-core/src/main/java/cloud/commandframework/arguments/compound/FlagArgument.java +++ b/cloud-core/src/main/java/cloud/commandframework/arguments/compound/FlagArgument.java @@ -27,7 +27,11 @@ import cloud.commandframework.arguments.CommandArgument; import cloud.commandframework.arguments.flags.CommandFlag; import cloud.commandframework.arguments.parser.ArgumentParseResult; import cloud.commandframework.arguments.parser.ArgumentParser; +import cloud.commandframework.captions.Caption; +import cloud.commandframework.captions.CaptionVariable; +import cloud.commandframework.captions.StandardCaptionKeys; import cloud.commandframework.context.CommandContext; +import cloud.commandframework.exceptions.parsing.ParserException; import org.checkerframework.checker.nullness.qual.NonNull; import java.util.Collection; @@ -106,11 +110,7 @@ public final class FlagArgument extends CommandArgument { CommandFlag currentFlag = null; for (final @NonNull String string : inputQueue) { - if (string.startsWith("-")) { - if (currentFlag != null && currentFlag.getCommandArgument() != null) { - return ArgumentParseResult.failure( - new IllegalArgumentException(String.format("Missing argument for '%s'", currentFlag.getName()))); - } + if (string.startsWith("-") && currentFlag == null) { if (string.startsWith("--")) { final String flagName = string.substring(2); for (final CommandFlag flag : this.flags) { @@ -131,11 +131,17 @@ public final class FlagArgument extends CommandArgument { } } if (currentFlag == null) { - return ArgumentParseResult.failure( - new IllegalArgumentException(String.format("Unknown flag '%s'", string))); + return ArgumentParseResult.failure(new FlagParseException( + string, + FailureReason.UNKNOWN_FLAG, + commandContext + )); } else if (parsedFlags.contains(currentFlag)) { - return ArgumentParseResult.failure( - new IllegalArgumentException(String.format("Duplicate flag '%s'", string))); + return ArgumentParseResult.failure(new FlagParseException( + string, + FailureReason.DUPLICATE_FLAG, + commandContext + )); } parsedFlags.add(currentFlag); if (currentFlag.getCommandArgument() == null) { @@ -146,9 +152,11 @@ public final class FlagArgument extends CommandArgument { } } else { if (currentFlag == null) { - return ArgumentParseResult.failure( - new IllegalArgumentException(String.format("No flag started. Don't" - + " know what to do with '%s'", string))); + return ArgumentParseResult.failure(new FlagParseException( + string, + FailureReason.NO_FLAG_STARTED, + commandContext + )); } else { final ArgumentParseResult result = ((CommandArgument) currentFlag.getCommandArgument()) @@ -168,6 +176,13 @@ public final class FlagArgument extends CommandArgument { } } } + if (currentFlag != null) { + return ArgumentParseResult.failure(new FlagParseException( + currentFlag.getName(), + FailureReason.MISSING_ARGUMENT, + commandContext + )); + } /* We've consumed everything */ inputQueue.clear(); return ArgumentParseResult.success(FLAG_PARSE_RESULT_OBJECT); @@ -223,4 +238,71 @@ public final class FlagArgument extends CommandArgument { } + /** + * Flag parse exception + */ + public static final class FlagParseException extends ParserException { + + private final String input; + + /** + * Construct a new flag parse exception + * + * @param input Input + * @param failureReason The reason of failure + * @param context Command context + */ + public FlagParseException( + final @NonNull String input, + final @NonNull FailureReason failureReason, + final @NonNull CommandContext context + ) { + super( + FlagArgument.FlagArgumentParser.class, + context, + failureReason.getCaption(), + CaptionVariable.of("input", input), + CaptionVariable.of("flag", input) + ); + this.input = input; + } + + /** + * Get the supplied input + * + * @return String value + */ + public String getInput() { + return input; + } + + } + + /** + * Reasons for which flag parsing may fail + */ + public enum FailureReason { + + UNKNOWN_FLAG(StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_UNKNOWN_FLAG), + DUPLICATE_FLAG(StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_DUPLICATE_FLAG), + NO_FLAG_STARTED(StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_NO_FLAG_STARTED), + MISSING_ARGUMENT(StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_MISSING_ARGUMENT); + + private final Caption caption; + + FailureReason(final @NonNull Caption caption) { + this.caption = caption; + } + + /** + * Get the caption used for this failure reason + * + * @return The caption + */ + public @NonNull Caption getCaption() { + return this.caption; + } + + } + } diff --git a/cloud-core/src/main/java/cloud/commandframework/captions/SimpleCaptionRegistry.java b/cloud-core/src/main/java/cloud/commandframework/captions/SimpleCaptionRegistry.java index 50f049e5..40c70135 100644 --- a/cloud-core/src/main/java/cloud/commandframework/captions/SimpleCaptionRegistry.java +++ b/cloud-core/src/main/java/cloud/commandframework/captions/SimpleCaptionRegistry.java @@ -60,6 +60,22 @@ public class SimpleCaptionRegistry implements FactoryDelegatingCaptionRegistr * Default caption for {@link StandardCaptionKeys#ARGUMENT_PARSE_FAILURE_UUID} */ public static final String ARGUMENT_PARSE_FAILURE_UUID = "'{input}' is not a valid UUID"; + /** + * Default caption for {@link StandardCaptionKeys#ARGUMENT_PARSE_FAILURE_FLAG_UNKNOWN_FLAG} + */ + public static final String ARGUMENT_PARSE_FAILURE_FLAG_UNKNOWN_FLAG = "Unknown flag '{flag}'"; + /** + * Default caption for {@link StandardCaptionKeys#ARGUMENT_PARSE_FAILURE_FLAG_DUPLICATE_FLAG} + */ + public static final String ARGUMENT_PARSE_FAILURE_FLAG_DUPLICATE_FLAG = "Duplicate flag '{flag}'"; + /** + * Default caption for {@link StandardCaptionKeys#ARGUMENT_PARSE_FAILURE_FLAG_NO_FLAG_STARTED} + */ + public static final String ARGUMENT_PARSE_FAILURE_FLAG_NO_FLAG_STARTED = "No flag started. Don't know what to do with '{input}'"; + /** + * Default caption for {@link StandardCaptionKeys#ARGUMENT_PARSE_FAILURE_FLAG_MISSING_ARGUMENT} + */ + public static final String ARGUMENT_PARSE_FAILURE_FLAG_MISSING_ARGUMENT = "Missing argument for '{flag}'"; private final Map> messageFactories = new HashMap<>(); @@ -88,6 +104,22 @@ public class SimpleCaptionRegistry implements FactoryDelegatingCaptionRegistr StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_UUID, (caption, sender) -> ARGUMENT_PARSE_FAILURE_UUID ); + this.registerMessageFactory( + StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_UNKNOWN_FLAG, + (caption, sender) -> ARGUMENT_PARSE_FAILURE_FLAG_UNKNOWN_FLAG + ); + this.registerMessageFactory( + StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_DUPLICATE_FLAG, + (caption, sender) -> ARGUMENT_PARSE_FAILURE_FLAG_DUPLICATE_FLAG + ); + this.registerMessageFactory( + StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_NO_FLAG_STARTED, + (caption, sender) -> ARGUMENT_PARSE_FAILURE_FLAG_NO_FLAG_STARTED + ); + this.registerMessageFactory( + StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_FLAG_MISSING_ARGUMENT, + (caption, sender) -> ARGUMENT_PARSE_FAILURE_FLAG_MISSING_ARGUMENT + ); } @Override diff --git a/cloud-core/src/main/java/cloud/commandframework/captions/StandardCaptionKeys.java b/cloud-core/src/main/java/cloud/commandframework/captions/StandardCaptionKeys.java index b1c208a9..90a30b6e 100644 --- a/cloud-core/src/main/java/cloud/commandframework/captions/StandardCaptionKeys.java +++ b/cloud-core/src/main/java/cloud/commandframework/captions/StandardCaptionKeys.java @@ -64,6 +64,22 @@ public final class StandardCaptionKeys { * Variables: {input}, {pattern} */ public static final Caption ARGUMENT_PARSE_FAILURE_REGEX = of("argument.parse.failure.regex"); + /** + * Variables: {flag} + */ + public static final Caption ARGUMENT_PARSE_FAILURE_FLAG_UNKNOWN_FLAG = of("argument.parse.failure.flag.unknown"); + /** + * Variables: {flag} + */ + public static final Caption ARGUMENT_PARSE_FAILURE_FLAG_DUPLICATE_FLAG = of("argument.parse.failure.flag.duplicate_flag"); + /** + * Variables: {input} + */ + public static final Caption ARGUMENT_PARSE_FAILURE_FLAG_NO_FLAG_STARTED = of("argument.parse.failure.flag.no_flag_started"); + /** + * Variables: {flag} + */ + public static final Caption ARGUMENT_PARSE_FAILURE_FLAG_MISSING_ARGUMENT = of("argument.parse.failure.flag.missing_argument"); private StandardCaptionKeys() { } diff --git a/cloud-minecraft/cloud-minecraft-extras/src/main/java/cloud/commandframework/minecraft/extras/MinecraftHelp.java b/cloud-minecraft/cloud-minecraft-extras/src/main/java/cloud/commandframework/minecraft/extras/MinecraftHelp.java index 66becdd2..7ae34dec 100644 --- a/cloud-minecraft/cloud-minecraft-extras/src/main/java/cloud/commandframework/minecraft/extras/MinecraftHelp.java +++ b/cloud-minecraft/cloud-minecraft-extras/src/main/java/cloud/commandframework/minecraft/extras/MinecraftHelp.java @@ -182,6 +182,15 @@ public final class MinecraftHelp { this.colors = colors; } + /** + * Get the colors used for help messages. + * + * @return The active {@link HelpColors} + */ + public @NonNull HelpColors getHelpColors() { + return this.colors; + } + /** * Set the length of the header/footer of help menus *