static Choice Argue(IArguable topic) { CurrentPosition = GetPosition(topic.Topic); while (true) { Console.WriteLine($"\nType your argument {CurrentPosition.ToString()} {topic.Topic} here, or:"); Console.WriteLine($"enter P to change your position on the topic of {topic.Topic}, X to choose another topic, 0 to quit.\n"); var choice = Console.ReadLine(); switch (choice) { case "0": return(Choice.Quit); case "X": return(Choice.ChangeTopic); case "P": CurrentPosition = GetPosition(topic.Topic); break; default: Console.WriteLine($"{Arguer.GetArgument(new Argument { Position = CurrentPosition })}\n"); break; } } }
/// <summary> /// Checks the validation of arguments at the specified index. /// </summary> private bool CheckArgumentValidation(IArguable comArgs, List <string> inputArgs, int index) { if (!string.IsNullOrEmpty(inputArgs[index]) && !comArgs.Arguments[index].IsValid(inputArgs[index])) { OnParseError(this, string.Format("Argument '{0}' is invalid. Must be a valid {1}.", comArgs.Arguments[index].Name, comArgs.Arguments[index].Rule.GetError())); return(true); } return(false); }
/// <summary> /// Resets the command's arguments back to their default values. /// </summary> private void ResetArgs(IArguable command) { foreach (var arg in command.Arguments) { arg.ResetValue(); if (arg.Arguments.Count > 0) { ResetArgs(arg); } } }
/// <summary> /// If the arguments are longer than they should be, merge them into the last one. /// This way a user does not need quotes for a chat message for example. /// </summary> private static void MergeLastArguments(bool recursive, Command command, IArguable comArgs, List <string> inputArgs, int i) { if ((i > 0 || i == comArgs.Arguments.Count - 1) && inputArgs.Count > command.Arguments.Count) { if (comArgs.Arguments.Count >= 1 + comArgs.Arguments[comArgs.Arguments.Count - 1].Arguments.Count && ((!recursive && !comArgs.Arguments[comArgs.Arguments.Count - 1].Enum) || recursive)) { var sb = new StringBuilder(); for (var j = command.Arguments.Count + (recursive && comArgs.Arguments.Count > 1 ? 1 : 0); j < inputArgs.Count; j++) { sb.Append(' ').Append(inputArgs[j]); } inputArgs[command.Arguments.Count - (recursive && comArgs.Arguments.Count > 1 ? 0 : 1)] += sb.ToString(); } } }
/// <summary> /// Parses the command's arguments or nested argument and recursively parses their children. /// </summary> /// <returns>True if an error has occurred during parsing and the calling loop should break.</returns> private bool ParseArguments(bool recursive, string commandText, Command command, IArguable comArgs, List <string> inputArgs, List <Argument> returnArgs) { //For each argument for (var i = 0; i < comArgs.Arguments.Count; i++) { //If the arguments are longer than they should be, merge them into the last one. //This way a user does not need quotes for a chat message for example. MergeLastArguments(recursive, command, comArgs, inputArgs, i); //If there are not enough arguments supplied, handle accordingly. if (i >= inputArgs.Count) { if (comArgs.Arguments[i].Optional) //If optional, we can quit and set a default value. { returnArgs.Add(comArgs.Arguments[i].SetValue(string.Empty)); continue; } //If not optional, show an error with the correct form. if (comArgs.Arguments[i].Enum) //Show list of types if enum (instead of argument name). { OnParseError(this, string.Format("Invalid arguments, {0} required. Usage: {1}", GenerateEnumArguments(comArgs.Arguments[i]), command.GenerateUsage(commandText))); } else { OnParseError(this, string.Format("Invalid arguments, '{0}' required. Usage: {1}", comArgs.Arguments[i].Name, command.GenerateUsage(commandText))); } return(true); } //If argument is an "enum" (Restricted to certain values), validate it. if (comArgs.Arguments[i].Enum) { //Check if passed value is a match for any of the possible values. var passed = comArgs.Arguments[i].Arguments.Any( arg => string.Equals(arg.Name, inputArgs[i], StringComparison.OrdinalIgnoreCase)); if (!passed) //If it was not found, alert the user, unless it is optional. { if (comArgs.Arguments[i].Optional && comArgs.Arguments[i].Default == string.Empty) { if (i != comArgs.Arguments.Count - 1) { continue; } } else if (comArgs.Arguments[i].Default != string.Empty && comArgs.Arguments[i].Arguments.Count > 0) //For enum arguments with default values, add the default value and then parse the children. { returnArgs.Add(comArgs.Arguments[i].SetValue(string.Empty)); //Find the argument that matches the default value. var argument = comArgs.Arguments[i].Arguments.FirstOrDefault( arg => string.Equals(arg.Name, comArgs.Arguments[i].Default, StringComparison.OrdinalIgnoreCase)); if (argument != null && argument.Arguments.Count > 0) { if (ParseArguments(true, commandText, command, argument, inputArgs, returnArgs)) { return(true); } if (i == comArgs.Arguments.Count - 1) { //If last argument, break, as no more input is expected break; } inputArgs.Insert(0, string.Empty); //Insert dummy data to fill inputArgs } else { OnParseError(this, string.Format("Argument '{0}' not recognized. Must be {1}", inputArgs[i].ToLower(), GenerateEnumArguments(comArgs.Arguments[i]))); return(true); } continue; } OnParseError(this, string.Format("Argument '{0}' not recognized. Must be {1}", inputArgs[i].ToLower(), GenerateEnumArguments(comArgs.Arguments[i]))); return(true); } //Set the argument to the selected "enum" value. returnArgs.Add(comArgs.Arguments[i].SetValue(inputArgs[i])); if (comArgs.Arguments[i].Arguments.Count > 0) //Parse its children. { //Find the nested arguments. var argument = comArgs.Arguments[i].Arguments.FirstOrDefault( arg => string.Equals(arg.Name, inputArgs[i], StringComparison.OrdinalIgnoreCase)); if (argument != null) { inputArgs.RemoveAt(0); //Remove the type we parsed. //Parse the value, to validate it if (ParseArguments(true, commandText, command, argument, inputArgs, returnArgs)) { return(true); } if (i == comArgs.Arguments.Count - 1) //If last argument, break, as no more input is expected { break; } inputArgs.Insert(0, string.Empty); //Insert dummy data to fill inputArgs //Now that the enum arg has been parsed, parse the remaining input, if any. } } continue; } //Check for validation rule. if (CheckArgumentValidation(comArgs, inputArgs, i)) { return(true); } //Set the value from the input argument if no errors were detected. returnArgs.Add(comArgs.Arguments[i].SetValue(inputArgs[i])); //If the next child argument is an "enum" (Only certain values allowed), then remove the current input argument. if ((comArgs.Arguments[i].Optional && comArgs.Arguments[i].Arguments.Count > 0 && !comArgs.Arguments[i].Arguments[0].Enum) || (comArgs.Arguments[i].Arguments.Count > 0 && comArgs.Arguments[i].Arguments[0].Enum)) { inputArgs.RemoveAt(0); } //If the argument has nested arguments, parse them recursively. if (comArgs.Arguments[i].Arguments.Count > 0) { return(ParseArguments(true, commandText, command, comArgs.Arguments[i], inputArgs, returnArgs)); } } return(false); }