Specific flag builder for enum to streamline context and completion

This commit is contained in:
Ben Woo 2023-08-29 10:44:25 +08:00
parent 59d211ce92
commit bf8bca3244
No known key found for this signature in database
GPG Key ID: FB2A3645536E12C8
3 changed files with 128 additions and 42 deletions

View File

@ -67,22 +67,8 @@ public class CreateCommand extends MultiverseCommand {
.map(genplugin -> genplugin.getDescription().getName()) .map(genplugin -> genplugin.getDescription().getName())
.collect(Collectors.toList())) .collect(Collectors.toList()))
.build()) .build())
.add(CommandValueFlag.builder("--world-type", WorldType.class) .add(CommandValueFlag.enumBuilder("--world-type", WorldType.class)
.addAlias("-t") .addAlias("-t")
.context((value) -> {
try {
return WorldType.valueOf(value.toUpperCase());
} catch (IllegalArgumentException e) {
throw new InvalidCommandArgument("Invalid world type: " + value);
}
})
.completion(() -> {
List<String> types = new ArrayList<>();
for (WorldType type : WorldType.values()) {
types.add(type.name().toLowerCase());
}
return types;
})
.build()) .build())
.add(CommandFlag.builder("--adjust-spawn") .add(CommandFlag.builder("--adjust-spawn")
.addAlias("-n") .addAlias("-n")

View File

@ -26,11 +26,12 @@ public class CommandFlag {
/** /**
* Creates a new flag. * Creates a new flag.
* *
* @param builder The builder. * @param key The key for the new flag.
* @param aliases The aliases that also refer to this flag.
*/ */
protected CommandFlag(@NotNull Builder<?> builder) { protected CommandFlag(@NotNull String key, @NotNull List<String> aliases) {
key = builder.key; this.key = key;
aliases = builder.aliases; this.aliases = aliases;
} }
/** /**
@ -57,8 +58,8 @@ public class CommandFlag {
* @param <S> The type of the builder. * @param <S> The type of the builder.
*/ */
public static class Builder<S extends Builder<?>> { public static class Builder<S extends Builder<?>> {
private final String key; protected final String key;
private final List<String> aliases; protected final List<String> aliases;
/** /**
* Create a new builder. * Create a new builder.
@ -87,7 +88,7 @@ public class CommandFlag {
* @return The flag. * @return The flag.
*/ */
public @NotNull CommandFlag build(){ public @NotNull CommandFlag build(){
return new CommandFlag(this); return new CommandFlag(key, aliases);
} }
} }
} }

View File

@ -1,12 +1,16 @@
package com.onarandombox.MultiverseCore.commandtools.flags; package com.onarandombox.MultiverseCore.commandtools.flags;
import java.util.Collection; import co.aikar.commands.InvalidCommandArgument;
import java.util.function.Function;
import java.util.function.Supplier;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/** /**
* Represents a flag with a value. * Represents a flag with a value.
* *
@ -24,6 +28,17 @@ public class CommandValueFlag<T> extends CommandFlag {
return new Builder<>(key, type); return new Builder<>(key, type);
} }
/**
* A builder for a flag with enum value.
*
* @param key The key for the new flag.
* @param type The type of the value, must be enum.
* @return The builder.
*/
public static @NotNull <T extends Enum<T>> EnumBuilder<T, ?> enumBuilder(@NotNull String key, @NotNull Class<T> type) {
return new EnumBuilder<>(key, type);
}
private final Class<T> type; private final Class<T> type;
private final boolean optional; private final boolean optional;
private final T defaultValue; private final T defaultValue;
@ -33,15 +48,29 @@ public class CommandValueFlag<T> extends CommandFlag {
/** /**
* Creates a new flag. * Creates a new flag.
* *
* @param builder The builder. * @param key The key for the new flag.
* @param aliases The aliases that also refer to this flag.
* @param type The type of the value.
* @param optional Allow for flag without value.
* @param defaultValue The default value if optional is true and user does not specify a value.
* @param context Function to parse string into value type.
* @param completion Function to get completion for this flag.
*/ */
protected CommandValueFlag(@NotNull Builder<T, ?> builder) { protected CommandValueFlag(
super(builder); @NotNull String key,
type = builder.type; @NotNull List<String> aliases,
optional = builder.optional; @NotNull Class<T> type,
defaultValue = builder.defaultValue; boolean optional,
context = builder.context; @Nullable T defaultValue,
completion = builder.completion; @Nullable Function<String, T> context,
@Nullable Supplier<Collection<String>> completion
) {
super(key, aliases);
this.type = type;
this.optional = optional;
this.defaultValue = defaultValue;
this.context = context;
this.completion = completion;
} }
/** /**
@ -96,11 +125,11 @@ public class CommandValueFlag<T> extends CommandFlag {
* @param <S> The type of the builder. * @param <S> The type of the builder.
*/ */
public static class Builder<T, S extends Builder<T, S>> extends CommandFlag.Builder<S> { public static class Builder<T, S extends Builder<T, S>> extends CommandFlag.Builder<S> {
private final Class<T> type; protected final Class<T> type;
private boolean optional = false; protected boolean optional = false;
private T defaultValue = null; protected T defaultValue = null;
private Function<String, T> context = null; protected Function<String, T> context = null;
private Supplier<Collection<String>> completion = null; protected Supplier<Collection<String>> completion = null;
/** /**
* Create a new builder. * Create a new builder.
@ -166,7 +195,77 @@ public class CommandValueFlag<T> extends CommandFlag {
if (context == null && !String.class.equals(type)) { if (context == null && !String.class.equals(type)) {
throw new IllegalStateException("Context is required for none-string value flags"); throw new IllegalStateException("Context is required for none-string value flags");
} }
return new CommandValueFlag<>(this); return new CommandValueFlag<>(key, aliases, type, optional, defaultValue, context, completion);
}
}
/**
* Specific builder for a flag with enum value.
*
* @param <T> The type of the value.
* @param <S> The type of the builder.
*/
public static class EnumBuilder<T extends Enum<T>, S extends EnumBuilder<T, S>> extends CommandFlag.Builder<S> {
protected final Class<T> type;
protected boolean optional = false;
protected T defaultValue = null;
protected Function<String, T> context = null;
protected Supplier<Collection<String>> completion = null;
public EnumBuilder(@NotNull String key, @NotNull Class<T> type) {
super(key);
this.type = type;
setEnumContext();
setEnumCompletion();
}
private void setEnumContext() {
this.context = (String value) -> {
try {
return Enum.valueOf(type, value.toUpperCase());
} catch (IllegalArgumentException e) {
throw new InvalidCommandArgument("Invalid value for argument " + key + ": " + value);
}
};
}
private void setEnumCompletion() {
List<String> types = Arrays.stream(type.getEnumConstants())
.map(type -> type.name().toLowerCase())
.collect(Collectors.toList());
this.completion = () -> types;
}
/**
* Set the flag as optional for users to specify a value.
*
* @return The builder.
*/
public @NotNull S optional() {
this.optional = true;
return (S) this;
}
/**
* Set the default value. Used if optional is true and user does not specify a value.
*
* @param defaultValue The default value.
* @return The builder.
*/
public @NotNull S defaultValue(@NotNull T defaultValue) {
this.defaultValue = defaultValue;
return (S) this;
}
/**
* Build the flag.
*
* @return The flag.
*/
@Override
public @NotNull CommandFlag build() {
return new CommandValueFlag<>(key, aliases, type, optional, defaultValue, context, completion);
} }
} }
} }