public static ESDOptions Parse(string[] cargs) { HashSet <char> invalid = new HashSet <char>(Path.GetInvalidPathChars()); Queue <string> args = new Queue <string>(cargs); List <Option> opts = new List <Option>(); bool isFlag(string arg) { // - by itself can be a valid arg return(arg.Length > 1 && arg.StartsWith("-")); } while (args.Count > 0) { string arg = args.Dequeue(); if (!isFlag(arg)) { throw new Exception($"Expected flag; got argument -{arg}"); } arg = arg.Substring(1); string getOnlyArg() { if (args.Count == 0 || isFlag(args.Peek())) { throw new Exception($"No value provided for flag -{arg}"); } return(args.Dequeue()); } List <string> getMultiArg() { List <string> ret = new List <string>(); while (args.Count > 0 && !isFlag(args.Peek())) { ret.Add(args.Dequeue()); } if (ret.Count == 0) { throw new Exception($"No value provided for flag -{arg}"); } return(ret); } void checkFilename(string path) { if (invalid.Overlaps(path)) { throw new Exception($"Invalid filename {path}"); } } Regex format = new Regex("%."); void checkTemplate(string path, string formats) { foreach (Match m in format.Matches(path)) { char ch = m.Groups[0].Value[1]; if (!formats.Contains(ch)) { throw new Exception($"Unknown format %{ch} for flag -{arg}"); } } } if (games.Names.ContainsKey(arg)) { opts.Add(new SetGame { Game = games.Names[arg] }); } else if (specFlags.Contains(arg)) { SetGameOpt opt = new SetGameOpt { Name = arg }; string val = getOnlyArg(); if (arg == "outdcx") { opt.Dcx = dcxs[val.ToLower()]; } else { opt.Value = val; } opts.Add(opt); } else if (arg == "cmdtype") { string val = getOnlyArg(); opts.Add(new SetCmdType { Type = cmdTypes[val] }); } else if (arg == "eddformat") { string val = getOnlyArg(); opts.Add(new SetEddFormat { Type = eddFormats[val] }); } else if (arg == "edddir") { string val = getOnlyArg(); checkFilename(val); opts.Add(new SetEddDir { DirName = val }); } else if (allFlags.Contains(arg)) { bool val = true; if (!defaultFlags.ContainsKey(arg)) { arg = arg.Substring(2); val = false; } opts.Add(new SetFlag { Name = arg, Value = val }); } else if (arg == "f") { List <string> vals = getMultiArg(); foreach (string val in vals) { if (!(val.StartsWith("c") || val.StartsWith("h") || val.StartsWith("m") || ESDName.IsKnownPrefix(val))) { throw new Exception($"Unrecognized filter value {val}"); } } opts.Add(new AddFilter { Name = vals }); } else if (arg == "i") { List <string> vals = getMultiArg(); foreach (string val in vals) { checkFilename(val); } opts.Add(new AddInput { Name = vals }); } else if (arg == "writebnd") { string val = getOnlyArg(); checkFilename(val); opts.Add(new WriteBnd { DirName = val }); } else if (arg == "writeloose") { string val = getOnlyArg(); checkFilename(val); checkTemplate(val, "e"); opts.Add(new WriteLoose { Template = val }); } else if (arg == "writepy") { string val = getOnlyArg(); checkFilename(val); checkTemplate(val, "ecm"); opts.Add(new WritePy { Template = val }); } else if (arg == "writeedd") { string val = getOnlyArg(); checkFilename(val); checkTemplate(val, "e"); if (!val.EndsWith(".edd.txt")) { throw new Exception("writeedd argument does not end with .edd.txt"); } opts.Add(new WriteEdd { Template = val }); } else if (arg == "info") { opts.Add(new Info()); } else { throw new Exception($"Unknown command line flag -{arg}"); } } return(new ESDOptions(opts)); }
public Option NextAction() { while (opts.Count > 0) { Option opt = opts.Dequeue(); if (opt is SetGame game) { Spec = ForGame(game.Game); EsdInputs.Clear(); ClearFilters(); } else if (opt is SetGameOpt gameOpt) { string val = gameOpt.Value; switch (gameOpt.Name) { case "basedir": Spec.GameDir = WindowsifyPath(val); break; case "esddir": Spec.EsdDir = WindowsifyPath(val); EsdInputs.Clear(); ClearFilters(); break; case "maps": Spec.MsbDir = val; break; case "names": Spec.NameDir = val; break; case "msgs": Spec.MsgDir = val; break; case "layouts": Spec.LayoutDir = WindowsifyPath(val); break; case "params": Spec.ParamFile = WindowsifyPath(val); break; case "outdcx": Spec.Dcx = gameOpt.Dcx; break; default: break; } if (Spec.GameDir == null) { throw new Exception($"Can't set {gameOpt.Name} without setting basedir first"); } } else if (opt is SetFlag flag) { Flags[flag.Name] = flag.Value; } else if (opt is AddFilter filter) { ClearFilters(); foreach (string val in filter.Name) { if (ESDName.IsKnownPrefix(val)) { Esds.Add(val); } else if (val.StartsWith("m")) { Maps.Add(val); } else if (val.StartsWith("c") || val.StartsWith("h")) { Chrs.Add(val); } else { throw new Exception($"Internal error: unknown filter {val}"); } } } else if (opt is AddInput input) { if (input.Name.Any(n => n.EndsWith(".py"))) { if (!input.Name.All(n => n.EndsWith(".py"))) { throw new Exception($"Some but not all input files ended in .py"); } PyInputs.Clear(); PyInputs.AddRange(input.Name); } else { foreach (string val in input.Name) { if (!(val.EndsWith(".esd") || val.EndsWith("esdbnd.dcx") || val.EndsWith(".esd.dcx"))) { throw new Exception($"ESD input files must end in .esd, .esdbnd.dcx, or .esd.dcx"); } } EsdInputs.Clear(); EsdInputs.AddRange(input.Name); } } else if (opt is SetCmdType cmd) { Type = cmd.Type; } else if (opt is SetEddFormat eddFormat) { EddFormat = eddFormat.Type; } else if (opt is SetEddDir eddDir) { EddDir = eddDir.DirName; } else { // All others are actions LastAction = opt; return(LastAction); } } if (LastAction == null) { LastAction = new Info(); return(LastAction); } return(null); }
private EzSembleContext LoadContext(string esdName) { return(LoadContext(options.Type == ESDOptions.CmdType.Unknown ? ESDName.GetCmdType(Path.GetFileNameWithoutExtension(esdName), options.Spec.Game) : options.Type)); }