✨ Begin working on the flag system
This commit is contained in:
parent
7bd0af0fef
commit
549fbd1d1d
5 changed files with 409 additions and 0 deletions
|
|
@ -0,0 +1,56 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2020 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.compound;
|
||||||
|
|
||||||
|
import cloud.commandframework.types.tuples.DynamicTuple;
|
||||||
|
import cloud.commandframework.types.tuples.Tuple;
|
||||||
|
import io.leangen.geantyref.TypeToken;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container for flag parsing logic. This should not be be used directly.
|
||||||
|
* Internally, a flag argument is a special case of a {@link CompoundArgument}.
|
||||||
|
*
|
||||||
|
* @param <C> Command sender type
|
||||||
|
*/
|
||||||
|
public class FlagArgument<C> extends CompoundArgument<DynamicTuple, C, DynamicTuple> {
|
||||||
|
|
||||||
|
FlagArgument(final @NonNull Tuple names,
|
||||||
|
final @NonNull Tuple parserTuple,
|
||||||
|
final @NonNull Tuple types,
|
||||||
|
final @NonNull Function<@NonNull DynamicTuple, @NonNull DynamicTuple> mapper,
|
||||||
|
final @NonNull TypeToken<DynamicTuple> valueType) {
|
||||||
|
super(false,
|
||||||
|
"flags",
|
||||||
|
names,
|
||||||
|
parserTuple,
|
||||||
|
types,
|
||||||
|
mapper,
|
||||||
|
DynamicTuple::of,
|
||||||
|
valueType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2020 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.flags;
|
||||||
|
|
||||||
|
import cloud.commandframework.Description;
|
||||||
|
import cloud.commandframework.arguments.CommandArgument;
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A flag is an optional command argument that may have an associated parser,
|
||||||
|
* and is identified by its name. Essentially, it's a mixture of a command literal
|
||||||
|
* and an optional variable command argument.
|
||||||
|
*
|
||||||
|
* @param <T> Command argument type. {@link Void} is used when no argument is present.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class CommandFlag<T> {
|
||||||
|
|
||||||
|
private final @NonNull String name;
|
||||||
|
private final @NonNull String @NonNull [] aliases;
|
||||||
|
private final @NonNull Description description;
|
||||||
|
|
||||||
|
private final @Nullable CommandArgument<?, T> commandArgument;
|
||||||
|
|
||||||
|
private CommandFlag(@NonNull final String name,
|
||||||
|
@NonNull final String @NonNull [] aliases,
|
||||||
|
@NonNull final Description description,
|
||||||
|
@Nullable final CommandArgument<?, T> commandArgument) {
|
||||||
|
this.name = name;
|
||||||
|
this.aliases = aliases;
|
||||||
|
this.description = description;
|
||||||
|
this.commandArgument = commandArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new flag builder
|
||||||
|
*
|
||||||
|
* @param name Flag name
|
||||||
|
* @return Flag builder
|
||||||
|
*/
|
||||||
|
public static @NonNull Builder<Void> newBuilder(@NonNull final String name) {
|
||||||
|
return new Builder<>(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the flag name
|
||||||
|
*
|
||||||
|
* @return Flag name
|
||||||
|
*/
|
||||||
|
public @NonNull String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all flag aliases. This does not include the flag name
|
||||||
|
*
|
||||||
|
* @return Flag aliases
|
||||||
|
*/
|
||||||
|
public @NonNull Collection<@NonNull String> getAliases() {
|
||||||
|
return Arrays.asList(this.aliases);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the flag description
|
||||||
|
* <p>
|
||||||
|
* Flag description
|
||||||
|
*/
|
||||||
|
public @NonNull Description getDescription() {
|
||||||
|
return this.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the command argument, if it exists
|
||||||
|
*
|
||||||
|
* @return Command argument, or {@code null}
|
||||||
|
*/
|
||||||
|
public @Nullable CommandArgument<?, T> getCommandArgument() {
|
||||||
|
return this.commandArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("--%s", this.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static final class Builder<T> {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final String[] aliases;
|
||||||
|
private final Description description;
|
||||||
|
private final CommandArgument<?, T> commandArgument;
|
||||||
|
|
||||||
|
private Builder(@NonNull final String name,
|
||||||
|
@NonNull final String[] aliases,
|
||||||
|
@NonNull final Description description,
|
||||||
|
@Nullable final CommandArgument<?, T> commandArgument) {
|
||||||
|
this.name = name;
|
||||||
|
this.aliases = aliases;
|
||||||
|
this.description = description;
|
||||||
|
this.commandArgument = commandArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Builder(@NonNull final String name) {
|
||||||
|
this(name, new String[0], Description.empty(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new builder instance using the given flag aliases
|
||||||
|
*
|
||||||
|
* @param aliases Flag aliases
|
||||||
|
* @return New builder instance
|
||||||
|
*/
|
||||||
|
public Builder<T> withAliases(@NonNull final String... aliases) {
|
||||||
|
return new Builder<>(this.name, aliases, this.description, this.commandArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new builder instance using the given flag description
|
||||||
|
*
|
||||||
|
* @param description Flag description
|
||||||
|
* @return New builder instance
|
||||||
|
*/
|
||||||
|
public Builder<T> withDescription(@NonNull final Description description) {
|
||||||
|
return new Builder<>(this.name, this.aliases, description, this.commandArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new builder instance using the given command argument
|
||||||
|
*
|
||||||
|
* @param argument Command argument
|
||||||
|
* @param <N> New argument type
|
||||||
|
* @return New builder instance
|
||||||
|
*/
|
||||||
|
public <N> Builder<N> withArgument(@NonNull final CommandArgument<?, N> argument) {
|
||||||
|
return new Builder<>(this.name, this.aliases, this.description, argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a new command flag instance
|
||||||
|
*
|
||||||
|
* @return Constructed instance
|
||||||
|
*/
|
||||||
|
public @NonNull CommandFlag<T> build() {
|
||||||
|
return new CommandFlag<>(this.name, this.aliases, this.description, this.commandArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2020 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.flags;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag value mappings
|
||||||
|
*/
|
||||||
|
public class FlagContext {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy object stored as a flag value when the flag has no associated parser
|
||||||
|
*/
|
||||||
|
public static final Object FLAG_PRESENCE_VALUE = new Object();
|
||||||
|
|
||||||
|
private final Map<String, Object> flagValues;
|
||||||
|
|
||||||
|
private FlagContext() {
|
||||||
|
this.flagValues = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new flag context instance
|
||||||
|
*
|
||||||
|
* @return Constructed instance
|
||||||
|
*/
|
||||||
|
public static @NonNull FlagContext create() {
|
||||||
|
return new FlagContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that a presence flag was supplied
|
||||||
|
*
|
||||||
|
* @param flag Flag instance
|
||||||
|
*/
|
||||||
|
public void addPresenceFlag(@NonNull final CommandFlag<?> flag) {
|
||||||
|
this.flagValues.put(flag.getName(), FLAG_PRESENCE_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a value associated with a value flag
|
||||||
|
*
|
||||||
|
* @param flag Value flag
|
||||||
|
* @param value Flag value
|
||||||
|
* @param <T> Value type
|
||||||
|
*/
|
||||||
|
public <T> void addValueFlag(@NonNull final CommandFlag<T> flag, @NonNull final T value) {
|
||||||
|
this.flagValues.put(flag.getName(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether or not a flag is present. This will return {@code false}
|
||||||
|
* for all value flags.
|
||||||
|
*
|
||||||
|
* @param flag Flag name
|
||||||
|
* @return {@code true} if the flag is presence and the flag is a presence flag,
|
||||||
|
* else {@code false}
|
||||||
|
*/
|
||||||
|
public boolean isPresent(@NonNull final String flag) {
|
||||||
|
final Object value = this.flagValues.get(flag);
|
||||||
|
return FLAG_PRESENCE_VALUE.equals(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a flag value
|
||||||
|
*
|
||||||
|
* @param name Flag name
|
||||||
|
* @param defaultValue Default value
|
||||||
|
* @param <T> Value type
|
||||||
|
* @return Stored value, or the supplied default value
|
||||||
|
*/
|
||||||
|
public <T> T getValue(@NonNull final String name, @NonNull final T defaultValue) {
|
||||||
|
final Object value = this.flagValues.get(name);
|
||||||
|
if (value == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked") final T casted = (T) value;
|
||||||
|
return casted;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
package cloud.commandframework.context;
|
package cloud.commandframework.context;
|
||||||
|
|
||||||
import cloud.commandframework.arguments.CommandArgument;
|
import cloud.commandframework.arguments.CommandArgument;
|
||||||
|
import cloud.commandframework.arguments.flags.FlagContext;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -39,6 +40,7 @@ import java.util.Optional;
|
||||||
public final class CommandContext<C> {
|
public final class CommandContext<C> {
|
||||||
|
|
||||||
private final Map<CommandArgument<C, ?>, ArgumentTiming> argumentTimings = new HashMap<>();
|
private final Map<CommandArgument<C, ?>, ArgumentTiming> argumentTimings = new HashMap<>();
|
||||||
|
private final FlagContext flagContext = FlagContext.create();
|
||||||
private final Map<String, Object> internalStorage = new HashMap<>();
|
private final Map<String, Object> internalStorage = new HashMap<>();
|
||||||
private final C commandSender;
|
private final C commandSender;
|
||||||
private final boolean suggestions;
|
private final boolean suggestions;
|
||||||
|
|
@ -164,6 +166,15 @@ public final class CommandContext<C> {
|
||||||
return Collections.unmodifiableMap(this.argumentTimings);
|
return Collections.unmodifiableMap(this.argumentTimings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the associated {@link FlagContext} instance
|
||||||
|
*
|
||||||
|
* @return Flag context
|
||||||
|
*/
|
||||||
|
public @NonNull FlagContext flags() {
|
||||||
|
return this.flagContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to track performance metrics related to command parsing. This is attached
|
* Used to track performance metrics related to command parsing. This is attached
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2020 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.types.tuples;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamic sized tuple backed by a {@code Object[]}
|
||||||
|
*/
|
||||||
|
public final class DynamicTuple implements Tuple {
|
||||||
|
|
||||||
|
private final Object[] internalArray;
|
||||||
|
|
||||||
|
private DynamicTuple(@NonNull final Object @NonNull [] internalArray) {
|
||||||
|
this.internalArray = internalArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new dynamic tuple, containing the given elements
|
||||||
|
*
|
||||||
|
* @param elements Elements that should be contained in the tuple
|
||||||
|
* @return Created tuple, preserving the order of the given elements
|
||||||
|
*/
|
||||||
|
public static @NonNull DynamicTuple of(@NonNull final Object... elements) {
|
||||||
|
return new DynamicTuple(elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final int getSize() {
|
||||||
|
return this.internalArray.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull Object @NonNull [] toArray() {
|
||||||
|
final @NonNull Object @NonNull [] newArray = new Object[this.internalArray.length];
|
||||||
|
System.arraycopy(this.internalArray, 0, newArray, 0, this.internalArray.length);
|
||||||
|
return newArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue