public static KeyValuePair <string, IArgumentTaker> MakeOption(string optionName, IArgumentTaker argTaker) => new KeyValuePair <string, IArgumentTaker>(optionName, argTaker);
public CommandMatch Match(CommandConfig config, string commandAndArgs, MessageFlags messageFlags) { if ((messageFlags & RequiredFlags) != RequiredFlags) { // one or more required flags not set return(null); } if ((messageFlags & ForbiddenFlags) != 0) { // one or more forbidden flags set return(null); } string commandMatched = null; foreach (string commandName in CommandNames) { if (!commandAndArgs.StartsWith(commandName)) { // not this command continue; } if (commandAndArgs.Length == commandName.Length) { // this command without arguments commandMatched = commandName; break; } if (char.IsWhiteSpace(commandAndArgs, commandName.Length)) { // this command followed by whitespace commandMatched = commandName; break; } } if (commandMatched == null) { // not this command return(null); } string argumentsToGo = commandAndArgs.Substring(commandMatched.Length); bool keepTakingOptions = true; ImmutableList <KeyValuePair <string, object> > .Builder seenOptions = ImmutableList.CreateBuilder <KeyValuePair <string, object> >(); ImmutableList <object> .Builder args = ImmutableList.CreateBuilder <object>(); for (;;) { bool optionMatched = false; if (keepTakingOptions) { string startTrimmedToGo = argumentsToGo.TrimStart(); // forced end of options? if (startTrimmedToGo.StartsWith("--")) { if (startTrimmedToGo.Length == 2 || char.IsWhiteSpace(startTrimmedToGo, 2)) { // lone "--" option; stop taking options keepTakingOptions = false; argumentsToGo = startTrimmedToGo.Substring(2); continue; } } // options foreach (KeyValuePair <string, IArgumentTaker> option in Options) { bool thisOption = false; if (startTrimmedToGo.StartsWith(option.Key)) { // might be this option if (startTrimmedToGo.Length == option.Key.Length) { // it is, as the last option thisOption = true; } else { Debug.Assert(startTrimmedToGo.Length > option.Key.Length); if (startTrimmedToGo[option.Key.Length] == '=' || char.IsWhiteSpace(startTrimmedToGo, option.Key.Length)) { // it is, followed by a space or an equals sign thisOption = true; } } } if (!thisOption) { // not this one continue; } // attempt to match the value // (the equals sign, if it follows, is sent to the taker!) object optValue; string optRest = option.Value.Take(startTrimmedToGo.Substring(option.Key.Length), out optValue); if (optRest == null) { // the option name matched but its argument didn't continue; } // matched! seenOptions.Add(new KeyValuePair <string, object>(option.Key, optValue)); argumentsToGo = optRest; optionMatched = true; break; } } if (optionMatched) { continue; } // argument? IArgumentTaker upcomingArgumentTaker = Arguments .Skip(args.Count) .FirstOrDefault(); if (upcomingArgumentTaker == null) { // there should be no more arguments if (argumentsToGo.Trim().Length > 0) { // but there are; it's not this command return(null); } // good; let's get out of this loop break; } object argValue; string argRest = upcomingArgumentTaker.Take(argumentsToGo, out argValue); if (argRest == null) { // taking the argument failed; it's not this command return(null); } args.Add(argValue); argumentsToGo = argRest; } // command parsed successfully return(new CommandMatch( this, commandMatched, seenOptions.ToImmutable(), args.ToImmutable(), messageFlags )); }