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();
        }
Example #4
0
        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));
        }
Example #5
0
    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);
        }
Example #7
0
        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);
        }
Example #8
0
    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");
        }
Example #10
0
            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);
            }
Example #11
0
        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);
        }
Example #12
0
        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);
        }
Example #13
0
        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);
        }
Example #18
0
        /// <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);
        }
Example #22
0
 /// <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);
 }
Example #23
0
        /// <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);
        }
Example #24
0
        /// <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);
        }
Example #25
0
        /// <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");
        }
Example #28
0
        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);
 }