package game.command; import java.util.List; import java.util.Map; import java.util.Set; import game.collect.Lists; import game.collect.Maps; import game.collect.Sets; public class ArgumentSplitter { private final String command; private final Map arguments; private final CommandEnvironment env; protected ArgumentSplitter(Map arguments, String command, CommandEnvironment env) { this.arguments = arguments; this.command = command; this.env = env; } private static String joinArgs(Iterable iter) { StringBuilder sb = new StringBuilder("'"); for(T obj : iter) { if(sb.length() > 1) sb.append("', '"); sb.append(String.valueOf(obj)); } return sb.append("'").toString(); } public static ArgumentSplitter parseArgs(CommandEnvironment env, String str, String[] argv, CachedExecutable cached) { Map parameters = cached.getParameters(); List positionals = Lists.newArrayList(cached.getPositionals()); // String[] argv = ArgumentParser.splitString(str); Map args = Maps.newHashMap(); int ppos = 0; boolean parse = true; for(int z = 1; z < argv.length; z++) { String arg = argv[z]; Parameter param = null; boolean pos = false; if(parse && arg.equals("--")) { parse = false; continue; } else if(parse && (arg.startsWith("--") || (arg.startsWith("-") && arg.length() == 2))) { param = parameters.get(arg.substring(arg.startsWith("--") ? 2 : 1)); if(param != null && param.isPositional() && !args.containsKey(param.getName())) { for(int n = 0; n < positionals.size(); n++) { if(param == positionals.get(n)) { positionals.remove(n); break; } } } } else if(ppos < positionals.size()) { param = positionals.get(ppos++); pos = true; } else { throw new RunException("Position %d: Parameter '%s' ist überflüssig", z, arg); } if(param == null) throw new RunException("Position %d: Argument '%s' ist unbekannt", z, arg); if(args.containsKey(param.getName())) throw new RunException("Position %d: Parameter '%s' mehrfach angegeben", z, param.getName()); int nargs = param.getParsers().size(); // if(!pos) // z += 1; if(z + (pos ? 0 : 1) + nargs > argv.length) if(nargs == 1 && param.getName().equals(param.getParsers().get(0).getName())) throw new RunException("Position %d: Argument '%s' benötigt einen Parameter", z, param.getName()); else throw new RunException("Position %d: Argument '%s' benötigt %d Parameter (%s)", z, param.getName(), nargs, joinArgs(param.getParsers())); Map params = Maps.newHashMapWithExpectedSize(nargs); String[] inputs = new String[nargs + (pos ? 0 : 1)]; int apos = 0; for(int n = pos ? 0 : 1; n < nargs + (pos ? 0 : 1); n++) { String par = inputs[n] = argv[z + n]; ArgumentParser parser = param.getParsers().get(apos); if(parse && (par.startsWith("--") || (par.startsWith("-") && par.length() == 2))) if(nargs == 1 && param.getName().equals(parser.getName())) throw new RunException("Position %d: Argument '%s': '%s' als Parameter verwendet", z + n, param.getName(), par); else throw new RunException("Position %d: Argument '%s': '%s' als Parameter '%s' (#%d) verwendet", z + n, param.getName(), par, parser.getName(), apos + 1); try { params.put(parser.getName(), parser.parse(env, par)); } catch(Throwable e) { if(nargs == 1 && param.getName().equals(parser.getName())) throw new RunException(e, "Position %d: Argument '%s': Parameter konnte nicht interpretiert werden", z + n, param.getName()); else throw new RunException(e, "Position %d: Argument '%s': Parameter '%s' (#%d) konnte nicht interpretiert werden", z + n, param.getName(), parser.getName(), apos + 1); } apos += 1; } if(!pos) inputs[0] = arg; args.put(param.getName(), new Argument(param, z, inputs, params)); z += nargs - (pos ? 1 : 0); } for(Parameter param : parameters.values()) { if(!args.containsKey(param.getName())) { if(param.isRequired()) { for(ArgumentParser parser : param.getParsers()) { if(parser.getDefault(env) == null) throw new RunException("Argument '%s' muss angegeben werden", param.getName()); } } else if(param.getParsers().isEmpty()) { continue; } Map params = Maps.newHashMapWithExpectedSize(param.getParsers().size()); for(ArgumentParser parser : param.getParsers()) { params.put(parser.getName(), parser.getDefault(env)); } args.put(param.getName(), new Argument(param, -1, null, params)); } } return new ArgumentSplitter(args, str, env); } private static String[] getParam(CommandEnvironment env, String[] argv, CachedExecutable cached) { Map parameters = cached.getParameters(); List positionals = Lists.newArrayList(cached.getPositionals()); Set args = Sets.newHashSet(); int ppos = 0; boolean parse = true; for(int z = 1; z < argv.length; z++) { String arg = argv[z]; Parameter param = null; boolean pos = false; if(z == argv.length - 1) { if(ppos < positionals.size()) { param = positionals.get(ppos); if(param.getParsers().isEmpty()) // np return null; return param.getParsers().get(0).getCompletions(env); } else { return null; } } else if(parse && arg.equals("--")) { parse = false; continue; } else if(parse && (arg.startsWith("--") || (arg.startsWith("-") && arg.length() == 2))) { param = parameters.get(arg.substring(arg.startsWith("--") ? 2 : 1)); if(param != null && param.isPositional() && !args.contains(param.getName())) { for(int n = 0; n < positionals.size(); n++) { if(param == positionals.get(n)) { positionals.remove(n); break; } } } } else if(ppos < positionals.size()) { param = positionals.get(ppos++); pos = true; } else { return null; } if(param == null || args.contains(param.getName())) return null; int nargs = param.getParsers().size(); // if(z + (pos ? 0 : 1) + nargs > argv.length - 1) { // return param.getParsers().get(argv.length - z).getCompletions(env); // } int apos = 0; for(int n = pos ? 0 : 1; n < nargs + (pos ? 0 : 1); n++) { if(z + n == argv.length - 1) return param.getParsers().get(apos).getCompletions(env); String par = argv[z + n]; if(parse && (par.startsWith("--") || (par.startsWith("-") && par.length() == 2))) return null; apos += 1; } args.add(param.getName()); z += nargs - (pos ? 1 : 0); } return null; } public static String[] parseComplete(CommandEnvironment env, String[] argv, CachedExecutable cached, String last) { String[] comp = getParam(env, argv, cached); if(comp == null || comp.length == 0) { Set params = Sets.newTreeSet(); boolean all = last.startsWith("--"); for(String param : cached.getParameters().keySet()) { if(all || param.length() == 1) params.add(param.length() == 1 ? "-" + param : ("--" + param)); } comp = params.toArray(new String[params.size()]); } return comp; } // public ScriptArg getArg(String name) { // return this.arguments.get(name); // } public boolean hasArg(String name) { return this.arguments.containsKey(name); } // public boolean has(String name, String par) { // return this.arguments.containsKey(name) && this.arguments.get(name).getValues().containsKey(par); // } // public boolean has(String name) { // return this.has(name, name); // } // public T getDefault(String name, String par, T def) { // ScriptArg arg = this.arguments.get(name); // if(arg == null) // return def; // Object value = arg.getValues().get(par); // return value == null ? def : (T)value; // } // // public T getDefault(String name, T def) { // return this.getDefault(name, name, def); // } // // public T getUnchecked(String name, String par) { // return this.getDefault(name, par, null); // } public T getUnchecked(String name, String par) { Argument arg = this.arguments.get(name); if(arg == null) return null; Object value = arg.getValues().get(par); return value == null ? null : (T)value; } // public T getUnchecked(String name) { // return this.getDefault(name, null); // } // // public boolean getBool(String name, boolean def) { // return this.getDefault(name, def); // } // // public boolean getBool(String name) { // return this.getUnchecked(name); // } // // public > T getEnum(String name, T def) { // return this.getDefault(name, def); // } // // public > T getEnum(String name) { // return this.getUnchecked(name); // } // // public int getInt(String name, int def) { // return this.getDefault(name, def); // } // // public int getInt(String name) { // return this.getUnchecked(name); // } // // public long getLong(String name, long def) { // return this.getDefault(name, def); // } // // public long getLong(String name) { // return this.getUnchecked(name); // } // // public double getDouble(String name, double def) { // return this.getDefault(name, def); // } // // public double getDouble(String name) { // return this.getUnchecked(name); // } // // public String getString(String name, String def) { // return this.getDefault(name, def); // } // // public String getString(String name) { // return this.getUnchecked(name); // } // // public String[] getStrings(String name, String[] def) { // return this.getDefault(name, def); // } // // public String[] getStrings(String name) { // return this.getUnchecked(name); // } // // public Entity getEntity(String name, Entity def) { // return this.getDefault(name, def); // } // // public Entity getEntity(String name) { // return this.getUnchecked(name); // } // // public EntityLiving getLiving(String name, EntityLiving def) { // return this.getDefault(name, def); // } // // public EntityLiving getLiving(String name) { // return this.getUnchecked(name); // } // // public EntityNPC getNpc(String name, EntityNPC def) { // return this.getDefault(name, def); // } // // public EntityNPC getNpc(String name) { // return this.getUnchecked(name); // } // // public Block getBlock(String name, Block def) { // return this.getDefault(name, def); // } // // public Block getBlock(String name) { // return this.getUnchecked(name); // } // // public State getState(String name, State def) { // return this.getDefault(name, def); // } // // public State getState(String name) { // return this.getUnchecked(name); // } // // public Item getItem(String name, Item def) { // return this.getDefault(name, def); // } // // public Item getItem(String name) { // return this.getUnchecked(name); // } // // public ItemStack getStack(String name, ItemStack def) { // return this.getDefault(name, def); // } // // public ItemStack getStack(String name) { // return this.getUnchecked(name); // } // // public BlockPos getColumnPos(String name, BlockPos def) { // return this.hasArg(name) ? this.getColumnPos(name) : def; // } // // public BlockPos getColumnPos(String name) { // return new BlockPos(this.getUnchecked(name, "x"), 0, this.getUnchecked(name, "z")); // } // // public BlockPos getBlockPos(String name, BlockPos def) { // return this.hasArg(name) ? this.getBlockPos(name) : def; // } // // public BlockPos getBlockPos(String name) { // return new BlockPos(this.getUnchecked(name, "x"), this.getUnchecked(name, "y"), this.getUnchecked(name, "z")); // } // // public WorldPos getWorldPos(String name, WorldPos def) { // return this.hasArg(name) ? this.getWorldPos(name) : def; // } // // public WorldPos getWorldPos(String name) { // return new WorldPos(this.getUnchecked(name, "x"), this.getUnchecked(name, "y"), this.getUnchecked(name, "z"), // this.getUnchecked(name, "dim")); // } // // public Vec3 getVector2D(String name, Vec3 def) { // return this.hasArg(name) ? this.getVector2D(name) : def; // } // // public Vec3 getVector2D(String name) { // return new Vec3(this.getUnchecked(name, "x"), 0.0, this.getUnchecked(name, "z")); // } // // public Vec3 getVector(String name, Vec3 def) { // return this.hasArg(name) ? this.getVector(name) : def; // } // // public Vec3 getVector(String name) { // return new Vec3(this.getUnchecked(name, "x"), this.getUnchecked(name, "y"), this.getUnchecked(name, "z")); // } // // public WorldServer getWorld(String name) { // return this.getUnchecked(name); // } // // public NBTTagCompound getTag(String name) { // return this.getUnchecked(name); // } }