- l10n
- generating help messages
- different arguments for one command
(like
teleport <playerTo>
ANDteleport <playerFrom> <playerTo>
- context (for command issuer, language settings etc.)
- aliases
- async support
Last active
November 9, 2019 08:33
-
-
Save SirYwell/f520bfcae0afe367037b8d1e4fe1cbe3 to your computer and use it in GitHub Desktop.
Raw draft oft Commandry
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.eldoria.commandry; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.RetentionPolicy; | |
@Retention(RetentionPolicy.RUNTIME) | |
public @interface Command { | |
String value(); | |
String parent() default ""; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.eldoria.commandry; | |
public interface CommandResult { | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.eldoria.commandry; | |
import de.eldoria.commandry.parser.Parsers; | |
import de.eldoria.commandry.tree.CommandNode; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Method; | |
import java.lang.reflect.Parameter; | |
import java.util.Arrays; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.stream.Collectors; | |
public class Commandry { | |
private static CommandNode root = new CommandNode(); | |
public static void runCommand(String command) { | |
StringReader reader = new StringReader(command); | |
run(reader, new Object[0], root); | |
} | |
private static void run(StringReader reader, Object[] params, CommandNode parent) { | |
String cmd = reader.readWord(); | |
if (parent.children.containsKey(cmd)) { | |
var node = parent.children.get(cmd); | |
Parameter[] parameters = node.method.getParameters(); | |
Object[] paramValues = new Object[parameters.length]; | |
for (int i = 0; i < parameters.length; i++) { | |
Parameter parameter = parameters[i]; | |
if (params.length > i) { | |
paramValues[i] = params[i]; | |
continue; // copy params of old method | |
} | |
if (!reader.canRead()) { | |
System.out.println("Command usage..."); | |
return; | |
} | |
paramValues[i] = Parsers.parse(reader.readWord(), parameter.getType()); | |
} | |
if (!reader.canRead()) { | |
try { | |
node.method.invoke(node.commandObject, paramValues); | |
} catch (IllegalAccessException | InvocationTargetException e) { | |
e.printStackTrace(); | |
} | |
} else { | |
run(reader, paramValues, node); | |
} | |
} | |
} | |
public static <T> void registerCommand(Class<T> clazz) { | |
LinkedList<Method> methods = new LinkedList<>(findMethods(clazz)); | |
System.out.println(methods); | |
while (!methods.isEmpty()) { | |
Method method = methods.getFirst(); | |
Command command = method.getAnnotation(Command.class); | |
CommandNode node = new CommandNode(); | |
node.commandObject = createObject(clazz); | |
node.name = command.value(); | |
node.method = method; | |
if (command.parent().isEmpty()) { | |
System.out.println("root command added " + command.value()); | |
root.children.put(command.value(), node); | |
methods.poll(); | |
} else { | |
if (root.children.containsKey(command.parent())) { | |
root.children.get(command.parent()).children.put(command.value(), node); | |
methods.poll(); | |
} | |
} | |
} | |
} | |
private static Object createObject(Class<?> clazz) { | |
try { | |
return clazz.getConstructor().newInstance(); | |
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
private static <T> List<Method> findMethods(Class<T> clazz) { | |
Method[] methods = clazz.getMethods(); | |
return Arrays.stream(methods) | |
.filter(method -> { | |
Command annotation = method.getAnnotation(Command.class); | |
return annotation != null; | |
}) | |
.sorted((m1, m2) -> { | |
Command a1 = m1.getAnnotation(Command.class); | |
Command a2 = m2.getAnnotation(Command.class); | |
int c = a1.parent().compareTo(a2.parent()); | |
return c != 0 ? c : a1.value().compareTo(a2.value()); | |
}) | |
.collect(Collectors.toList()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.eldoria.commandry.parser; | |
public interface Parser<T> { | |
T parse(CharSequence sequence); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.eldoria.commandry.parser; | |
import java.util.HashMap; | |
import java.util.Map; | |
public final class Parsers { | |
private static Map<Class<?>, Parser<?>> parserMap = new HashMap<>(); | |
static { | |
parserMap.put(int.class, (Parser<Integer>) sequence -> Integer.parseInt(sequence.toString())); | |
parserMap.put(String.class, CharSequence::toString); | |
} | |
public static <T> T parse(String input, Class<T> clazz) { | |
return (T) parserMap.get(clazz).parse(input); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.eldoria.commandry; | |
public class StringReader { | |
private final String string; | |
private final int length; | |
private int position; | |
private int mark; | |
public StringReader(String string) { | |
this.string = string; | |
this.length = string.length(); | |
this.position = 0; | |
this.mark = 0; | |
} | |
public String readWord() { | |
if (!canRead()) { | |
throw new StringIndexOutOfBoundsException(position); | |
} | |
while (position < length && peekChar() == ' ') { // ignore leading spaces | |
position++; | |
} | |
int start = position; | |
while (position < length && peekChar() != ' ') { | |
position++; | |
} | |
int end = position; | |
if (position < length) { | |
position++; // skip space | |
} | |
return string.substring(start, end); | |
} | |
public String readRemaining() { | |
if (position == 0) { | |
return string; | |
} | |
if (!canRead()) { | |
throw new StringIndexOutOfBoundsException(position); | |
} | |
int start = position; | |
position = length; | |
return string.substring(start); | |
} | |
public boolean canRead() { | |
return position < length; | |
} | |
public void reset() { | |
this.position = mark; | |
} | |
private char peekChar() { | |
return string.charAt(position); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.eldoria.commandry; | |
import java.util.Scanner; | |
public class Test { | |
public static void main(String[] args) { | |
Commandry.registerCommand(Test.class); | |
Scanner scanner = new Scanner(System.in); | |
while (true) { | |
Commandry.runCommand(scanner.nextLine()); | |
} | |
} | |
@Command("user") | |
public void myCommand(String user) { | |
System.out.println("Hi " + user); | |
} | |
@Command(value = "age", parent = "user") | |
public void second(String user, int age) { | |
System.out.println(user + " is " + age + " years old."); | |
} | |
@Command("userage") | |
public void third(String user, int age) { | |
System.out.println(user + " is " + age + " years old."); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.eldoria.commandry.tree; | |
import java.lang.reflect.Method; | |
import java.util.HashMap; | |
import java.util.Map; | |
public class CommandNode { | |
public String name; | |
public Method method; | |
public Object commandObject; | |
public Map<String, CommandNode> children = new HashMap<>(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment