using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Microsoft.Extensions.CommandLineUtils; namespace QuantConnect.Configuration { /// /// Command Line application parser /// public static class ApplicationParser { /// /// This function will parse args based on options and will show application name, version, help /// /// The application name to be shown /// The application description to be shown /// The application help text /// The command line arguments /// The applications command line available options /// To show help when no command line arguments were provided /// The user provided options. Key is option name public static Dictionary Parse(string applicationName, string applicationDescription, string applicationHelpText, string[] args, List options, bool noArgsShowHelp = false) { var application = new CommandLineApplication { Name = applicationName, Description = applicationDescription, ExtendedHelpText = applicationHelpText }; application.HelpOption("-?|-h|--help"); // This is a helper/shortcut method to display version info - it is creating a regular Option, with some defaults. // The default help text is "Show version Information" application.VersionOption("-v|-V|--version", () => $"Version {Assembly.GetEntryAssembly().GetCustomAttribute()?.InformationalVersion}"); var optionsObject = new Dictionary(); var listOfOptions = new List(); foreach (var option in options) { listOfOptions.Add(application.Option($"--{option.Name}", option.Description, option.Type)); } application.OnExecute(() => { foreach (var commandOption in listOfOptions.Where(option => option.HasValue())) { var optionKey = commandOption.Template.Replace("--", ""); var matchingOption = options.Find(o => o.Name == optionKey); switch (matchingOption.Type) { // Booleans, string and numbers case CommandOptionType.NoValue: case CommandOptionType.SingleValue: optionsObject[optionKey] = ParseTypedArgument(commandOption.Value()); break; // Parsing nested objects case CommandOptionType.MultipleValue: var keyValuePairs = commandOption.Value().Split(','); var subDictionary = new Dictionary(); foreach (var keyValuePair in keyValuePairs) { var subKeys = keyValuePair.Split(':'); subDictionary[subKeys[0]] = ParseTypedArgument(subKeys.Length > 1 ? subKeys[1] : ""); } optionsObject[optionKey] = subDictionary; break; default: throw new ArgumentOutOfRangeException(); } } return 0; }); application.Execute(args); if (noArgsShowHelp && args.Length == 0) { application.ShowHelp(); } return optionsObject; } private static object ParseTypedArgument(string value) { if (value == "true" || value == "false") { return value == "true"; } double numericValue; if (double.TryParse(value, out numericValue)) { return numericValue; } return value; } } }