implement switches

This commit is contained in:
dfsek
2021-03-08 00:52:57 -07:00
parent 0cd5898107
commit 026a6066d3
7 changed files with 102 additions and 21 deletions
@@ -6,15 +6,15 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
public final class ExecutionState { public final class ExecutionState {
private final Set<String> flags = new HashSet<>(); private final Set<String> switches = new HashSet<>();
private final Map<String, String> args = new HashMap<>(); private final Map<String, String> args = new HashMap<>();
protected ExecutionState() { protected ExecutionState() {
} }
protected void addFlag(String flag) { protected void addSwitch(String flag) {
flags.add(flag); switches.add(flag);
} }
protected void addArgument(String arg, String value) { protected void addArgument(String arg, String value) {
@@ -39,7 +39,7 @@ public final class ExecutionState {
return (T) value; return (T) value;
} }
public boolean hasFlag(String flag) { public boolean hasSwitch(String flag) {
return flags.contains(flag); return switches.contains(flag);
} }
} }
@@ -3,9 +3,11 @@ package com.dfsek.terra.api.command;
import com.dfsek.terra.api.command.annotation.Argument; import com.dfsek.terra.api.command.annotation.Argument;
import com.dfsek.terra.api.command.annotation.Command; import com.dfsek.terra.api.command.annotation.Command;
import com.dfsek.terra.api.command.annotation.Subcommand; import com.dfsek.terra.api.command.annotation.Subcommand;
import com.dfsek.terra.api.command.annotation.Switch;
import com.dfsek.terra.api.command.exception.CommandException; import com.dfsek.terra.api.command.exception.CommandException;
import com.dfsek.terra.api.command.exception.InvalidArgumentsException; import com.dfsek.terra.api.command.exception.InvalidArgumentsException;
import com.dfsek.terra.api.command.exception.MalformedCommandException; import com.dfsek.terra.api.command.exception.MalformedCommandException;
import com.dfsek.terra.api.command.exception.SwitchFormatException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList; import java.util.ArrayList;
@@ -62,14 +64,25 @@ public class TerraCommandManager implements CommandManager {
String arg = args.get(0); String arg = args.get(0);
if(arg.startsWith("-")) { // flags have started. if(arg.startsWith("-")) { // switches have started.
if(req) throw new InvalidArgumentsException("Flags must come after arguments."); if(req) throw new InvalidArgumentsException("Switches must come after arguments.");
break; break;
} }
state.addArgument(argument.value(), args.remove(0)); state.addArgument(argument.value(), args.remove(0));
} }
while(!args.isEmpty()) {
String aSwitch = args.remove(0);
if(!aSwitch.startsWith("-")) throw new SwitchFormatException("Invalid switch \"" + aSwitch + "\"");
String val = aSwitch.substring(1); // remove dash
if(!commandHolder.switches.containsKey(val)) throw new SwitchFormatException("No such switch \"" + aSwitch + "\"");
state.addSwitch(commandHolder.switches.get(val));
}
invoke(commandClass, state); invoke(commandClass, state);
} }
@@ -91,6 +104,7 @@ public class TerraCommandManager implements CommandManager {
private static final class CommandHolder { private static final class CommandHolder {
private final Class<? extends CommandTemplate> clazz; private final Class<? extends CommandTemplate> clazz;
private final Map<String, CommandHolder> subcommands = new HashMap<>(); private final Map<String, CommandHolder> subcommands = new HashMap<>();
private final Map<String, String> switches = new HashMap<>();
private CommandHolder(Class<? extends CommandTemplate> clazz) { private CommandHolder(Class<? extends CommandTemplate> clazz) {
this.clazz = clazz; this.clazz = clazz;
@@ -103,6 +117,12 @@ public class TerraCommandManager implements CommandManager {
subcommands.put(alias, holder); subcommands.put(alias, holder);
} }
} }
for(Switch aSwitch : command.switches()) {
switches.put(aSwitch.value(), aSwitch.value());
for(String alias : aSwitch.aliases()) {
switches.put(alias, aSwitch.value());
}
}
} }
} }
} }
@@ -10,7 +10,7 @@ import java.lang.annotation.Target;
public @interface Command { public @interface Command {
Argument[] arguments() default {}; Argument[] arguments() default {};
Flag[] flags() default {}; Switch[] switches() default {};
Subcommand[] subcommands() default {}; Subcommand[] subcommands() default {};
@@ -7,10 +7,8 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE) @Target(ElementType.ANNOTATION_TYPE)
public @interface Flag { public @interface Switch {
String value(); String value();
String shorthand() default ""; String[] aliases() default {};
String defaultValue() default "";
} }
@@ -0,0 +1,13 @@
package com.dfsek.terra.api.command.exception;
public class SwitchFormatException extends CommandException {
private static final long serialVersionUID = -965858989317844628L;
public SwitchFormatException(String message) {
super(message);
}
public SwitchFormatException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -2,18 +2,21 @@ package com.dfsek.terra.commands.structure;
import com.dfsek.terra.api.command.CommandTemplate; import com.dfsek.terra.api.command.CommandTemplate;
import com.dfsek.terra.api.command.ExecutionState; import com.dfsek.terra.api.command.ExecutionState;
import com.dfsek.terra.api.command.annotation.Argument;
import com.dfsek.terra.api.command.annotation.Command; import com.dfsek.terra.api.command.annotation.Command;
import com.dfsek.terra.api.command.annotation.Flag; import com.dfsek.terra.api.command.annotation.Switch;
@Command( @Command(
flags = { arguments = {
@Flag(value = "rotation", @Argument(
defaultValue = "0", value = "rotation",
shorthand = "r" required = false,
), type = int.class
@Flag(value = "load", )
defaultValue = "FULL", },
shorthand = "l" switches = {
@Switch(value = "chunk",
aliases = "c"
) )
} }
) )
@@ -7,6 +7,7 @@ import com.dfsek.terra.api.command.TerraCommandManager;
import com.dfsek.terra.api.command.annotation.Argument; import com.dfsek.terra.api.command.annotation.Argument;
import com.dfsek.terra.api.command.annotation.Command; import com.dfsek.terra.api.command.annotation.Command;
import com.dfsek.terra.api.command.annotation.Subcommand; import com.dfsek.terra.api.command.annotation.Subcommand;
import com.dfsek.terra.api.command.annotation.Switch;
import com.dfsek.terra.api.command.exception.CommandException; import com.dfsek.terra.api.command.exception.CommandException;
import com.dfsek.terra.api.command.exception.InvalidArgumentsException; import com.dfsek.terra.api.command.exception.InvalidArgumentsException;
import com.dfsek.terra.api.command.exception.MalformedCommandException; import com.dfsek.terra.api.command.exception.MalformedCommandException;
@@ -64,6 +65,24 @@ public class CommandTest {
} }
} }
@Test
public void switches() throws CommandException {
CommandManager manager = new TerraCommandManager();
manager.register("test", DemoSwitchCommand.class);
manager.execute("test", Arrays.asList("first", "2"));
manager.execute("test", Arrays.asList("first", "2", "3.4"));
manager.execute("test", Arrays.asList("first", "2", "-a"));
manager.execute("test", Arrays.asList("first", "2", "3.4", "-b"));
manager.execute("test", Arrays.asList("first", "2", "-aSwitch"));
manager.execute("test", Arrays.asList("first", "2", "3.4", "-bSwitch"));
manager.execute("test", Arrays.asList("first", "2", "-aSwitch", "-b"));
manager.execute("test", Arrays.asList("first", "2", "3.4", "-bSwitch", "-a"));
}
@Command( @Command(
arguments = { arguments = {
@Argument(value = "arg0"), @Argument(value = "arg0"),
@@ -84,6 +103,34 @@ public class CommandTest {
} }
} }
@Command(
arguments = {
@Argument(value = "arg0"),
@Argument(value = "arg1", type = int.class),
@Argument(value = "arg2", type = double.class, required = false)
},
switches = {
@Switch(value = "a", aliases = {"aSwitch"}),
@Switch(value = "b", aliases = {"bSwitch"})
}
)
public static final class DemoSwitchCommand implements CommandTemplate {
@Override
public void execute(ExecutionState state) {
System.out.println(state.getArgument("arg0", String.class));
System.out.println(state.getArgument("arg1", int.class));
try {
System.out.println(state.getArgument("arg2", double.class));
} catch(IllegalArgumentException e) {
System.out.println("arg2 undefined.");
}
System.out.println("A: " + state.hasSwitch("a"));
System.out.println("B: " + state.hasSwitch("b"));
}
}
@Command( @Command(
arguments = { arguments = {
@Argument(value = "arg0"), @Argument(value = "arg0"),