From d4f9246f6815fa72db721bbe83e1ec3649679091 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 12 Nov 2022 15:19:36 +0100 Subject: [PATCH] Update some stuff to strings --- .../steamwar/command/AbstractSWCommand.java | 52 +++++++++++++++++-- src/de/steamwar/command/CommandPart.java | 6 +++ src/de/steamwar/command/SWCommandUtils.java | 12 ++++- .../steamwar/command/ArgumentCommandTest.java | 2 + 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/src/de/steamwar/command/AbstractSWCommand.java b/src/de/steamwar/command/AbstractSWCommand.java index c23fd91..7e76d62 100644 --- a/src/de/steamwar/command/AbstractSWCommand.java +++ b/src/de/steamwar/command/AbstractSWCommand.java @@ -67,17 +67,54 @@ public abstract class AbstractSWCommand { protected void sendMessage(T sender, String message, Object[] args) {} + private String[] quote(String[] args) { + List list = new ArrayList<>(); + StringBuilder builder = new StringBuilder(); + boolean quote = false; + for (String arg : args) { + if (arg.startsWith("\"") && arg.endsWith("\"")) { + list.add(arg); + continue; + } + if (arg.startsWith("\"")) { + quote = true; + builder.append(arg); + continue; + } + if (arg.endsWith("\"")) { + quote = false; + builder.append(" ").append(arg); + list.add(builder.toString()); + builder = new StringBuilder(); + continue; + } + if (quote) { + builder.append(" ").append(arg); + continue; + } + list.add(arg); + } + if (quote) { + commandSystemWarning(() -> "Missing closing quote in command"); + } + if (builder.length() > 0) { + list.add(builder.toString()); + } + return list.toArray(new String[0]); + } + protected final void execute(T sender, String alias, String[] args) { initialize(); + String[] finalArgs = quote(args); List errors = new ArrayList<>(); try { - if (!commandList.stream().anyMatch(s -> s.invoke(errors::add, sender, alias, args))) { + if (!commandList.stream().anyMatch(s -> s.invoke(errors::add, sender, alias, finalArgs))) { if (!errors.isEmpty()) { errors.forEach(Runnable::run); return; } commandHelpList.stream().anyMatch(s -> s.invoke((ignore) -> { - }, sender, alias, args)); + }, sender, alias, finalArgs)); } } catch (CommandNoHelpException e) { // Ignored @@ -89,10 +126,11 @@ public abstract class AbstractSWCommand { protected final List tabComplete(T sender, String alias, String[] args) throws IllegalArgumentException { initialize(); + String[] finalArgs = quote(args); String string = args[args.length - 1].toLowerCase(); return commandList.stream() .filter(s -> !s.noTabComplete) - .map(s -> s.tabComplete(sender, args)) + .map(s -> s.tabComplete(sender, finalArgs)) .filter(Objects::nonNull) .flatMap(Collection::stream) .filter(s -> !s.isEmpty()) @@ -371,4 +409,12 @@ public abstract class AbstractSWCommand { @Target({ElementType.PARAMETER}) protected @interface AllowNull { } + + /** + * This annotation is used to mark a String to be quotable with multiple words. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.PARAMETER}) + protected @interface Quotable { + } } diff --git a/src/de/steamwar/command/CommandPart.java b/src/de/steamwar/command/CommandPart.java index 9f21ec8..a81c646 100644 --- a/src/de/steamwar/command/CommandPart.java +++ b/src/de/steamwar/command/CommandPart.java @@ -56,6 +56,9 @@ class CommandPart { @Setter private boolean allowNullValues = false; + @Setter + private boolean quotable = false; + private Parameter parameter; private int parameterIndex; @@ -183,6 +186,9 @@ class CommandPart { } catch (Exception e) { return new CheckArgumentResult(false, null); } + if (value instanceof String && !quotable && ((String) value).contains(" ")) { + return new CheckArgumentResult(false, null); + } if (validator != null && errors != null) { try { if (!validator.validate(sender, value, (s, objects) -> { diff --git a/src/de/steamwar/command/SWCommandUtils.java b/src/de/steamwar/command/SWCommandUtils.java index 32c46c4..5d0312c 100644 --- a/src/de/steamwar/command/SWCommandUtils.java +++ b/src/de/steamwar/command/SWCommandUtils.java @@ -62,7 +62,15 @@ public class SWCommandUtils { addMapper(double.class, Double.class, createMapper(numberMapper(Double::parseDouble), numberCompleter(Double::parseDouble))); addMapper(int.class, Integer.class, createMapper(numberMapper(Integer::parseInt), numberCompleter(Integer::parseInt))); addMapper(long.class, Long.class, createMapper(numberMapper(Long::parseLong), numberCompleter(Long::parseLong))); - MAPPER_FUNCTIONS.put(String.class.getTypeName(), createMapper(s -> s, Collections::singletonList)); + MAPPER_FUNCTIONS.put(String.class.getTypeName(), createMapper(s -> { + if (s.startsWith("\"") && s.endsWith("\"")) { + return s.substring(1, s.length() - 1); + } + if (s.startsWith("'") && s.endsWith("'")) { + return s.substring(1, s.length() - 1); + } + return s; + }, Collections::singletonList)); } public static , K, V> void init(SWTypeMapperCreator swTypeMapperCreator) { @@ -95,10 +103,12 @@ public class SWCommandUtils { Class varArgType = parameter.isVarArgs() ? parameter.getType().getComponentType() : null; AbstractSWCommand.OptionalValue optionalValue = parameter.getAnnotation(AbstractSWCommand.OptionalValue.class); AbstractSWCommand.AllowNull allowNull = parameter.getAnnotation(AbstractSWCommand.AllowNull.class); + AbstractSWCommand.Quotable quotable = parameter.getAnnotation(AbstractSWCommand.Quotable.class); CommandPart commandPart = new CommandPart<>(command, typeMapper, validator, varArgType, optionalValue != null ? optionalValue.value() : null, parameter, i); commandPart.setOnlyUseIfNoneIsGiven(optionalValue != null && optionalValue.onlyUINIG()); commandPart.setAllowNullValues(allowNull != null); + commandPart.setQuotable(quotable != null); if (current != null) { current.setNext(commandPart); } diff --git a/testsrc/de/steamwar/command/ArgumentCommandTest.java b/testsrc/de/steamwar/command/ArgumentCommandTest.java index e57edd0..013e035 100644 --- a/testsrc/de/steamwar/command/ArgumentCommandTest.java +++ b/testsrc/de/steamwar/command/ArgumentCommandTest.java @@ -97,6 +97,8 @@ public class ArgumentCommandTest { } catch (Exception e) { assertCMDFramework(e, ExecutionIdentifier.class, "RunArgument with String"); } + cmd.execute("test", "", new String[]{"\"Hello World\""}); + cmd.execute("test", "", new String[]{"\"Hello", "World\""}); } @Test