/// <summary> /// Parse the indicated string table /// </summary> /// <param name="args"></param> public void Parse(string[] args) { // // This parser attempts to emulate, roughly, the behavior // of the POSIX getopt C runtime function for parsing // command line arguments. This mechanism is fairly // easy to use as it is quite flexible in how it // lets you submit arguments for parsing. // // For example, all of these would be valid and equivalent // command line arguments if you had flags // p, q, and z where z takes an argument. // // -p -q -z7 // -p -q -z 7 // -pqz7 // -p -qz7 // // -p -qz "7" // -p -qz"7" // // The main difference between this parser and getopt, however, // is that with getopt you have to do command handling dispatch // yourself in a big switch statement. This parser does // the dispatching automatically leveraging C#'s Action<> convention. // // This parser also provides a slightly more cumbersome syntax for // specifying arguments, but by paying this syntax tax, you get the // benefit of a help screen that can be generated automatically // for you based on the list of command arguments you supply to the // parser. This reduces the common burden a writer of a command line // tool has. It also ensures that the help screen for the application // is always up to date whenever new flags or arguments are added // to the tool. // // // reset the tracking collections for unknown and missing // required commands // ResetTrackingCollections(); // // first, we merge the whole command line into a single string // since we're going to have to parse char by char // ///******************************************************* ///Update ///Update, by this way, we can use another args inputs ///var args = Environment.GetCommandLineArgs(); //var joined = String.Join(" ", args.Skip(1).ToArray()); // // we keep track of all commands dispatched to determine if // any commands that are required were not supplied // var dispatchedCommands = new List <CommandArgument>(); // // these are the state variables that are used to track what's // going on in the command line as we walk character by character // through it. // bool isLongArg = false; CommandArgument currentCommand = null; // // now we walk through the characters of the array until // we determine if we've found a matching switch // foreach (String arg in args.Skip(1)) { if (IsArgStart(arg)) { // // we check if we're about to deal with a long argument // isLongArg = IsLongArg(arg); String argName; if (!isLongArg) { argName = arg.Substring(1, arg.Length - 1); } else { argName = arg.Substring(2, arg.Length - 2); } currentCommand = GetCommand(argName, isLongArg); if (currentCommand != null) { // // if the current command doesn't take a parameter, // then we just dispatch it to it's handler // if (CommandArgumentFlags.FlagDisabled(currentCommand.Flags, CommandArgumentFlags.TakesParameter)) { dispatchedCommands.Add(currentCommand); currentCommand = DispatchCommand(currentCommand, String.Empty); } } } else { // // if we've reached a new arg, but there is a current // command, that means we've been gathering a parameter // for it and it needs to be dispatched now. // if (currentCommand != null) { dispatchedCommands.Add(currentCommand); currentCommand = DispatchCommand(currentCommand, arg); } else if ((currentCommand == null) && !String.IsNullOrEmpty(arg.Trim())) { this.unknownCommands.Add(arg); } } } // // now that we're done with all the dispatching, we need to determine // if there were any required commands that didn't get supplied // and store that set for the caller to use // this.missingRequired = DetermineMissingRequiredCommands(dispatchedCommands); }
private CommandArgument DispatchCommand(CommandArgument ca, string param) { ca.Action(this, param.Trim()); return(null); }