internal static RootCommand CreateCommandLineOptions() { var rootCommand = new RootCommand { new Argument <string?>("workspace") { Arity = ArgumentArity.ZeroOrOne, Description = Resources.A_path_to_a_solution_file_a_project_file_or_a_folder_containing_a_solution_or_project_file_If_a_path_is_not_specified_then_the_current_directory_is_used }.LegalFilePathsOnly(), new Option(new[] { "--folder", "-f" }, Resources.Whether_to_treat_the_workspace_argument_as_a_simple_folder_of_files), new Option(new[] { "--fix-whitespace", "-w" }, Resources.Run_whitespace_formatting_Run_by_default_when_not_applying_fixes), new Option(new[] { "--fix-style", "-s" }, Resources.Run_code_style_analyzers_and_apply_fixes) { Argument = new Argument <string?>("severity") { Arity = ArgumentArity.ZeroOrOne }.FromAmong(SeverityLevels) }, new Option(new[] { "--fix-analyzers", "-a" }, Resources.Run_3rd_party_analyzers_and_apply_fixes) { Argument = new Argument <string?>("severity") { Arity = ArgumentArity.ZeroOrOne }.FromAmong(SeverityLevels) }, new Option(new[] { "--include" }, Resources.A_list_of_relative_file_or_folder_paths_to_include_in_formatting_All_files_are_formatted_if_empty) { Argument = new Argument <string[]>(() => Array.Empty <string>()) }, new Option(new[] { "--exclude" }, Resources.A_list_of_relative_file_or_folder_paths_to_exclude_from_formatting) { Argument = new Argument <string[]>(() => Array.Empty <string>()) }, new Option(new[] { "--check" }, Resources.Formats_files_without_saving_changes_to_disk_Terminates_with_a_non_zero_exit_code_if_any_files_were_formatted), new Option(new[] { "--report" }, Resources.Accepts_a_file_path_which_if_provided_will_produce_a_format_report_json_file_in_the_given_directory) { Argument = new Argument <string?>(() => null) { Name = "report-path" }.LegalFilePathsOnly() }, new Option(new[] { "--verbosity", "-v" }, Resources.Set_the_verbosity_level_Allowed_values_are_quiet_minimal_normal_detailed_and_diagnostic) { Argument = new Argument <string?>() { Arity = ArgumentArity.ExactlyOne }.FromAmong(VerbosityLevels) }, new Option(new[] { "--include-generated" }, Resources.Include_generated_code_files_in_formatting_operations) { IsHidden = true }, }; rootCommand.Description = "dotnet-format"; rootCommand.AddValidator(EnsureFolderNotSpecifiedWhenFixingStyle); rootCommand.AddValidator(EnsureFolderNotSpecifiedWhenFixingAnalyzers); return(rootCommand); }
/// <summary> /// Build the RootCommand for parsing /// </summary> /// <returns>RootCommand</returns> public static RootCommand BuildRootCommand() { RootCommand root = new RootCommand { Name = "WebValidate", Description = "Validate API responses", TreatUnmatchedTokensAsErrors = true }; root.AddOption(new Option <string>(new string[] { "-s", "--server" }, ParseString, true, "Server to test")); root.AddOption(new Option <List <string> >(new string[] { "-f", "--files" }, ParseStringList, true, "List of files to test")); root.AddOption(new Option <int>(new string[] { "-l", "--sleep" }, ParseInt, true, "Sleep (ms) between each request")); root.AddOption(new Option <string>(new string[] { "-u", "--base-url" }, ParseString, true, "Base url for files")); root.AddOption(new Option <bool>(new string[] { "-v", "--verbose" }, ParseBool, true, "Display verbose results")); root.AddOption(new Option <bool>(new string[] { "-r", "--run-loop" }, ParseBool, true, "Run test in an infinite loop")); root.AddOption(new Option <bool>(new string[] { "--random" }, ParseBool, true, "Run requests randomly (requires --run-loop)")); root.AddOption(new Option <int>(new string[] { "--duration" }, ParseInt, true, "Test duration (seconds) (requires --run-loop)")); root.AddOption(new Option <int>(new string[] { "-t", "--timeout" }, ParseInt, true, "Request timeout (seconds)")); root.AddOption(new Option <int>(new string[] { "--max-concurrent" }, ParseInt, true, "Max concurrent requests")); root.AddOption(new Option <int>(new string[] { "--max-errors" }, ParseInt, true, "Max validation errors")); root.AddOption(new Option <string>(new string[] { "--telemetry-name" }, ParseString, true, "App Insights application name")); root.AddOption(new Option <string>(new string[] { "--telemetry-key" }, ParseString, true, "App Insights key")); root.AddOption(new Option <bool>(new string[] { "-d", "--dry-run" }, "Validates configuration")); // these require access to --run-loop so are added at the root level root.AddValidator(ValidateRunLoopDependencies); root.AddValidator(ValidateTelemetry); return(root); }
internal static RootCommand CreateCommandLineOptions() { var rootCommand = new RootCommand { new Argument<string>("project") { Arity = ArgumentArity.ZeroOrOne, Description = Resources.The_solution_or_project_file_to_operate_on_If_a_file_is_not_specified_the_command_will_search_the_current_directory_for_one }, new Option(new[] { "--folder", "-f" }, Resources.Whether_to_treat_the_project_path_as_a_folder_of_files) { Argument = new Argument<string?>(() => null) { Arity = ArgumentArity.ZeroOrOne }, }, new Option(new[] { "--workspace", "-w" }, Resources.The_solution_or_project_file_to_operate_on_If_a_file_is_not_specified_the_command_will_search_the_current_directory_for_one) { Argument = new Argument<string?>(() => null), IsHidden = true }, new Option(new[] { "--include", "--files" }, Resources.A_list_of_relative_file_or_folder_paths_to_include_in_formatting_All_files_are_formatted_if_empty) { Argument = new Argument<string[]>(() => Array.Empty<string>()) }, new Option(new[] { "--exclude" }, Resources.A_list_of_relative_file_or_folder_paths_to_exclude_from_formatting) { Argument = new Argument<string[]>(() => Array.Empty<string>()) }, new Option(new[] { "--check", "--dry-run" }, Resources.Formats_files_without_saving_changes_to_disk_Terminates_with_a_non_zero_exit_code_if_any_files_were_formatted) { Argument = new Argument<bool>() }, new Option(new[] { "--report" }, Resources.Accepts_a_file_path_which_if_provided_will_produce_a_format_report_json_file_in_the_given_directory) { Argument = new Argument<string?>(() => null) }, new Option(new[] { "--verbosity", "-v" }, Resources.Set_the_verbosity_level_Allowed_values_are_quiet_minimal_normal_detailed_and_diagnostic) { Argument = new Argument<string?>() { Arity = ArgumentArity.ExactlyOne } }, new Option(new[] { "--include-generated" }, Resources.Include_generated_code_files_in_formatting_operations) { Argument = new Argument<bool>(), IsHidden = true }, }; rootCommand.Description = "dotnet-format"; rootCommand.AddValidator(ValidateProjectArgumentAndWorkspace); rootCommand.AddValidator(ValidateProjectArgumentAndFolder); rootCommand.AddValidator(ValidateWorkspaceAndFolder); return rootCommand; }
/// <summary> /// Build the RootCommand for parsing /// </summary> /// <returns>RootCommand</returns> public static RootCommand BuildRootCommand() { RootCommand root = new RootCommand { Name = "loderunner", Description = "Validate API responses", TreatUnmatchedTokensAsErrors = true, }; root.AddOption(new Option <List <string> >(new string[] { "-s", "--server" }, Parsers.ParseStringList, true, "Server(s) to test")); root.AddOption(new Option <List <string> >(new string[] { "-f", "--files" }, Parsers.ParseStringList, true, "List of files to test")); root.AddOption(new Option <string>(new string[] { "--zone" }, Parsers.ParseString, true, "Zone for logging")); root.AddOption(new Option <string>(new string[] { "--region" }, Parsers.ParseString, true, "Region for logging")); root.AddOption(new Option <bool>(new string[] { "-p", "--prometheus" }, Parsers.ParseBool, true, "Send metrics to Prometheus")); root.AddOption(new Option <string>(new string[] { "--tag" }, Parsers.ParseString, true, "Tag for logging")); root.AddOption(new Option <int>(new string[] { "-l", "--sleep" }, Parsers.ParseIntGTZero, true, "Sleep (ms) between each request")); root.AddOption(new Option <bool>(new string[] { "-j", "--strict-json" }, Parsers.ParseBool, true, "Use strict json when parsing")); root.AddOption(new Option <string>(new string[] { "-u", "--base-url" }, Parsers.ParseString, true, "Base url for files")); root.AddOption(new Option <bool>(new string[] { "-v", "--verbose" }, Parsers.ParseBool, true, "Display verbose results")); root.AddOption(new Option <bool>(new string[] { "-r", "--run-loop" }, Parsers.ParseBool, true, "Run test in an infinite loop")); root.AddOption(new Option <bool>(new string[] { "--verbose-errors" }, Parsers.ParseBool, true, "Log verbose error messages")); root.AddOption(new Option <bool>(new string[] { "--random" }, Parsers.ParseBool, true, "Run requests randomly (requires --run-loop)")); root.AddOption(new Option <int>(new string[] { "--duration" }, Parsers.ParseIntGTZero, true, "Test duration (seconds) (requires --run-loop)")); root.AddOption(new Option <int>(new string[] { "--summary-minutes" }, Parsers.ParseIntGTZero, true, "Display summary results (minutes) (requires --run-loop)")); root.AddOption(new Option <int>(new string[] { "-t", "--timeout" }, Parsers.ParseIntGTZero, true, "Request timeout (seconds)")); root.AddOption(new Option <int>(new string[] { "--max-concurrent" }, Parsers.ParseIntGTZero, true, "Max concurrent requests")); root.AddOption(new Option <int>(new string[] { "--max-errors" }, Parsers.ParseIntGTZero, true, "Max validation errors")); root.AddOption(new Option <int>(new string[] { "--delay-start" }, Parsers.ParseIntGTZero, true, "Delay test start (seconds)")); root.AddOption(new Option <bool>(new string[] { "-d", "--dry-run" }, "Validates configuration")); // these require access to --run-loop so are added at the root level root.AddValidator(ValidateRunLoopDependencies); return(root); }
public static RootCommand GetRootCommand() { var rootCommand = new RootCommand(); rootCommand.Name = "nrustlightning-cli"; rootCommand.Description = "CLI interface for requesting to NRustLightning server"; foreach (var op in GetOptions()) { rootCommand.Add(op); } foreach (var sub in GetSubCommands()) { rootCommand.AddCommand(sub); } rootCommand.AddValidator(result => { var hasNetwork = result.Children.Contains("network"); if (result.Children.Contains("mainnet") && hasNetwork) { return("You cannot specify both '--network' and '--mainnet'"); } if (result.Children.Contains("testnet") && hasNetwork) { return("You cannot specify both '--network' and '--testnet'"); } if (result.Children.Contains("regtest") && hasNetwork) { return("You cannot specify both '--network' and '--regtest'"); } return(null); }); return(rootCommand); }
[Fact] // https://github.com/dotnet/command-line-api/issues/1573 public void Multiple_validators_on_the_same_command_do_not_report_duplicate_errors() { var command = new RootCommand(); command.AddValidator(result => result.ErrorMessage = "Wrong"); command.AddValidator(_ => { }); var parseResult = command.Parse(""); parseResult.Errors .Should() .ContainSingle() .Which .Message .Should() .Be("Wrong"); }
internal static RootCommand CreateCommandLineOptions() { // Sync changes to option and argument names with the FormatCommant.Handler above. var rootCommand = new RootCommand { new Argument <string?>("workspace", () => null, Resources.A_path_to_a_solution_file_a_project_file_or_a_folder_containing_a_solution_or_project_file_If_a_path_is_not_specified_then_the_current_directory_is_used).LegalFilePathsOnly(), new Option <bool>(new[] { "--no-restore" }, Resources.Doesnt_execute_an_implicit_restore_before_formatting), new Option <bool>(new[] { "--folder", "-f" }, Resources.Whether_to_treat_the_workspace_argument_as_a_simple_folder_of_files), new Option <bool>(new[] { "--fix-whitespace", "-w" }, Resources.Run_whitespace_formatting_Run_by_default_when_not_applying_fixes), new Option(new[] { "--fix-style", "-s" }, Resources.Run_code_style_analyzers_and_apply_fixes, argumentType: typeof(string), arity: ArgumentArity.ZeroOrOne) { ArgumentHelpName = "severity" }.FromAmong(SeverityLevels), new Option(new[] { "--fix-analyzers", "-a" }, Resources.Run_3rd_party_analyzers_and_apply_fixes, argumentType: typeof(string), arity: ArgumentArity.ZeroOrOne) { ArgumentHelpName = "severity" }.FromAmong(SeverityLevels), new Option <string[]>(new[] { "--diagnostics" }, () => Array.Empty <string>(), Resources.A_space_separated_list_of_diagnostic_ids_to_use_as_a_filter_when_fixing_code_style_or_3rd_party_issues), new Option <string[]>(new[] { "--include" }, () => Array.Empty <string>(), Resources.A_list_of_relative_file_or_folder_paths_to_include_in_formatting_All_files_are_formatted_if_empty), new Option <string[]>(new[] { "--exclude" }, () => Array.Empty <string>(), Resources.A_list_of_relative_file_or_folder_paths_to_exclude_from_formatting), new Option <bool>(new[] { "--check" }, Resources.Formats_files_without_saving_changes_to_disk_Terminates_with_a_non_zero_exit_code_if_any_files_were_formatted), new Option(new[] { "--report" }, Resources.Accepts_a_file_path_which_if_provided_will_produce_a_format_report_json_file_in_the_given_directory, argumentType: typeof(string), arity: ArgumentArity.ZeroOrOne) { ArgumentHelpName = "report-path" }.LegalFilePathsOnly(), new Option <string>(new[] { "--verbosity", "-v" }, Resources.Set_the_verbosity_level_Allowed_values_are_quiet_minimal_normal_detailed_and_diagnostic).FromAmong(VerbosityLevels), new Option <bool>(new[] { "--include-generated" }, Resources.Include_generated_code_files_in_formatting_operations) { IsHidden = true }, new Option(new[] { "--binarylog" }, Resources.Log_all_project_or_solution_load_information_to_a_binary_log_file, argumentType: typeof(string), arity: ArgumentArity.ZeroOrOne) { ArgumentHelpName = "binary-log-path" }.LegalFilePathsOnly(), }; rootCommand.Description = "dotnet-format"; rootCommand.AddValidator(EnsureFolderNotSpecifiedWhenFixingStyle); rootCommand.AddValidator(EnsureFolderNotSpecifiedWhenFixingAnalyzers); rootCommand.AddValidator(EnsureFolderNotSpecifiedWithNoRestore); rootCommand.AddValidator(EnsureFolderNotSpecifiedWhenLoggingBinlog); return(rootCommand); }
public static RootCommand InitializeCommands(IServiceScope scope) { var argAccountname = new Argument("accountname") { Arity = ArgumentArity.ExactlyOne, Description = "Accountname. Must be a text." }; var argUsername = new Argument("username") { Arity = ArgumentArity.ExactlyOne, Description = "Username. Must be a text." }; var argPassword = new Argument("password") { Arity = ArgumentArity.ExactlyOne, Description = "User password. Must meet minimum security requirements." }; CommandWithExamples createAccount = new CommandWithExamples( "-createaccount", "Creates a new account in database with provided accountname, username and password.", new[] { "%1 -createaccount Some!Demo_Accountname Some!Username Some!Password" } ) { argAccountname, argUsername, argPassword }; var account = scope.ServiceProvider.GetService <IAccountRepository>(); createAccount.Handler = CommandHandler.Create( (string accountname, string username, string password) => InitializeCreateAccount(account, accountname, username, password)); var optionStartup = new Option("-startup", "Start a SPV Channel rest server"); RootCommand root = new RootCommand("Start a SPV Channel rest server when invoked without parameters. Manage users when invoked with additional parameters.") { createAccount, optionStartup }; root.AddValidator(symbol => { if (symbol.Children.Count == 0) { return("Starting application without parameters is not allowed."); } return(String.Empty); }); root.Handler = CommandHandler.Create <string>((startup) => { }); return(root); }
public static int Main(string[] args) { var rootCommand = new RootCommand("A tool for obfuscating file names."); rootCommand.AddValidator(x => "Select a command to continue. Run --help for more information."); var obfuscationCommand = CreateObfuscationCommand(); rootCommand.AddCommand(obfuscationCommand); var deobfuscate = CreateDeobfuscationCommand(); rootCommand.AddCommand(deobfuscate); return(rootCommand.Invoke(args)); }
public void All_custom_validators_are_called(string commandLine) { var commandValidatorWasCalled = false; var optionValidatorWasCalled = false; var argumentValidatorWasCalled = false; var option = new Option <string>("-o"); option.AddValidator(_ => { optionValidatorWasCalled = true; return(null); }); var argument = new Argument <string>("the-arg"); argument.AddValidator(_ => { argumentValidatorWasCalled = true; return(null); }); var rootCommand = new RootCommand { option, argument }; rootCommand.AddValidator(_ => { commandValidatorWasCalled = true; return(null); }); rootCommand.Invoke(commandLine); commandValidatorWasCalled.Should().BeTrue(); optionValidatorWasCalled.Should().BeTrue(); argumentValidatorWasCalled.Should().BeTrue(); }
static async Task Main(string [] args) { if (args.Length == 1 && IsUrl(args[0])) { await Run(args [0]); return; } const string options = "Options include: Xamarin.Android, Xamarin.iOS, Xamarin.Mac, and Mono."; var rootCommand = new RootCommand { new Option( "--url", "A URL to a pkg or vsix file to install") { Argument = new Argument <string>() }, new Option( "--stable", $"Install the latest *stable* version of a product from VS manifests. {options}") { Argument = new Argument <string>() }, new Option( "--preview", $"Install the latest *preview* version of a product from VS manifests. {options}") { Argument = new Argument <string>() }, }; rootCommand.Name = "boots"; rootCommand.AddValidator(Validator); rootCommand.Description = $"boots {Version} File issues at: https://github.com/jonathanpeppers/boots/issues"; rootCommand.Handler = CommandHandler.Create <string, string, string> (Run); await rootCommand.InvokeAsync(args); }
/// <summary> /// Build the RootCommand for parsing /// </summary> /// <returns>RootCommand</returns> public static RootCommand BuildRootCommand() { RootCommand root = new RootCommand { Name = "DataService", Description = "NGSA Data Service", TreatUnmatchedTokensAsErrors = true, }; // add the options root.AddOption(new Option <int>(new string[] { "--cache-duration" }, () => 300, "Cache for duration (seconds)")); root.AddOption(new Option <bool>(new string[] { "--in-memory" }, "Use in-memory database")); root.AddOption(new Option <bool>(new string[] { "--no-cache" }, "Don't cache results")); root.AddOption(new Option <int>(new string[] { "--perf-cache" }, "Cache only when load exceeds value")); root.AddOption(new Option <string>(new string[] { "--secrets-volume" }, () => "secrets", "Secrets Volume Path")); root.AddOption(new Option <LogLevel>(new string[] { "-l", "--log-level" }, () => LogLevel.Warning, "Log Level")); root.AddOption(new Option <bool>(new string[] { "-d", "--dry-run" }, "Validates configuration")); // validate dependencies root.AddValidator(ValidateDependencies); return(root); }
public static RootCommand GetRootCommand() { var rootCommand = new RootCommand(); rootCommand.Name = "nrustlightning-cli"; rootCommand.Description = "CLI interface for requesting to NRustLightning server"; foreach (var op in GetOptions()) { rootCommand.Add(op); } foreach (var sub in GetSubCommands()) { rootCommand.AddCommand(sub); } rootCommand.AddValidator(result => { var hasNetwork = result.Children.Contains("network"); var hasMainnet = result.Children.Contains("mainnet"); var hasTestNet = result.Children.Contains("testnet"); var hasRegtest = result.Children.Contains("regtest"); int count = 0; foreach (var flag in new bool[] { hasNetwork, hasMainnet, hasTestNet, hasRegtest }) { if (flag) { count++; } } if (count > 1) { return("You cannot specify more than one network."); } return(null); }); return(rootCommand); }
/// <summary> /// Entry point for `perlang`, with the possibility to override the console streams (stdin, stdout, stderr). /// </summary> /// <param name="args">The command line arguments.</param> /// <param name="console">A custom `IConsole` implementation to use. May be null, in which case the standard /// streams of the calling process will be used.</param> /// <returns>Zero if the program executed successfully; non-zero otherwise.</returns> public static int MainWithCustomConsole(string[] args, IConsole console) { var versionOption = new Option(new[] { "--version", "-v" }, "Show version information"); var detailedVersionOption = new Option("-V", "Show detailed version information"); var evalOption = new Option <string>("-e", "Executes a single-line script") { AllowMultipleArgumentsPerToken = false, ArgumentHelpName = "script" }; var printOption = new Option <string>("-p", "Parse a single-line script and output a human-readable version of the AST") { ArgumentHelpName = "script" }; var noWarnAsErrorOption = new Option <string>("-Wno-error", "Treats specified warning as a warning instead of an error.") { ArgumentHelpName = "error" }; var disabledWarningsAsErrorsList = new List <WarningType>(); noWarnAsErrorOption.AddValidator(result => { string warningName = result.GetValueOrDefault <string>(); if (!WarningType.KnownWarning(warningName)) { return($"Unknown warning: {warningName}"); } disabledWarningsAsErrorsList.Add(WarningType.Get(warningName)); return(null); }); // Note: options must be present in this list to be valid for the RootCommand. var options = new[] { versionOption, detailedVersionOption, evalOption, printOption, noWarnAsErrorOption }; var scriptNameArgument = new Argument <string> { Name = "script-name", Arity = ArgumentArity.ZeroOrOne, }; scriptNameArgument.AddValidator(result => { var tokens = result.Parent !.Tokens; if (tokens.Any(t => t.Type == System.CommandLine.Parsing.TokenType.Option && t.Value == evalOption.Name)) { return("<script-name> positional argument cannot be used together with the -e option"); } return(null); }); var rootCommand = new RootCommand { Description = "The Perlang Interpreter", Handler = CommandHandler.Create((ParseResult parseResult, IConsole console) => { if (parseResult.HasOption(versionOption)) { console.Out.WriteLine(CommonConstants.InformationalVersion); return(Task.FromResult(0)); } if (parseResult.HasOption(detailedVersionOption)) { console.Out.WriteLine($"Perlang {CommonConstants.InformationalVersion} (built from git commit {CommonConstants.GitCommit}) on .NET {Environment.Version}"); console.Out.WriteLine(); console.Out.WriteLine($" Number of detected (v)CPUs: {Environment.ProcessorCount}"); console.Out.WriteLine($" Running in 64-bit mode: {Environment.Is64BitProcess}"); console.Out.WriteLine($" Operating system info: {Environment.OSVersion.VersionString}"); console.Out.WriteLine(); return(Task.FromResult(0)); } if (parseResult.HasOption(evalOption)) { // TODO: Workaround until we have a command-line-api package with https://github.com/dotnet/command-line-api/pull/1271 included. OptionResult optionResult = parseResult.FindResultFor(evalOption); string source = optionResult.Children .Where(c => c.Symbol.Name == evalOption.ArgumentHelpName) .Cast <ArgumentResult>() .First() .GetValueOrDefault <string>(); var program = new Program( replMode: true, standardOutputHandler: console.Out.WriteLine, disabledWarningsAsErrors: disabledWarningsAsErrorsList ); int result = program.Run(source, program.CompilerWarning); return(Task.FromResult(result)); } else if (parseResult.HasOption(printOption)) { // TODO: Workaround until we have a command-line-api package with https://github.com/dotnet/command-line-api/pull/1271 included. OptionResult optionResult = parseResult.FindResultFor(printOption); string source = optionResult.Children .Where(c => c.Symbol.Name == evalOption.ArgumentHelpName) .Cast <ArgumentResult>() .First() .GetValueOrDefault <string>(); new Program( replMode: true, standardOutputHandler: console.Out.WriteLine, disabledWarningsAsErrors: disabledWarningsAsErrorsList ).ParseAndPrint(source); return(Task.FromResult(0)); } else if (parseResult.Tokens.Count == 0) { new Program( replMode: true, standardOutputHandler: console.Out.WriteLine, disabledWarningsAsErrors: disabledWarningsAsErrorsList ).RunPrompt(); return(Task.FromResult(0)); } else { string scriptName = parseResult.ValueForArgument(scriptNameArgument); int result; if (parseResult.Tokens.Count == 1) { var program = new Program( replMode: false, standardOutputHandler: console.Out.WriteLine, disabledWarningsAsErrors: disabledWarningsAsErrorsList ); result = program.RunFile(scriptName); } else { // The first token available in RootCommandResult.Tokens at this point is the script name. // All remaining arguments are passed to the program, which can use methods on the ARGV // object to retrieve them. var remainingArguments = parseResult.RootCommandResult.Tokens.Skip(1) .Take(parseResult.Tokens.Count - 1) .Select(r => r.Value); var program = new Program( replMode: false, arguments: remainingArguments, standardOutputHandler: console.Out.WriteLine, disabledWarningsAsErrors: disabledWarningsAsErrorsList ); result = program.RunFile(scriptName); } return(Task.FromResult(result)); } }) }; rootCommand.AddArgument(scriptNameArgument); rootCommand.AddValidator(result => { if (result.HasOption(evalOption) && result.HasOption(printOption)) { return("Error: the -e and -p options are mutually exclusive"); } if (result.HasOption(evalOption) && result.HasArgument(scriptNameArgument)) { return("Error: the -e option cannot be combined with the <script-name> argument"); } return(null); }); var scriptArguments = new Argument <string> { Name = "args", Arity = ArgumentArity.ZeroOrMore }; rootCommand.AddArgument(scriptArguments); foreach (Option option in options) { rootCommand.AddOption(option); } return(new CommandLineBuilder(rootCommand) .UseDefaults() .Build() .Invoke(args, console)); }
/// <summary> /// Build the RootCommand for parsing /// </summary> /// <returns>RootCommand</returns> public static RootCommand BuildRootCommand() { RootCommand root = new RootCommand { Name = "complex-app", Description = "Validate API responses", TreatUnmatchedTokensAsErrors = true }; // create options with validators Option serverOption = new Option(new string[] { "-s", "--server" }, "Server to test") { Argument = new Argument <string>(), Required = true }; serverOption.AddValidator(v => { const string errorMessage = "--server must be 3 - 20 characters [a-z][0-9]"; if (v.Tokens == null || v.Tokens.Count != 1 || v.Tokens[0].Value == null || v.Tokens[0].Value.Length < 3 || v.Tokens[0].Value.Length > 20) { return(errorMessage); } return(string.Empty); }); Option filesOption = new Option(new string[] { "-f", "--files" }, "List of files to test") { Argument = new Argument <List <string> >(() => new List <string> { "baseline.json" }) }; filesOption.AddValidator(v => { string ret = string.Empty; if (v.Tokens.Count != 0) { foreach (Token t in v.Tokens) { if (!CheckFileExists(t.Value)) { if (string.IsNullOrEmpty(ret)) { ret = "File not found: " + t.Value; } else { ret = ret.Replace("File ", "Files ", StringComparison.Ordinal); ret += ", " + t.Value; } } } } return(ret); }); Option timeoutOption = new Option(new string[] { "-t", "--timeout" }, "Request timeout (seconds)") { Argument = new Argument <int>(() => 30) }; timeoutOption.AddValidator(ValidateIntGTEZero); Option sleepOption = new Option(new string[] { "-l", "--sleep" }, "Sleep (ms) between each request") { Argument = new Argument <int>() }; sleepOption.AddValidator(ValidateIntGTEZero); Option durationOption = new Option(new string[] { "--duration" }, "Test duration (seconds) (requires --run-loop)") { Argument = new Argument <int>(() => 0) }; durationOption.AddValidator(ValidateIntGTEZero); Option maxConcurrentOption = new Option(new string[] { "--max-concurrent" }, "Max concurrent requests") { Argument = new Argument <int>(() => 100) }; maxConcurrentOption.AddValidator(ValidateIntGTEZero); Option maxErrorsOption = new Option(new string[] { "--max-errors" }, "Max validation errors") { Argument = new Argument <int>(() => 10) }; maxErrorsOption.AddValidator(ValidateIntGTEZero); Option telemetryOption = new Option(new string[] { "--telemetry" }, "App Insights name and key") { Argument = new Argument <List <string> >() }; telemetryOption.AddValidator(v => { if (v.Tokens.Count != 2) { return("--telemetry requires appName and appKey parameters"); } return(string.Empty); }); root.AddOption(serverOption); root.AddOption(filesOption); root.AddOption(sleepOption); root.AddOption(new Option(new string[] { "-v", "--verbose" }, "Display verbose results") { Argument = new Argument <bool>() }); root.AddOption(new Option(new string[] { "-r", "--run-loop" }, "Run test in an infinite loop") { Argument = new Argument <bool>(() => false) }); root.AddOption(new Option(new string[] { "--random" }, "Run requests randomly (requires --run-loop)") { Argument = new Argument <bool>(() => false) }); root.AddOption(durationOption); root.AddOption(timeoutOption); root.AddOption(maxConcurrentOption); root.AddOption(maxErrorsOption); root.AddOption(telemetryOption); root.AddOption(new Option(new string[] { "-d", "--dry-run" }, "Validates configuration") { Argument = new Argument <bool>() }); // these require access to --run-loop so are added at the root level root.AddValidator(ValidateDuration); root.AddValidator(ValidateRandom); return(root); }