public void A_custom_validator_can_be_added_to_an_option() { var option = new Option <int>("-x"); option.AddValidator(r => { var value = r.GetValueOrDefault <int>(); return($"Option {r.Token.Value} cannot be set to {value}"); }); var command = new RootCommand { option }; var result = command.Parse("-x 123"); result.Errors .Should() .ContainSingle(e => e.SymbolResult.Symbol == option) .Which .Message .Should() .Be("Option -x cannot be set to 123"); }
public void Validators_on_global_options_are_executed_when_invoking_a_subcommand(string commandLine) { var option = new Option <FileInfo>("--file"); option.AddValidator(r => { return("Invoked validator"); }); var subCommand = new Command("subcommand"); var rootCommand = new RootCommand { subCommand }; rootCommand.AddGlobalOption(option); var result = rootCommand.Parse(commandLine); result.Errors .Should() .ContainSingle(e => e.SymbolResult.Symbol == option) .Which .Message .Should() .Be("Invoked validator"); }
public async Task A_custom_validator_added_to_a_global_option_is_checked(string commandLine) { var handlerWasCalled = false; var globalOption = new Option <int>("--value"); globalOption.AddValidator(option => "oops!"); var grandchildCommand = new Command("grandchild"); var childCommand = new Command("child") { grandchildCommand }; var rootCommand = new RootCommand { childCommand }; rootCommand.AddGlobalOption(globalOption); rootCommand.Handler = CommandHandler.Create((int value) => handlerWasCalled = true); childCommand.Handler = CommandHandler.Create((int value) => handlerWasCalled = true); grandchildCommand.Handler = CommandHandler.Create((int value) => handlerWasCalled = true); var result = await rootCommand.InvokeAsync(commandLine); result.Should().Be(1); handlerWasCalled.Should().BeFalse(); }
public static async Task <int> Main(params string[] args) { RootCommand rootCommand = new RootCommand( description: "Write hashes for files." ); Option inputOption = new Option(new string[] { "--input", "-i" }, description: "Input directory") { Required = true, Argument = new Argument <string>("input") }; inputOption.AddValidator(DirectoryValidator); rootCommand.AddOption( inputOption ); var outputOption = new Option(new string[] { "--output", "-o" }, description: "Output directory") { Required = true, Argument = new Argument <string>("output"), }; outputOption.AddValidator(DirectoryValidator); rootCommand.AddOption(outputOption); rootCommand.AddOption( new Option(new string[] { "--hashtype", "-t" }, description: "Hash type to use? Default MD5.") { Required = false, Argument = new Argument <EHashType>("eHashType", () => EHashType.MD5), } ); rootCommand.AddOption( new Option(new string[] { "--recursive", "-r" }, description: "Search recursively? Default true. \n") { Required = false, Argument = new Argument <bool>("isRecursive", () => true), } ); rootCommand.AddOption( new Option(new string[] { "--pattern", "-p" }, description: "File pattern to search? Default all. \n") { Required = false, Argument = new Argument <Regex>("patternOfFiles", () => new Regex(@"(\w*.exe$|\w*.dat$)")), } ); rootCommand.Handler = CommandHandler.Create <DirectoryInfo, DirectoryInfo, EHashType, bool, Regex>(KarlosumCLI.Run); return(await rootCommand.InvokeAsync(args)); }
public ComputeHistoryCommand() : base("compute-history", "Used to examine the history of the specified repository and determine the sha hashes that will need to be checked out to complete a historical analysis at the intervals specified.") { var repositoryIdentifier = new Argument <string>("repository-id", "The ID of the repository to compute history for") { Arity = ArgumentArity.ExactlyOne }; AddArgument(repositoryIdentifier); var commitHistory = new Option <bool>("--commit-history", "Analyzes only the points in time when files have changed in the commit history") { AllowMultipleArgumentsPerToken = false, Arity = ArgumentArity.ZeroOrOne }; AddOption(commitHistory); var historyInterval = new Option <string>("--history-interval", description: "As the analyze command moves backwards in time through the history of the project, what time interval should it use to determine the points in time that are sampled. Possible values: y(ears), m(onths), w(eeks), d(ays)", getDefaultValue: () => "m") { AllowMultipleArgumentsPerToken = false, Arity = ArgumentArity.ZeroOrOne }; historyInterval.AddValidator(optionResult => { var givenValue = optionResult.GetValueOrDefault <string>(); string[] possibleValues = { "y", "m", "w", "d" }; if (!Array.Exists(possibleValues, possibleValue => possibleValue == givenValue)) { optionResult.ErrorMessage = string.Format( "Option {0} not valid. Possible options are {1}", givenValue, string.Join(", ", possibleValues) ); } }); AddOption(historyInterval); var gitPath = new Option <string>( "--git-path", description: "Path to the git binary. Default = 'git'", getDefaultValue: () => "git" ) { Arity = ArgumentArity.ZeroOrOne }; AddOption(gitPath); }
public static Option <string> Create() { var o = new Option <string> ( alias: "--options", description: "Set filename of the user defined options", getDefaultValue: () => Const.Default_UserOptionsFilename ); o.AddValidator(r => Validate(r.Tokens)); return(o); }
public static Option <string> Create() { var o = new Option <string> ( aliases: new[] { "--user-repo-branch", "--repo" }, description: "Changes 'user/repo/branch' of the Github repository with a data", getDefaultValue: () => Default_ToptoutDataUserRepo ); o.AllowMultipleArgumentsPerToken = false; o.AddValidator(r => Validate(r.Tokens)); return(o); }
private static void AddStringRegexValidator(Option <string> option, string pattern, string parameterName) { var validator = new Regex(pattern); option.AddValidator((input) => { var value = input.GetValueForOption(option); if (string.IsNullOrEmpty(value) || !validator.IsMatch(value)) { input.ErrorMessage = $"{value} is not a valid {parameterName} for the client, the {parameterName} must conform to {pattern}"; } }); }
[Fact] // https://github.com/dotnet/command-line-api/issues/1573 public void Multiple_validators_on_the_same_option_do_not_report_duplicate_errors() { var option = new Option <string>("-x"); option.AddValidator(result => result.ErrorMessage = "Wrong"); option.AddValidator(_ => { }); var command = new RootCommand { option }; var parseResult = command.Parse("-x b"); parseResult.Errors .Should() .ContainSingle() .Which .Message .Should() .Be("Wrong"); }
public ExtractCommand() : base("extract", "Extract data from the bundle") { AddArgument(bundleFile); AddArgument(new Argument <FileInfo>("outputFile", "Path to the output file")); AddOption(new Option <bool>(new[] { "-a", "--all" }, "Extract all data")); AddOption(new Option <int>(new[] { "-b", "--block" }, "Extract a specific block (1-indexed)")); var sliceOption = new Option <string>(new[] { "-s", "--slice" }, "Extract a slice of data (syntax: 'from,to'; to is exclusive)"); sliceOption.AddValidator(result => ValidateSlice(result.GetValueOrDefault <string>())); AddOption(sliceOption); AddValidator(ValidateMutuallyExclusiveOptions); Handler = CommandHandler.Create <FileInfo, FileInfo, bool, int, string>(ExecuteCommand); }
public static Option <T> CreateOption <T>(string alias, string description = null, bool isRequired = false, T defaultValue = default, Func <T, bool> validator = null) { var options = new Option <T>(alias, description) { IsRequired = isRequired }; if (!isRequired) { options.SetDefaultValue(defaultValue); } if (validator != null) { options.AddValidator(result => Validator(result, validator)); } return(options); }
private static Option <string> BuildParamOption() { var names = new string[] { "--param", "-p" }; var opt = new Option <string>(names, "Parameters of report"); opt.AddValidator(symbol => symbol.Tokens .Select(e => e.Value.Split(':')) .Where(e => ValidateParam(e)) .Select(_ => "Params should be in format [key]:[value]") .FirstOrDefault() ); opt.Argument = new Argument <string> { Arity = ArgumentArity.OneOrMore }; return(opt); }
public void Option_T_default_value_is_validated() { var option = new Option <int>("-x", () => 123); option.AddValidator(symbol => symbol.ErrorMessage = symbol.Tokens .Select(t => t.Value) .Where(v => v == "123") .Select(_ => "ERR") .FirstOrDefault()); option .Parse("-x 123") .Errors .Select(e => e.Message) .Should() .BeEquivalentTo(new[] { "ERR" }); }
private static void ValidateFile(Option <string> fileOption, string errorMessage) { fileOption.AddValidator( cmd => { var fileValue = (string)cmd.GetValueOrDefault(); var fullPath = Path.GetFullPath(Directory.GetCurrentDirectory() + "/" + fileValue); if (!File.Exists(fullPath)) { return(errorMessage); } else { return(null); } } ); }
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(); }
private static void ValidatePath(Option <string> pathOption, string errorMessage) { pathOption.AddValidator( cmd => { var pathValue = (string)cmd.GetValueOrDefault(); var fullPath = Path.GetFullPath(Directory.GetCurrentDirectory() + "/" + pathValue); var directory = Path.GetDirectoryName(fullPath); if (!Directory.Exists(directory)) { return(errorMessage); } else { return(null); } } ); }
public void The_parsed_value_of_an_option_is_available_within_a_validator() { var option = new Option <int>("-x"); var errorMessage = "The value of option '-x' must be between 1 and 100."; option.AddValidator(result => { var value = result.GetValueForOption(option); if (value < 0 || value > 100) { result.ErrorMessage = errorMessage; } }); var result = option.Parse("-x -1"); result.Errors .Should() .HaveCount(1) .And .Contain(e => e.Message == errorMessage); }
/// <summary> /// Build the RootCommand for parsing /// </summary> /// <returns>RootCommand</returns> public static RootCommand BuildRootCommand() { RootCommand root = new RootCommand { Name = "helium", Description = "helium-csharp web app", TreatUnmatchedTokensAsErrors = true, }; // add options Option optKv = new Option <string>(new string[] { "-k", "--keyvault-name" }, "The name or URL of the Azure Keyvault") { Argument = new Argument <string>(), IsRequired = true, }; optKv.AddValidator(v => { if (v.Tokens == null || v.Tokens.Count != 1 || !KeyVaultHelper.ValidateName(v.Tokens[0].Value)) { return("--keyvault-name must be 3-20 characters [a-z][0-9]"); } return(string.Empty); }); // add the options root.AddOption(optKv); root.AddOption(new Option <AuthenticationType>(new string[] { "-a", "--auth-type" }, "Authentication type (Release builds require MI; Debug builds support all 3 options)")); root.AddOption(new Option <LogLevel>(new string[] { "-l", "--log-level" }, "Log Level")); root.AddOption(new Option(new string[] { "-d", "--dry-run" }, "Validates configuration")); return(root); }
[Fact] // https://github.com/dotnet/command-line-api/issues/1609 internal void When_there_is_an_arity_error_then_further_errors_are_not_reported() { var option = new Option <string>("-o"); option.AddValidator(result => { result.ErrorMessage = "OOPS"; }); //all good; var command = new Command("comm") { option }; var parseResult = command.Parse("comm -o"); parseResult.Errors .Should() .ContainSingle() .Which .Message .Should() .Be("Required argument missing for option: '-o'."); }
public static Option <T> WithinRange <T>(this Option <T> option, T minValue, T maxValue) where T : IComparable <T>, IConvertible { if (minValue is null) { throw new ArgumentNullException(nameof(minValue)); } if (maxValue is null) { throw new ArgumentNullException(nameof(maxValue)); } if (minValue.CompareTo(maxValue) > 0) { throw new ArgumentException($"{nameof(minValue)} must be <= {nameof(maxValue)}"); } option.AddValidator(opt => opt.Tokens .Select(t => t.Value) .Where(tokenValue => { try { T value = (T)Convert.ChangeType(tokenValue, typeof(T)); Console.Write(value.CompareTo(minValue)); Console.WriteLine(value.CompareTo(maxValue)); return(!(value.CompareTo(minValue) >= 0 && value.CompareTo(maxValue) <= 0)); } catch (Exception) { return(true); } }) .Select(value => $"The option '{opt.Symbol.RawAliases.First()}' must be of type '{opt.Option.ValueType}' and between '{minValue}' and '{maxValue}'. You passed: '{value}'.") .FirstOrDefault()); return(option); }
public Command GetCommand() { var downloadCommand = new Command("update-reports") { _dataDirOption, _maxPagesOption, _maxCommitsOption, _reportsOption, _defaultCursorValueOption, _verboseOption, }; var reportNames = Enum.GetNames(typeof(ReportName)).ToHashSet(StringComparer.OrdinalIgnoreCase); _reportsOption.AddValidator(optionResult => { var invalidValues = optionResult .Tokens .Where(x => !reportNames.Contains(x.Value)) .Select(x => x.Value) .ToList(); if (invalidValues.Any()) { return($"Invalid report names: {string.Join(", ", invalidValues)}"); } return(null); }); var possibleReportNames = $"Possible report names are: {string.Join(", ", reportNames.OrderBy(x => x))}"; downloadCommand.Description = "Incrementally update reports built off of the NuGet catalog. " + possibleReportNames; downloadCommand.Handler = this; return(downloadCommand); }
/// <summary> /// Case insensitive version for <see cref="System.CommandLine.OptionExtensions.FromAmong{TOption}(TOption, string[])"/>. /// </summary> internal static void FromAmongCaseInsensitive(this Option <string> option, string[]?allowedValues = null, string?allowedHiddenValue = null) { allowedValues ??= Array.Empty <string>(); option.AddValidator(optionResult => ValidateAllowedValues(optionResult, allowedValues, allowedHiddenValue)); option.AddCompletions(allowedValues); }
/// <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); }
/// <summary> /// Build the RootCommand for parsing /// </summary> /// <returns>RootCommand</returns> public static RootCommand BuildRootCommand() { RootCommand root = new RootCommand { Name = "simple-app", Description = "A simple app", TreatUnmatchedTokensAsErrors = true }; // add options Option optKv = new Option(new string[] { "-k", "--keyvault-name" }, "The name or URL of the Azure Keyvault") { Argument = new Argument <string>(), Required = true }; optKv.AddValidator(v => { if (v.Tokens == null || v.Tokens.Count != 1 || !KeyVaultHelper.ValidateName(v.Tokens[0].Value)) { return("--keyvault-name must be 3-20 characters [a-z][0-9]"); } return(string.Empty); }); Option optAuth = new Option(new string[] { "-a", "--auth-type" }, "Authentication type - MSI CLI VS") { Argument = new Argument <string>(() => "MSI") }; optAuth.AddValidator(v => { const string errorMessage = "--auth-type must be MSI CLI or VS"; if (v.Tokens == null) { return(errorMessage); } // use default value if (v.Tokens.Count != 1 && v.Option.Argument.HasDefaultValue) { return(string.Empty); } // validate using helper if (v.Tokens.Count != 1 || !KeyVaultHelper.ValidateAuthType(v.Tokens[0].Value)) { return(errorMessage); } return(string.Empty); }); // add the options root.AddOption(optKv); root.AddOption(optAuth); root.AddOption(new Option(new string[] { "-d", "--dry-run" }, "Validates configuration")); return(root); }
/// <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)); }
public static RootCommand GetRootCommand(string name, string description, Action <InvocationContext, CommandLineOptions> action) { var rootCommand = new RootCommand(name); rootCommand.Description = description; rootCommand.Handler = CommandHandler.Create(action); rootCommand.AddOption(new Option <string>( new string[] { "--port", "-P" }, "Set the serial port to listen on")); rootCommand.AddOption(new Option <int>( new string[] { "--baud", "-b" }, getDefaultValue: () => 115200, "Set serial port baud rate")); rootCommand.AddOption(new Option <bool>( new string[] { "--disconnect-exit", "-de" }, getDefaultValue: () => false, "Exit terminal on disconnection")); rootCommand.AddOption(new Option <bool>( new string[] { "--reset-esp32", "-r" }, getDefaultValue: () => false, "Reset ESP32 on connection")); var dbOption = new Option <int>( new string[] { "--data-bits", "-db" }, getDefaultValue: () => 8, "Sets the standard length of data bits per byte"); dbOption.AddSuggestions("5", "6", "7", "8"); dbOption.AddValidator(optionResult => { var suggestions = optionResult.Option.GetSuggestions().ToList(); if (optionResult.Tokens.Count > 0 && (!suggestions.Any(s => s.Equals(optionResult.Tokens[0].Value.ToLower(), StringComparison.OrdinalIgnoreCase)))) { return($"{optionResult.Tokens[0].Value} is not a valid argument for {optionResult.Token}"); } return(null); }); rootCommand.AddOption(dbOption); var parityOption = new Option <string>( new string[] { "--parity", "-pa" }, getDefaultValue: () => "None", "Sets the parity-checking protocol"); parityOption.AddSuggestions("None", "Mark", "Even", "Odd", "Space"); parityOption.AddValidator(optionResult => { var suggestions = optionResult.Option.GetSuggestions().ToList(); if (optionResult.Tokens.Count > 0 && (!suggestions.Any(s => s.Equals(optionResult.Tokens[0].Value.ToLower(), StringComparison.OrdinalIgnoreCase)))) { return($"{optionResult.Tokens[0].Value} is not a valid argument for {optionResult.Token}"); } return(null); }); rootCommand.AddOption(parityOption); var sbOption = new Option <string>( new string[] { "--stop-bits", "-sb" }, getDefaultValue: () => "One", "Sets the standard number of stopbits per byte"); sbOption.AddSuggestions("One", "OnePointFive", "Two"); sbOption.AddValidator(optionResult => { var suggestions = optionResult.Option.GetSuggestions().ToList(); if (optionResult.Tokens.Count > 0 && (!suggestions.Any(s => s.Equals(optionResult.Tokens[0].Value.ToLower(), StringComparison.OrdinalIgnoreCase)))) { return($"{optionResult.Tokens[0].Value} is not a valid argument for {optionResult.Token}"); } return(null); }); rootCommand.AddOption(sbOption); var hsOption = new Option <string>( new string[] { "--handshake", "-hs" }, getDefaultValue: () => "None", "Specifies the control protocol used in establishing a serial port communication"); hsOption.AddSuggestions("None", "RTS", "XonXoff", "RTSXonXoff"); hsOption.AddValidator(optionResult => { var suggestions = optionResult.Option.GetSuggestions().ToList(); if (optionResult.Tokens.Count > 0 && (!suggestions.Any(s => s.Equals(optionResult.Tokens[0].Value.ToLower(), StringComparison.OrdinalIgnoreCase)))) { return($"{optionResult.Tokens[0].Value} is not a valid argument for {optionResult.Token}"); } return(null); }); rootCommand.AddOption(hsOption); return(rootCommand); }
public static void CreateGeneratorCommandOptions(out Option <string> methodOption, out Option <string> targetOption, out Option <int> entriesOption, out Option <string> outputOption) { methodOption = new Option <string>( alias: "--method", getDefaultValue: () => "POST", description: "HTTP request method, set of options: [POST, GET, DELETE]"); methodOption.AddValidator( cmd => { List <string> availableMethods = new List <string> { "POST", "GET", "DELETE" }; var methodValue = (string)cmd.GetValueOrDefault(); if (!availableMethods.Exists(m => m.Equals(methodValue))) { return("Invalid value to method option, type --help to see the options"); } else { return(null); } } ); targetOption = new Option <string>( alias: "--target", getDefaultValue: () => "/app/log/private", description: "Target which will receive the requests"); targetOption.AddValidator( cmd => { var targetValue = (string)cmd.GetValueOrDefault(); if (!targetValue.StartsWith("/")) { return("Invalid value to target argument, check the written path"); } else { return(null); } } ); entriesOption = new Option <int>( alias: "--entries", getDefaultValue: () => 100, description: "How many requests will be generated"); entriesOption.AddValidator( cmd => { var entriesValue = (int)cmd.GetValueOrDefault(); if (entriesValue < 1) { return("Invalid value to entries argument, check if inserted value is correct"); } else { return(null); } } ); outputOption = new Option <string>( alias: "--requestsfile", getDefaultValue: () => "/../results/requests.parquet", description: "Path to Parquet with raw requests"); ValidatePath(outputOption, "Invalid output path, verify if the entered path is correct"); }
private static Command Connect() { var c = new Command("connect", "connect to other lightning node"); var op1 = new Option(new [] { "--nodeid", "--pubkey" }, "hex-encoded public key of the node we want to connect to") { Argument = new Argument <string> { Arity = ArgumentArity.ExactlyOne } }; op1.AddValidator(r => { var msg = "Must specify valid pubkey in hex"; var v = r.GetValueOrDefault <string>(); if (String.IsNullOrEmpty(v)) { return(msg); } if (!HexEncoder.IsWellFormed(v)) { return($"Invalid hex for pubkey: {v}"); } var hexEncoder = new HexEncoder(); var b = hexEncoder.DecodeData(v); if (!PubKey.Check(b, true)) { return($"Invalid pubkey {v}"); } return(null); }); c.AddOption(op1); var op2 = new Option("--host", "ip:port pair of the node") { Argument = new Argument <string> { Arity = ArgumentArity.ExactlyOne } }; op2.AddValidator(r => { var v = r.GetValueOrDefault <string>(); if (String.IsNullOrEmpty(v)) { return("Invalid host"); } if (!NBitcoin.Utils.TryParseEndpoint(v, 80, out var _)) { return("Invalid host"); } return(null); }); c.AddOption(op2); return(c); }
public static void CreateSenderCommandOptions(out Option <string> hostOption, out Option <string> userOption, out Option <string> userPkOption, out Option <string> caCertOption, out Option <string> infileOption, out Option <string> requestsFileOption, out Option <string> responsesFileOption) { hostOption = new Option <string>( alias: "--host", getDefaultValue: () => "127.0.0.1:8000", description: "Address of CCF node host"); hostOption.AddValidator( cmd => { var hostValue = (string)cmd.GetValueOrDefault(); try { if (!Uri.IsWellFormedUriString(hostValue, UriKind.Absolute)) { var tryCreateUri = new UriBuilder(hostValue); } return(null); } catch { return("Invalid Host, verify if the entered host is well formed"); } } ); userOption = new Option <string>( alias: "--user", getDefaultValue: () => "user0_cert.pem", description: "Path to User certificate file"); ValidateFile(userOption, "Invalid user certificate file, verify if the entered path is correct"); userPkOption = new Option <string>( alias: "--pk", getDefaultValue: () => "user0_privk.pem", description: "Path to User private key file"); ValidateFile(userPkOption, "Invalid user private key file, verify if the entered path is correct"); caCertOption = new Option <string>( alias: "--cacert", getDefaultValue: () => "networkcert.pem", description: "Path to Certificate Authority file"); ValidateFile(caCertOption, "Invalid Certificate Authority file, verify if the entered path is correct"); infileOption = new Option <string>( alias: "--infile", getDefaultValue: () => "/../results/requests.parquet", description: "Path to Parquet with raw requests"); ValidateFile(infileOption, "Invalid input file, verify if the entered path is correct"); requestsFileOption = new Option <string>( alias: "--requestsfile", getDefaultValue: () => "/../results/sentrequests.parquet", description: "Path to Parquet with sent requests data"); ValidatePath(requestsFileOption, "Invalid sent requests output path, verify if the entered path is correct"); responsesFileOption = new Option <string>( alias: "--responsesfile", getDefaultValue: () => "/../results/responses.parquet", description: "Path to Parquet with responses data"); ValidatePath(responsesFileOption, "Invalid responses output path, verify if the entered path is correct"); }
public static Option <T> WithValidator <T>(this Option <T> option, ValidateSymbol <OptionResult> validator) { option.AddValidator(validator); return(option); }