public static void Main(string[] args)
        {
            RootCommand root = new RootCommand("Convert between different file formats supported by RDFSharp.");

            root.AddArgument(new Argument <RDFModelEnums.RDFFormats>("formatSource"));
            root.AddArgument(new Argument <FileInfo>("fileSource").ExistingOnly());
            root.AddArgument(new Argument <RDFModelEnums.RDFFormats>("formatDestination"));
            root.AddArgument(new Argument <FileInfo>("fileDestination").LegalFilePathsOnly());

            root.Handler = CommandHandler.Create <RDFModelEnums.RDFFormats, FileInfo, RDFModelEnums.RDFFormats, FileInfo>(Convert);

            root.Invoke(args);
        }
Exemple #2
0
        private static async Task <int> Main(string[] args)
        {
            // Directly output characters up to and including 255 as bytes, without modifying them.
            // This allows UTF-8 encoded text to be output one byte at a time.
            Console.OutputEncoding = Encoding.GetEncoding("iso-8859-1");
            var bytes        = Enumerable.Range(0, 256).Select(x => (byte)x).ToArray();
            var encodedBytes = Console.OutputEncoding
                               .GetBytes(bytes.Select(x => (char)x).ToArray());

            if (!bytes.SequenceEqual(encodedBytes))
            {
                throw new InvalidOperationException("Encoding error.");
            }

            var rootCommand = new RootCommand
            {
                new Option <int>(
                    new[] { "-g", "--generate" },
                    "Generate a hexagon with the given size."),
                new Option <bool>(
                    new[] { "-d", "--debug" },
                    "Output debug information to STDERR for instructions preceded by \"`\"."),
                new Option <bool>(
                    new[] { "-D", "--debug-all" },
                    "Output debug information to STDERR after every tick."),
            };

            rootCommand.AddArgument(new Argument
            {
                Name         = "File",
                ArgumentType = typeof(FileInfo),
                Arity        = ArgumentArity.ZeroOrOne,
                Description  = "Path to code file. Use \"-\" for STDIN.",
            });

            rootCommand.AddArgument(new Argument
            {
                Name         = "Arguments",
                ArgumentType = typeof(string),
                Arity        = ArgumentArity.ZeroOrMore,
                Description  = "Optional arguments for program that will be joined with null characters. Otherwise, if STDIN is not used for the code file, it will be used for input.",
            });

            rootCommand.Description = "Hexagony interpreter";

            // Note that the parameters of the handler method are matched according to the names of the options.
            rootCommand.Handler = CommandHandler.Create <CommandLineOptions>(MainTask);

            return(await rootCommand.InvokeAsync(args));
        }
Exemple #3
0
            static CommandLineBuilder BuildCommandLine()
            {
                var root = new RootCommand();

                root.AddArgument(new Argument <System.IO.DirectoryInfo>("source"));
                root.AddArgument(new Argument <System.IO.DirectoryInfo>("destination"));
                root.AddOption(new Option <bool>(new[] { "-m", "--move" }, "Moves the files"));
                root.AddOption(new Option <bool>(new[] { "-r", "--recursive" }, "Recursively searches <SOURCE>"));
                root.AddOption(new Option <bool>(new[] { "-n", "--dry-run" }, "Don’t actually move/copy any file(s). Instead, just show if they exist and would otherwise be moved/copied by the command."));
                root.AddOption(new Option <bool>(new[] { "-i", "--inplace" }, "Renames the files in place, rather than to <DESTINATION>."));

                root.Handler = CommandHandler.Create <IHost, System.IO.DirectoryInfo, System.IO.DirectoryInfo, bool, bool, bool, bool>(Process);

                return(new CommandLineBuilder(root));
            }
        public RootCommand Build()
        {
            // Check attribute exists
            if (_att is null)
            {
                throw new ArgumentNullException("Object doesn't implement RootCommandAttribute");
            }
            // Create root command
            var root = new RootCommand(_att.Description ?? "");

            // Search in properties for arguments and options
            foreach (var p in _t.GetProperties())
            {
                var arg = new ArgumentFactory(p);
                if (arg.IsValid)
                {
                    root.AddArgument(arg.Build());
                    continue;
                }

                var opt = new OptionFactory(p);
                if (opt.IsValid)
                {
                    root.AddOption(opt.Build());
                }
            }
            return(root);
        }
        private static RootCommand BuildCommand()
        {
            var root = new RootCommand
            {
                new Option <FileInfo>(
                    new string[] { "--output", "-o" },
                    description: "Output file path"),
                new Option <string>(
                    new string[] { "--target", "-t" },
                    description: "Translation target language"),
                new Option <string>(
                    new string[] { "--model", "-m" },
                    description: "Data model source (connection string or JSON file path)"),
                new Option <string>(
                    new string[] { "--namespace-mapping", "-n" },
                    description: "Namespace mapping json file path"),
                new Option <string>(
                    new string[] { "--default-namespace", "-d" },
                    description: "Default data model namespace"),
                new Option(
                    new string[] { "--verbose", "-v" },
                    description: "Logs debug information"),
                new Option(
                    new string[] { "--console", "-c" },
                    description: "Print logs to console output")
            };

            root.AddArgument(new Argument <FileInfo>("input"));
            root.Description = "VTL translator command line interface";

            root.Handler = CommandHandler.Create <TranslateOptions>(Run);
            return(root);
        }
Exemple #6
0
        /// <summary>
        /// The BuildCommandLine.
        /// </summary>
        /// <returns>The <see cref="CommandLineBuilder"/>.</returns>
        private static CommandLineBuilder BuildCommandLine()
        {
            var root = new RootCommand(@"$ dotnet run 'MUM_120'")
            {
            };

            root.AddArgument(new Argument <string>("number", "number of av"));
            root.AddOption(new Option <bool>(new string[] { "--table", "-t" }, () => false, "set table view"));
            root.AddOption(new Option <bool>(new string[] { "--search", "-s" }, () => false, "enable search"));
            root.Handler = CommandHandler.Create <string, List <string>, bool, bool, IHost>(Run);
            return(new CommandLineBuilder(root));
        }
        public void Command_argument_is_bound_to_longest_constructor()
        {
            var rootCommand = new RootCommand();

            rootCommand.AddArgument(new Argument <int> {
                Name = nameof(ClassWithMultipleCtor.IntProperty)
            });
            var parser = new Parser(rootCommand);

            var bindingContext = new BindingContext(parser.Parse("42"));
            var binder         = new ModelBinder <ClassWithMultipleCtor>();
            var instance       = binder.CreateInstance(bindingContext) as ClassWithMultipleCtor;

            instance.Should().NotBeNull();
            instance.IntProperty.Should().Be(42);
        }
Exemple #8
0
        private static int Main(string[] args)
        {
            RootCommand rootCommand = new RootCommand(
                description: "Parses Kindle highlight files into useful formats.");

            rootCommand.AddOption(new Option <string>(new string[] { "--format", "--f" },
                                                      () => "",
                                                      "Select the output format. Default: pages and nopages. Also available: json. For multiple formats, separate them by comma."));

            rootCommand.AddArgument(new Argument <FileInfo>("highlightsFile",
                                                            () => new FileInfo("My Clippings.txt"),
                                                            "The path to the highlights file."));

            rootCommand.Handler = CommandHandler.Create <FileInfo, string>(ParseAndOutput);

            return(rootCommand.Invoke(args));
        }
        private void BuildCommand()
        {
            var fileArgument =
                new Argument <FileInfo>()
            {
                Name        = "Model",
                Description = "3MF file to open",
                Arity       = ArgumentArity.ZeroOrOne
            }.ExistingOnly();

            RootCommand.AddArgument(fileArgument);
            RootCommand.Add(_createCommand.Command);
            RootCommand.Add(_addCommand.Command);
            RootCommand.Add(_listCommand.Command);
            RootCommand.Add(_setCommand.Command);
            RootCommand.Add(_removeCommand.Command);
            RootCommand.Add(_packCommand.Command);
            RootCommand.Add(_extractCommand.Command);
            RootCommand.Handler = CommandHandler.Create <FileInfo>((model) => new PrintProjectWebview().Run(model));
        }
Exemple #10
0
        static void Main(string[] args)
        {
            var rootCommand = new RootCommand(description: "Converts a specfic colour (chroma key) in images and makes them transparent")
            {
                new Option(new string[] { "--color", "--colour", "-c" }, "The named colour to be changed")
                {
                    Argument = new Argument <Color>()
                },
                new Option(new string[] { "--outdir" }, "The custom directory to output the changed image.")
                {
                    Argument = new Argument <DirectoryInfo>()
                },
            };

            rootCommand.AddArgument(new Argument <FileInfo[]>("files"));

            rootCommand.Handler = CommandHandler.Create <Color?, DirectoryInfo, FileInfo[]>(ProcessImages);

            rootCommand.InvokeAsync(args).Wait();
        }
Exemple #11
0
        private static RootCommand CreateCommandLineInterface()
        {
            var rootCommand = new RootCommand();

            rootCommand.Handler = CommandHandler.Create <IHost>(Run);

            rootCommand.AddArgument(new Argument <FileInfo>("path")
            {
                Description = "Path of the script file to execute.",
                Arity       = ArgumentArity.ExactlyOne
            });

            rootCommand.AddOption(new Option <string>("--plugin-path"));
            //rootCommand.AddOption(new Option<int>(new string[] { "--int-option", "/int-option" }, getDefaultValue: () => 42, description: "An option whose argument is parsed to an int"));
            //rootCommand.AddOption(new Option<string>("--string-option", getDefaultValue: () => "NONE", description: "An option for string value"));
            //rootCommand.AddOption(new Option("--that-option", "An option that's there or not"));

            //rootCommand.Description = "Sample App using System.CommandLine";

            return(rootCommand);
        }
        private async Task <(int ExitCode, IConsole Console)> RunCommand(string filename, bool allowNewFile = false)
        {
            var file = new FileArgument("file");

            file.AllowNewFile = allowNewFile;

            var command = new RootCommand();

            command.AddArgument(file);

            var console = new TestConsole();

            command.SetHandler((string file) =>
            {
                console.Out.Write("Success " + file);
            }, file);

            var exitCode = await command.InvokeAsync(filename, console);

            return(exitCode, console);
        }
Exemple #13
0
        public static RootCommand RootCommand()
        {
            RootCommand command = new RootCommand();

            command.AddArgument(new Argument <string[]>("input-file-path", "Input file(s)")
            {
                Arity = new ArgumentArity(1, Int32.MaxValue)
            });
            command.AddOption(new Option <string[]>(new[] { "--reference", "-r" }, "Reference metadata from the specified assembly"));
            command.AddOption(new Option <string>(new[] { "--system-module", "-s" }, "System module name (default: mscorlib)"));
            command.AddOption(new Option <string[]>(new[] { "--include", "-i" }, "Use only methods/types/namespaces, which match the given regular expression(s)"));
            command.AddOption(new Option <FileInfo>(new[] { "--include-file" }, "Same as --include, but the regular expression(s) are declared line by line in the specified file.").ExistingOnly());
            command.AddOption(new Option <string[]>(new[] { "--exclude", "-e" }, "Skip methods/types/namespaces, which match the given regular expression(s)"));
            command.AddOption(new Option <FileInfo>(new[] { "--exclude-file" }, "Same as --exclude, but the regular expression(s) are declared line by line in the specified file.").ExistingOnly());
            command.AddOption(new Option <string[]>(new[] { "--ignore-error", "-g" }, "Ignore errors, which match the given regular expression(s)"));
            command.AddOption(new Option <FileInfo>(new[] { "--ignore-error-file" }, "Same as --ignore-error, but the regular expression(s) are declared line by line in the specified file.").ExistingOnly());
            command.AddOption(new Option <bool>(new[] { "--statistics" }, "Print verification statistics"));
            command.AddOption(new Option <bool>(new[] { "--verbose", "-v" }, "Verbose output"));
            command.AddOption(new Option <bool>(new[] { "--tokens", "-t" }, "Include metadata tokens in error messages"));
            return(command);
        }
Exemple #14
0
        /// <summary>
        /// Main entry for the program.
        /// https://dotnetdevaddict.co.za/2020/09/25/getting-started-with-system-commandline/ Tutorial for System.CommandLine
        /// https://github.com/dotnet/command-line-api System.CommandLine Git repository and its document.
        /// </summary>
        /// <param name="args">Command line arguments.</param>
        static int Main(string[] args)
        {
            var rootCommand = new RootCommand("The PHP switcher command line that will work on these tasks for you.");
            var phpversion  = new Argument <string>(
                name: "phpversion",
                description: "The PHP version to switch to."
                );

            rootCommand.AddArgument(phpversion);

            var configjson = new Option <FileInfo>(
                name: "--config-json",
                description: "The path to phpswitch.json configuration file."
                );

            rootCommand.AddOption(configjson);
            var verbose = new Option <bool>(
                name: "--verbose",
                description: "Show verbose output"
                );

            verbose.AddAlias("-v");
            rootCommand.Add(verbose);

            rootCommand.Description = "The PHP switcher command line that will work on these tasks for you."
                                      + "\n"
                                      + "  Switch PHP version for CLI.\n"
                                      + "  Rewrite Apache configuration to use selected PHP version. (Optional)\n"
                                      + "  Start and stop web server service(s). (Optional)\n"
                                      + "  Copy files depend on PHP version in JSON config file. (Optional)";

            rootCommand.SetHandler((phpversion, configJson, verbose) => {
                var app = new App();
                app.Run(phpversion, configJson, verbose);
            },
                                   phpversion, configjson, verbose);

            // Parse the incoming args and invoke the handler
            return(rootCommand.InvokeAsync(args).Result);
        }
Exemple #15
0
        static async Task <int> Main(string[] args)
        {
            Func <string, bool, bool, string, string, int, Task <int> > action = Run;
            var rootCommand = new RootCommand(description: "A test runner for running standalone bash-based or xunit tests");

            rootCommand.Handler = CommandHandler.Create(action);

            var testRootArgument = new Argument <string>();

            testRootArgument.Name        = "testRoot";
            testRootArgument.Description = "Root directory for searching for tests";
            testRootArgument.Arity       = ArgumentArity.ZeroOrOne;

            rootCommand.AddArgument(testRootArgument);
            rootCommand.AddOption(compatibleOption);
            rootCommand.AddOption(verboseOption);
            rootCommand.AddOption(logDirectoryOption);
            rootCommand.AddOption(additionalFeedOption);
            rootCommand.AddOption(timeoutOption);

            return(await rootCommand.InvokeAsync(args));
        }
Exemple #16
0
        static async Task <int> Main(string[] args)
        {
            CultureInfo.CurrentCulture   = CultureInfo.InvariantCulture;
            CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;

            var cmd = new RootCommand
            {
                new Option <int>(new [] { "--scan-radius", "-r" }, 50, "Scan radius in ly (default: 50)"),
                new Option <bool>(new [] { "--plot-journey", "-p" }, false, "Plot journey (default: false)"),
                new Option <bool>(new [] { "--include-bodies", "-b" }, false, "Include bodies in systems.txt (default: false)"),
                new Option <TimeSpan>(new [] { "--cache-duration" }, TimeSpan.FromMinutes(30), "Duration on how long system details are cached (default: 00:30:00)"),
                new Option <string[]>(new [] { "--filter-body", "-fb" }, Array.Empty <string>, $"Body filter(s) written in form on LINQ expression like: \"{nameof(SystemBody.IsScoopable)}==true\". When applied, only the systems with at least one matching body will be returned."),
                new Option <string[]>(new [] { "--filter-system", "-fs" }, Array.Empty <string>, $"System filter(s) written in form on LINQ expression like: \"{nameof(SystemDetails.DiscoveredStars)} > 1\".")
            };

            cmd.Description = "Edsm Scanner";
            cmd.AddArgument(new Argument <string>("origin-system")
            {
                Description = "Origin system name"
            });
            cmd.Handler = CommandHandler.Create <string, int, bool, bool, TimeSpan, string[], string[]>(Scan);


            var helpCmd = new Command("help", "Displays help");

            helpCmd.AddCommand(new Command("usage", "Displays usage")
            {
                Handler = CommandHandler.Create(HelpUsage)
            });
            helpCmd.AddCommand(new Command("filters", "Displays filters usage")
            {
                Handler = CommandHandler.Create(FiltersUsage)
            });

            cmd.AddCommand(helpCmd);
            return(await cmd.InvokeAsync(args));
        }
Exemple #17
0
        public Program()
        {
            Option            optionServerConfigName   = new Option("--server", "defines a name of server configuration which will be used");
            Argument <string> argumentServerConfigName = new Argument <string> {
                Arity = ArgumentArity.ExactlyOne
            };
            Argument <string> argumentServerFingerPrint = new Argument <string> ("server-finger-print")
            {
                Arity = ArgumentArity.ExactlyOne
            };

            optionServerConfigName.AddAlias("-s");
            optionServerConfigName.Argument = argumentServerConfigName;
            rootCommand.AddOption(optionServerConfigName);
            rootCommand.AddArgument(argumentServerFingerPrint);

            var commandUpload = new Command("upload", "uploads file to the specified or the default server");

            commandUpload.AddAlias("u");

            var argumentLocalPathFileName = new Argument <string> ("local-path-file-name")
            {
                Arity = ArgumentArity.ExactlyOne
            };

            commandUpload.AddArgument(argumentLocalPathFileName);

            var argumentRemotePathFileName = new Argument <string> ("remote-path-file-name")
            {
                Arity = ArgumentArity.ExactlyOne
            };

            commandUpload.AddArgument(argumentRemotePathFileName);

            commandUpload.Handler = CommandHandler.Create <string, string, string, string> (Upload);
            rootCommand.AddCommand(commandUpload);
        }
Exemple #18
0
        public static Parser Create(
            IServiceCollection services,
            StartServer startServer = null,
            Demo demo           = null,
            TryGitHub tryGithub = null,
            Pack pack           = null,
            Install install     = null,
            Verify verify       = null,
            Jupyter jupyter     = null,
            StartKernelServer startKernelServer = null,
            ITelemetry telemetry = null,
            IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel = null)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            startServer = startServer ??
                          ((startupOptions, invocationContext) =>
                           Program.ConstructWebHost(startupOptions).Run());

            jupyter = jupyter ??
                      ((startupOptions, console, server, context) =>
                       JupyterCommand.Do(startupOptions, console, server, context));

            demo = demo ??
                   DemoCommand.Do;

            tryGithub = tryGithub ??
                        ((repo, console) =>
                         GitHubHandler.Handler(repo,
                                               console,
                                               new GitHubRepoLocator()));

            verify = verify ??
                     ((options, console, startupOptions) =>
                      VerifyCommand.Do(options,
                                       console,
                                       startupOptions));

            pack = pack ??
                   PackCommand.Do;

            install = install ??
                      InstallCommand.Do;

            startKernelServer = startKernelServer ??
                                ((startupOptions, kernel, console) =>
                                 KernelServerCommand.Do(startupOptions, kernel, console));

            // Setup first time use notice sentinel.
            firstTimeUseNoticeSentinel = firstTimeUseNoticeSentinel ?? new FirstTimeUseNoticeSentinel();

            // Setup telemetry.
            telemetry = telemetry ?? new Telemetry.Telemetry(firstTimeUseNoticeSentinel);
            var filter = new TelemetryFilter(Sha256Hasher.HashWithNormalizedCasing);
            Action <ParseResult> track = o => telemetry.SendFiltered(filter, o);

            var dirArgument = new Argument <FileSystemDirectoryAccessor>(() => new FileSystemDirectoryAccessor(Directory.GetCurrentDirectory()))
            {
                Name        = nameof(StartupOptions.RootDirectory),
                Arity       = ArgumentArity.ZeroOrOne,
                Description = "Specify the path to the root directory for your documentation",
            };

            dirArgument.AddValidator(symbolResult =>
            {
                var directory = symbolResult.Tokens
                                .Select(t => t.Value)
                                .FirstOrDefault();

                if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
                {
                    return($"Directory does not exist: {directory}");
                }

                return(null);
            });

            var rootCommand = StartInTryMode();

            rootCommand.AddCommand(StartInHostedMode());
            rootCommand.AddCommand(Demo());
            rootCommand.AddCommand(GitHub());
            rootCommand.AddCommand(Pack());
            rootCommand.AddCommand(Install());
            rootCommand.AddCommand(Verify());
            rootCommand.AddCommand(Jupyter());
            rootCommand.AddCommand(KernelServer());

            return(new CommandLineBuilder(rootCommand)
                   .UseDefaults()
                   .UseMiddleware(async(context, next) =>
            {
                // If sentinel does not exist, print the welcome message showing the telemetry notification.
                if (!firstTimeUseNoticeSentinel.Exists() && !Telemetry.Telemetry.SkipFirstTimeExperience)
                {
                    context.Console.Out.WriteLine();
                    context.Console.Out.WriteLine(Telemetry.Telemetry.WelcomeMessage);

                    firstTimeUseNoticeSentinel.CreateIfNotExists();
                }

                if (context.ParseResult.Directives.Contains("debug") &&
                    !(Clock.Current is VirtualClock))
                {
                    VirtualClock.Start();
                }

                await next(context);
            })
                   .Build());

            RootCommand StartInTryMode()
            {
                var command = new RootCommand
                {
                    Name        = "dotnet-try",
                    Description = "Interactive documentation in your browser"
                };

                command.AddArgument(dirArgument);

                command.AddOption(new Option(
                                      "--add-package-source",
                                      "Specify an additional NuGet package source")
                {
                    Argument = new Argument <PackageSource>(() => new PackageSource(Directory.GetCurrentDirectory()))
                    {
                        Name = "NuGet source"
                    }
                });

                command.AddOption(new Option(
                                      "--package",
                                      "Specify a Try .NET package or path to a .csproj to run code samples with")
                {
                    Argument = new Argument <string>
                    {
                        Name = "name or .csproj"
                    }
                });

                command.AddOption(new Option(
                                      "--package-version",
                                      "Specify a Try .NET package version to use with the --package option")
                {
                    Argument = new Argument <string>
                    {
                        Name = "version"
                    }
                });

                command.AddOption(new Option(
                                      "--uri",
                                      "Specify a URL or a relative path to a Markdown file")
                {
                    Argument = new Argument <Uri>()
                });

                command.AddOption(new Option(
                                      "--enable-preview-features",
                                      "Enable preview features")
                {
                    Argument = new Argument <bool>()
                });

                command.AddOption(new Option(
                                      "--log-path",
                                      "Enable file logging to the specified directory")
                {
                    Argument = new Argument <DirectoryInfo>
                    {
                        Name = "dir"
                    }
                });

                command.AddOption(new Option(
                                      "--verbose",
                                      "Enable verbose logging to the console")
                {
                    Argument = new Argument <bool>()
                });

                var portArgument = new Argument <ushort>();

                portArgument.AddValidator(symbolResult =>
                {
                    if (symbolResult.Tokens
                        .Select(t => t.Value)
                        .Count(value => !ushort.TryParse(value, out _)) > 0)
                    {
                        return("Invalid argument for --port option");
                    }

                    return(null);
                });

                command.AddOption(new Option(
                                      "--port",
                                      "Specify the port for dotnet try to listen on")
                {
                    Argument = portArgument
                });

                command.Handler = CommandHandler.Create <InvocationContext, StartupOptions>((context, options) =>
                {
                    services.AddSingleton(_ => PackageRegistry.CreateForTryMode(
                                              options.RootDirectory,
                                              options.AddPackageSource));

                    startServer(options, context);
                });

                return(command);
            }

            Command StartInHostedMode()
            {
                var command = new Command("hosted")
                {
                    new Option(
                        "--id",
                        "A unique id for the agent instance (e.g. its development environment id).")
                    {
                        Argument = new Argument <string>(defaultValue: () => Environment.MachineName)
                    },
                    new Option(
                        "--production",
                        "Specifies whether the agent is being run using production resources")
                    {
                        Argument = new Argument <bool>()
                    },
                    new Option(
                        "--language-service",
                        "Specifies whether the agent is being run in language service-only mode")
                    {
                        Argument = new Argument <bool>()
                    },
                    new Option(
                        new[]
                    {
                        "-k",
                        "--key"
                    },
                        "The encryption key")
                    {
                        Argument = new Argument <string>()
                    },
                    new Option(
                        new[]
                    {
                        "--ai-key",
                        "--application-insights-key"
                    },
                        "Application Insights key.")
                    {
                        Argument = new Argument <string>()
                    },
                    new Option(
                        "--region-id",
                        "A unique id for the agent region")
                    {
                        Argument = new Argument <string>()
                    },
                    new Option(
                        "--log-to-file",
                        "Writes a log file")
                    {
                        Argument = new Argument <bool>()
                    }
                };

                command.Description = "Starts the Try .NET agent";

                command.IsHidden = true;

                command.Handler = CommandHandler.Create <InvocationContext, StartupOptions>((context, options) =>
                {
                    services.AddSingleton(_ => PackageRegistry.CreateForHostedMode());
                    services.AddSingleton(c => new MarkdownProject(c.GetRequiredService <PackageRegistry>()));
                    services.AddSingleton <IHostedService, Warmup>();

                    startServer(options, context);
                });

                return(command);
            }

            Command Demo()
            {
                var demoCommand = new Command(
                    "demo",
                    "Learn how to create Try .NET content with an interactive demo")
                {
                    new Option("--output", "Where should the demo project be written to?")
                    {
                        Argument = new Argument <DirectoryInfo>(
                            defaultValue: () => new DirectoryInfo(Directory.GetCurrentDirectory()))
                    }
                };

                demoCommand.Handler = CommandHandler.Create <DemoOptions, InvocationContext>((options, context) =>
                {
                    demo(options, context.Console, startServer, context);
                });

                return(demoCommand);
            }

            Command GitHub()
            {
                var argument = new Argument <string>
                {
                    // System.CommandLine parameter binding does lookup by name,
                    // so name the argument after the github command's string param
                    Name = nameof(TryGitHubOptions.Repo)
                };

                var github = new Command("github", "Try a GitHub repo")
                {
                    argument
                };

                github.IsHidden = true;

                github.Handler = CommandHandler.Create <TryGitHubOptions, IConsole>((repo, console) => tryGithub(repo, console));

                return(github);
            }

            Command Jupyter()
            {
                var jupyterCommand      = new Command("jupyter", "Starts dotnet try as a Jupyter kernel");
                var defaultKernelOption = new Option("--default-kernel", "The default .NET kernel language for the notebook.")
                {
                    Argument = new Argument <string>(defaultValue: () => "csharp")
                };

                jupyterCommand.AddOption(defaultKernelOption);
                var connectionFileArgument = new Argument <FileInfo>
                {
                    Name  = "ConnectionFile",
                    Arity = ArgumentArity.ZeroOrOne //should be removed once the commandlineapi allows subcommands to not have arguments from the main command
                }.ExistingOnly();

                jupyterCommand.AddArgument(connectionFileArgument);

                jupyterCommand.Handler = CommandHandler.Create <StartupOptions, JupyterOptions, IConsole, InvocationContext>((startupOptions, options, console, context) =>
                {
                    track(context.ParseResult);

                    services
                    .AddSingleton(c => ConnectionInformation.Load(options.ConnectionFile))
                    .AddSingleton(
                        c =>
                    {
                        return(CommandScheduler
                               .Create <JupyterRequestContext>(delivery => c.GetRequiredService <ICommandHandler <JupyterRequestContext> >()
                                                               .Trace()
                                                               .Handle(delivery)));
                    })
                    .AddSingleton(c => CreateKernel(options.DefaultKernel))
                    .AddSingleton(c => new JupyterRequestContextHandler(c.GetRequiredService <IKernel>())
                                  .Trace())
                    .AddSingleton <IHostedService, Shell>()
                    .AddSingleton <IHostedService, Heartbeat>();

                    return(jupyter(startupOptions, console, startServer, context));
                });

                var installCommand = new Command("install", "Install the .NET kernel for Jupyter");

                installCommand.Handler = CommandHandler.Create <IConsole, InvocationContext>((console, context) =>
                {
                    track(context.ParseResult);
                    return(new JupyterCommandLine(console, new FileSystemJupyterKernelSpec()).InvokeAsync());
                });

                jupyterCommand.AddCommand(installCommand);

                return(jupyterCommand);
            }

            Command KernelServer()
            {
                var startKernelServerCommand = new Command("kernel-server", "Starts dotnet-try with kernel functionality exposed over standard I/O");
                var defaultKernelOption      = new Option("--default-kernel", "The default .NET kernel language for the notebook.")
                {
                    Argument = new Argument <string>(defaultValue: () => "csharp")
                };

                startKernelServerCommand.AddOption(defaultKernelOption);

                startKernelServerCommand.Handler = CommandHandler.Create <StartupOptions, KernelServerOptions, IConsole, InvocationContext>(
                    (startupOptions, options, console, context) =>
                {
                    track(context.ParseResult);
                    return(startKernelServer(startupOptions, CreateKernel(options.DefaultKernel), console));
                });

                return(startKernelServerCommand);
            }

            Command Pack()
            {
                var packCommand = new Command("pack", "Create a Try .NET package")
                {
                    new Argument <DirectoryInfo>
                    {
                        Name = nameof(PackOptions.PackTarget)
                    },
                    new Option("--version", "The version of the Try .NET package")
                    {
                        Argument = new Argument <string>()
                    },
                    new Option("--enable-wasm", "Enables web assembly code execution")
                };

                packCommand.IsHidden = true;

                packCommand.Handler = CommandHandler.Create <PackOptions, IConsole>(
                    (options, console) =>
                {
                    return(pack(options, console));
                });

                return(packCommand);
            }

            Command Install()
            {
                var installCommand = new Command("install", "Install a Try .NET package")
                {
                    new Argument <string>
                    {
                        Name  = nameof(InstallOptions.PackageName),
                        Arity = ArgumentArity.ExactlyOne
                    },
                    new Option("--add-source")
                    {
                        Argument = new Argument <PackageSource>()
                    }
                };

                installCommand.IsHidden = true;

                installCommand.Handler = CommandHandler.Create <InstallOptions, IConsole>((options, console) => install(options, console));

                return(installCommand);
            }

            Command Verify()
            {
                var verifyCommand = new Command("verify", "Verify Markdown files in the target directory and its children.")
                {
                    dirArgument
                };

                verifyCommand.Handler = CommandHandler.Create <VerifyOptions, IConsole, StartupOptions>(
                    (options, console, startupOptions) =>
                {
                    return(verify(options, console, startupOptions));
                });

                return(verifyCommand);
            }
        }
        static CommandLineConfigs()
        {
            UninstallRootCommand.AddArgument(new Argument <IEnumerable <string> >
            {
                Name        = LocalizableStrings.UninstallNoOptionArgumentName,
                Description = LocalizableStrings.UninstallNoOptionArgumentDescription
            });

            UninstallRootCommand.AddCommand(ListCommand);

            var supportedBundleTypeNames = SupportedBundleTypeConfigs.GetSupportedBundleTypes().Select(type => type.OptionName);

            var supportedUninstallBundleTypeOptions = new Option[]
            {
                UninstallSdkOption,
                UninstallRuntimeOption,
                UninstallAspNetRuntimeOption,
                UninstallHostingBundleOption
            }
            .Where(option => supportedBundleTypeNames.Contains(option.Name));

            var supportedListBundleTypeOptions = new Option[]
            {
                ListSdkOption,
                ListRuntimeOption,
                ListAspNetRuntimeOption,
                ListHostingBundleOption
            }
            .Where(option => supportedBundleTypeNames.Contains(option.Name));

            UninstallAuxOptions = supportedUninstallBundleTypeOptions
                                  .Append(VerbosityOption)
                                  .Append(UninstallX64Option)
                                  .Append(UninstallX86Option)
                                  .Append(VersionOption)
                                  .Append(DryRunOption)
                                  .Append(YesOption);

            ListAuxOptions = supportedListBundleTypeOptions
                             .Append(VerbosityOption)
                             .Append(ListX64Option)
                             .Append(ListX86Option);

            foreach (var option in UninstallMainOptions
                     .Concat(UninstallAuxOptions)
                     .OrderBy(option => option.Name))
            {
                UninstallRootCommand.AddOption(option);
            }

            foreach (var option in ListAuxOptions
                     .OrderBy(option => option.Name))
            {
                ListCommand.AddOption(option);
            }

            ListCommand.Handler          = CommandHandler.Create(ExceptionHandler.HandleException(() => ListCommandExec.Execute()));
            UninstallRootCommand.Handler = CommandHandler.Create(ExceptionHandler.HandleException(() => UninstallCommandExec.Execute()));

            CommandLineParseResult = UninstallRootCommand.Parse(Environment.GetCommandLineArgs());
        }
Exemple #20
0
        public static Parser Create(
            IServiceCollection services,
            StartServer startServer = null,
            Demo demo           = null,
            TryGitHub tryGithub = null,
            Pack pack           = null,
            Install install     = null,
            Verify verify       = null,
            Jupyter jupyter     = null)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            startServer = startServer ??
                          ((options, invocationContext) =>
                           Program.ConstructWebHost(options).Run());

            jupyter = jupyter ??
                      JupyterCommand.Do;

            demo = demo ??
                   DemoCommand.Do;

            tryGithub = tryGithub ??
                        ((repo, console) =>
                         GitHubHandler.Handler(repo,
                                               console,
                                               new GitHubRepoLocator()));

            verify = verify ??
                     ((verifyOptions, console, startupOptions) =>
                      VerifyCommand.Do(verifyOptions,
                                       console,
                                       () => new FileSystemDirectoryAccessor(verifyOptions.Dir),
                                       PackageRegistry.CreateForTryMode(verifyOptions.Dir),
                                       startupOptions));

            pack = pack ??
                   PackCommand.Do;

            install = install ??
                      InstallCommand.Do;


            var dirArgument = new Argument <DirectoryInfo>
            {
                Arity       = ArgumentArity.ZeroOrOne,
                Name        = nameof(StartupOptions.Dir).ToLower(),
                Description = "Specify the path to the root directory for your documentation"
            }.ExistingOnly();

            var rootCommand = StartInTryMode();

            rootCommand.AddCommand(StartInHostedMode());
            rootCommand.AddCommand(Demo());
            rootCommand.AddCommand(GitHub());
            rootCommand.AddCommand(Pack());
            rootCommand.AddCommand(Install());
            rootCommand.AddCommand(Verify());
            rootCommand.AddCommand(Jupyter());

            return(new CommandLineBuilder(rootCommand)
                   .UseDefaults()
                   .UseMiddleware(async(context, next) =>
            {
                if (context.ParseResult.Directives.Contains("debug") &&
                    !(Clock.Current is VirtualClock))
                {
                    VirtualClock.Start();
                }

                await next(context);
            })
                   .Build());

            RootCommand StartInTryMode()
            {
                var command = new RootCommand
                {
                    Name        = "dotnet-try",
                    Description = "Interactive documentation in your browser"
                };

                command.AddArgument(dirArgument);

                command.AddOption(new Option(
                                      "--add-package-source",
                                      "Specify an additional NuGet package source")
                {
                    Argument = new Argument <PackageSource>(() => new PackageSource(Directory.GetCurrentDirectory()))
                    {
                        Name = "NuGet source"
                    }
                });

                command.AddOption(new Option(
                                      "--package",
                                      "Specify a Try .NET package or path to a .csproj to run code samples with")
                {
                    Argument = new Argument <string>
                    {
                        Name = "name or .csproj"
                    }
                });

                command.AddOption(new Option(
                                      "--package-version",
                                      "Specify a Try .NET package version to use with the --package option")
                {
                    Argument = new Argument <string>
                    {
                        Name = "version"
                    }
                });

                command.AddOption(new Option(
                                      "--uri",
                                      "Specify a URL or a relative path to a Markdown file")
                {
                    Argument = new Argument <Uri>()
                });

                command.AddOption(new Option(
                                      "--enable-preview-features",
                                      "Enable preview features")
                {
                    Argument = new Argument <bool>()
                });

                command.AddOption(new Option(
                                      "--log-path",
                                      "Enable file logging to the specified directory")
                {
                    Argument = new Argument <DirectoryInfo>
                    {
                        Name = "dir"
                    }
                });

                command.AddOption(new Option(
                                      "--verbose",
                                      "Enable verbose logging to the console")
                {
                    Argument = new Argument <bool>()
                });

                var portArgument = new Argument <ushort>();

                portArgument.AddValidator(symbolResult =>
                {
                    if (symbolResult.Tokens
                        .Select(t => t.Value)
                        .Count(value => !ushort.TryParse(value, out _)) > 0)
                    {
                        return("Invalid argument for --port option");
                    }

                    return(null);
                });

                command.AddOption(new Option(
                                      "--port",
                                      "Specify the port for dotnet try to listen on")
                {
                    Argument = portArgument
                });

                command.Handler = CommandHandler.Create <InvocationContext, StartupOptions>((context, options) =>
                {
                    services.AddSingleton(_ => PackageRegistry.CreateForTryMode(
                                              options.Dir,
                                              options.AddPackageSource));

                    startServer(options, context);
                });

                return(command);
            }

            Command StartInHostedMode()
            {
                var command = new Command("hosted")
                {
                    new Option(
                        "--id",
                        "A unique id for the agent instance (e.g. its development environment id).")
                    {
                        Argument = new Argument <string>(defaultValue: () => Environment.MachineName)
                    },
                    new Option(
                        "--production",
                        "Specifies whether the agent is being run using production resources")
                    {
                        Argument = new Argument <bool>()
                    },
                    new Option(
                        "--language-service",
                        "Specifies whether the agent is being run in language service-only mode")
                    {
                        Argument = new Argument <bool>()
                    },
                    new Option(
                        new[]
                    {
                        "-k",
                        "--key"
                    },
                        "The encryption key")
                    {
                        Argument = new Argument <string>()
                    },
                    new Option(
                        new[]
                    {
                        "--ai-key",
                        "--application-insights-key"
                    },
                        "Application Insights key.")
                    {
                        Argument = new Argument <string>()
                    },
                    new Option(
                        "--region-id",
                        "A unique id for the agent region")
                    {
                        Argument = new Argument <string>()
                    },
                    new Option(
                        "--log-to-file",
                        "Writes a log file")
                    {
                        Argument = new Argument <bool>()
                    }
                };

                command.Description = "Starts the Try .NET agent";

                command.IsHidden = true;

                command.Handler = CommandHandler.Create <InvocationContext, StartupOptions>((context, options) =>
                {
                    services.AddSingleton(_ => PackageRegistry.CreateForHostedMode());
                    services.AddSingleton(c => new MarkdownProject(c.GetRequiredService <PackageRegistry>()));
                    services.AddSingleton <IHostedService, Warmup>();

                    startServer(options, context);
                });

                return(command);
            }

            Command Demo()
            {
                var demoCommand = new Command(
                    "demo",
                    "Learn how to create Try .NET content with an interactive demo")
                {
                    new Option("--output", "Where should the demo project be written to?")
                    {
                        Argument = new Argument <DirectoryInfo>(
                            defaultValue: () => new DirectoryInfo(Directory.GetCurrentDirectory()))
                    }
                };

                demoCommand.Handler = CommandHandler.Create <DemoOptions, InvocationContext>((options, context) =>
                {
                    demo(options, context.Console, startServer, context);
                });

                return(demoCommand);
            }

            Command GitHub()
            {
                var argument = new Argument <string>
                {
                    // System.CommandLine parameter binding does lookup by name,
                    // so name the argument after the github command's string param
                    Name = nameof(TryGitHubOptions.Repo)
                };

                var github = new Command("github", "Try a GitHub repo")
                {
                    argument
                };

                github.IsHidden = true;

                github.Handler = CommandHandler.Create <TryGitHubOptions, IConsole>((repo, console) => tryGithub(repo, console));

                return(github);
            }

            Command Jupyter()
            {
                var jupyterCommand = new Command("jupyter", "Starts dotnet try as a Jupyter kernel")
                {
                    IsHidden = true
                };
                var connectionFileArgument = new Argument <FileInfo>
                {
                    Name = "ConnectionFile"
                }.ExistingOnly();

                jupyterCommand.AddArgument(connectionFileArgument);

                jupyterCommand.Handler = CommandHandler.Create <JupyterOptions, IConsole, InvocationContext>((options, console, context) =>
                {
                    services
                    .AddSingleton(c => ConnectionInformation.Load(options.ConnectionFile))
                    .AddSingleton(
                        c =>
                    {
                        return(CommandScheduler
                               .Create <JupyterRequestContext>(delivery => c.GetRequiredService <ICommandHandler <JupyterRequestContext> >()
                                                               .Trace()
                                                               .Handle(delivery)));
                    })
                    .AddTransient <IKernel>(c => new CompositeKernel
                    {
                        new CSharpKernel().UseNugetDirective()
                    })
                    .AddSingleton(c => new JupyterRequestContextHandler(
                                      c.GetRequiredService <PackageRegistry>(),
                                      c.GetRequiredService <IKernel>())
                                  .Trace())
                    .AddSingleton <IHostedService, Shell>()
                    .AddSingleton <IHostedService, Heartbeat>();

                    return(jupyter(options, console, startServer, context));
                });

                return(jupyterCommand);
            }

            Command Pack()
            {
                var packCommand = new Command("pack", "Create a Try .NET package")
                {
                    new Argument <DirectoryInfo>
                    {
                        Name = nameof(PackOptions.PackTarget)
                    },
                    new Option("--version", "The version of the Try .NET package")
                    {
                        Argument = new Argument <string>()
                    },
                    new Option("--enable-wasm", "Enables web assembly code execution")
                };

                packCommand.IsHidden = true;

                packCommand.Handler = CommandHandler.Create <PackOptions, IConsole>(
                    (options, console) =>
                {
                    return(pack(options, console));
                });

                return(packCommand);
            }

            Command Install()
            {
                var installCommand = new Command("install", "Install a Try .NET package")
                {
                    new Argument <string>
                    {
                        Name = nameof(InstallOptions.PackageName)
                    },
                    new Option("--add-source")
                    {
                        Argument = new Argument <PackageSource>()
                    }
                };

                installCommand.IsHidden = true;

                installCommand.Handler = CommandHandler.Create <InstallOptions, IConsole>((options, console) => install(options, console));

                return(installCommand);
            }

            Command Verify()
            {
                var verifyCommand = new Command("verify", "Verify Markdown files in the target directory and its children.")
                {
                    dirArgument
                };

                verifyCommand.Handler = CommandHandler.Create <VerifyOptions, IConsole, StartupOptions>(
                    (options, console, startupOptions) =>
                {
                    return(verify(options, console, startupOptions));
                });

                return(verifyCommand);
            }
        }
Exemple #21
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));
        }
Exemple #22
0
        static void Main(string[] args)
        {
            var rootCommand = new RootCommand()
            {
                Name        = "AndroidBackupUnpacker",
                Description = "Tool for converting and unpacking android backups - Luka Kusulja",
            };

            var backupFileNameArgument = new Argument <string>("backup");

            rootCommand.AddArgument(backupFileNameArgument);

            var convertCommand = new Command("--convert", "Convert backtup to TAR archive")
            {
                new Argument <string>("tar")
            };

            rootCommand.AddCommand(convertCommand);

            var unpackCommand = new Command("--unpack", "Extract content to folder")
            {
                new Argument <string>("folder")
            };

            rootCommand.AddCommand(unpackCommand);

            var exitCodesCommand = new Command("--exitcodes", "Print exit code list");

            rootCommand.AddCommand(exitCodesCommand);

            rootCommand.AddGlobalOption(new Option("--password", "Password if the backup is encrypted")
            {
                Argument = new Argument <string>("password")
            });

            convertCommand.Handler = CommandHandler.Create <string, string, string>(
                (backup, tar, password) =>
            {
                UnpackBackup(backup, tar, false, password);
            });

            unpackCommand.Handler = CommandHandler.Create <string, string, string>(
                (backup, folder, password) =>
            {
                UnpackBackup(backup, folder, true, password);
            });

            exitCodesCommand.Handler = CommandHandler.Create(
                () =>
            {
                PrintExitCodes();
            });

            rootCommand.Handler = CommandHandler.Create(
                () =>
            {
                Console.Error.WriteLine("Missing command");
                Environment.Exit((int)ExitCode.MissingCommand);
            });

            rootCommand.Invoke(args);
        }
        public void Binding_is_correct_for_Func_overload_having_arity_(int arity)
        {
            var command     = new RootCommand();
            var commandLine = "";

            for (var i = 1; i <= arity; i++)
            {
                command.AddArgument(new Argument <int>($"i{i}"));

                commandLine += $" {i}";
            }

            var      receivedValues = new List <int>();
            Delegate handlerFunc    = arity switch
            {
                1 => new Func <int, Task>(
                    i1 =>
                    Received(i1)),
                2 => new Func <int, int, Task>(
                    (i1, i2) =>
                    Received(i1, i2)),
                3 => new Func <int, int, int, Task>(
                    (i1, i2, i3) =>
                    Received(i1, i2, i3)),
                4 => new Func <int, int, int, int, Task>(
                    (i1, i2, i3, i4) =>
                    Received(i1, i2, i3, i4)),
                5 => new Func <int, int, int, int, int, Task>(
                    (i1, i2, i3, i4, i5) =>
                    Received(i1, i2, i3, i4, i5)),
                6 => new Func <int, int, int, int, int, int, Task>(
                    (i1, i2, i3, i4, i5, i6) =>
                    Received(i1, i2, i3, i4, i5, i6)),
                7 => new Func <int, int, int, int, int, int, int, Task>(
                    (i1, i2, i3, i4, i5, i6, i7) =>
                    Received(i1, i2, i3, i4, i5, i6, i7)),
                8 => new Func <int, int, int, int, int, int, int, int, Task>(
                    (i1, i2, i3, i4, i5, i6, i7, i8) =>
                    Received(i1, i2, i3, i4, i5, i6, i7, i8)),
                9 => new Func <int, int, int, int, int, int, int, int, int, Task>(
                    (i1, i2, i3, i4, i5, i6, i7, i8, i9) =>
                    Received(i1, i2, i3, i4, i5, i6, i7, i8, i9)),
                10 => new Func <int, int, int, int, int, int, int, int, int, int, Task>(
                    (i1, i2, i3, i4, i5, i6, i7, i8, i9, i10) =>
                    Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10)),
                11 => new Func <int, int, int, int, int, int, int, int, int, int, int, Task>(
                    (i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11) =>
                    Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11)),
                12 => new Func <int, int, int, int, int, int, int, int, int, int, int, int, Task>(
                    (i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12) =>
                    Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12)),
                13 => new Func <int, int, int, int, int, int, int, int, int, int, int, int, int, Task>(
                    (i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13) =>
                    Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13)),
                14 => new Func <int, int, int, int, int, int, int, int, int, int, int, int, int, int, Task>(
                    (i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14) =>
                    Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14)),
                15 => new Func <int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, Task>(
                    (i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15) =>
                    Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15)),
                16 => new Func <int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, Task>(
                    (i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16) =>
                    Received(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16)),

                _ => throw new ArgumentOutOfRangeException()
            };

            // build up the method invocation
            var genericMethodDef = typeof(Handler)
                                   .GetMethods()
                                   .Where(m => m.Name == nameof(Handler.SetHandler))
                                   .Where(m => m.IsGenericMethod /* symbols + handler Func */)
                                   .Where(m => m.GetParameters().ElementAt(1).ParameterType.Name.StartsWith("Func"))
                                   .Single(m => m.GetGenericArguments().Length == arity);

            var genericParameterTypes = Enumerable.Range(1, arity)
                                        .Select(_ => typeof(int))
                                        .ToArray();

            var setHandler = genericMethodDef.MakeGenericMethod(genericParameterTypes);

            var parameters = new List <object>
            {
                command,
                handlerFunc,
                command.Arguments.ToArray()
            };

            setHandler.Invoke(null, parameters.ToArray());

            var exitCode = command.Invoke(commandLine);

            receivedValues.Should().BeEquivalentTo(
                Enumerable.Range(1, arity),
                config => config.WithStrictOrdering());

            exitCode.Should().Be(123);

            Task Received(params int[] values)
            {
                receivedValues.AddRange(values);
                return(Task.FromResult(123));
            }
        }
Exemple #24
0
        public static Parser Create(
            IServiceCollection services,
            StartServer startServer = null,
            Install install         = null,
            Demo demo            = null,
            TryGitHub tryGithub  = null,
            Pack pack            = null,
            Verify verify        = null,
            Publish publish      = null,
            ITelemetry telemetry = null,
            IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel = null)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            startServer ??= (startupOptions, invocationContext) =>
            Program.ConstructWebHost(startupOptions).Run();

            demo ??= DemoCommand.Do;

            tryGithub ??= (repo, console) =>
            GitHubHandler.Handler(repo,
                                  console,
                                  new GitHubRepoLocator());

            verify ??= VerifyCommand.Do;

            publish ??= (options, console, startupOptions) =>
            PublishCommand.Do(options,
                              console,
                              startupOptions);

            pack ??= PackCommand.Do;

            // Setup first time use notice sentinel.
            firstTimeUseNoticeSentinel ??=
            new FirstTimeUseNoticeSentinel(VersionSensor.Version().AssemblyInformationalVersion);

            // Setup telemetry.
            telemetry ??= new Telemetry(
                VersionSensor.Version().AssemblyInformationalVersion,
                firstTimeUseNoticeSentinel);
            var filter = new TelemetryFilter(Sha256Hasher.HashWithNormalizedCasing);
            Action <ParseResult> track = o => telemetry.SendFiltered(filter, o);

            var dirArgument = new Argument <FileSystemDirectoryAccessor>(result =>
            {
                var directory = result.Tokens
                                .Select(t => t.Value)
                                .FirstOrDefault();

                if (!string.IsNullOrEmpty(directory) &&
                    !Directory.Exists(directory))
                {
                    result.ErrorMessage = $"Directory does not exist: {directory}";
                    return(null);
                }

                return(new FileSystemDirectoryAccessor(
                           directory ??
                           Directory.GetCurrentDirectory()));
            }, isDefault: true)
            {
                Name        = "root-directory",
                Arity       = ArgumentArity.ZeroOrOne,
                Description = "The root directory for your documentation"
            };

            var rootCommand = StartInTryMode();

            rootCommand.AddCommand(StartInHostedMode());
            rootCommand.AddCommand(Demo());
            rootCommand.AddCommand(GitHub());
            rootCommand.AddCommand(Install());
            rootCommand.AddCommand(Pack());
            rootCommand.AddCommand(Verify());
            rootCommand.AddCommand(Publish());

            return(new CommandLineBuilder(rootCommand)
                   .UseDefaults()
                   .UseMiddleware(async(context, next) =>
            {
                if (context.ParseResult.Errors.Count == 0)
                {
                    telemetry.SendFiltered(filter, context.ParseResult);
                }

                // If sentinel does not exist, print the welcome message showing the telemetry notification.
                if (!firstTimeUseNoticeSentinel.Exists() && !Telemetry.SkipFirstTimeExperience)
                {
                    context.Console.Out.WriteLine();
                    context.Console.Out.WriteLine(Telemetry.WelcomeMessage);

                    firstTimeUseNoticeSentinel.CreateIfNotExists();
                }

                if (context.ParseResult.Directives.Contains("debug") &&
                    !(Clock.Current is VirtualClock))
                {
                    VirtualClock.Start();
                }

                await next(context);
            })
                   .Build());

            RootCommand StartInTryMode()
            {
                var command = new RootCommand
                {
                    Name        = "dotnet-try",
                    Description = "Interactive documentation in your browser"
                };

                command.AddArgument(dirArgument);

                command.AddOption(new Option(
                                      "--add-package-source",
                                      "Specify an additional NuGet package source")
                {
                    Argument = new Argument <PackageSource>(() => new PackageSource(Directory.GetCurrentDirectory()))
                    {
                        Name = "NuGet source"
                    }
                });

                command.AddOption(new Option(
                                      "--package",
                                      "Specify a Try .NET package or path to a .csproj to run code samples with")
                {
                    Argument = new Argument <string>
                    {
                        Name = "name or .csproj"
                    }
                });

                command.AddOption(new Option(
                                      "--package-version",
                                      "Specify a Try .NET package version to use with the --package option")
                {
                    Argument = new Argument <string>
                    {
                        Name = "version"
                    }
                });

                command.AddOption(new Option <Uri>(
                                      "--uri",
                                      "Specify a URL or a relative path to a Markdown file"));

                command.AddOption(new Option <bool>(
                                      "--enable-preview-features",
                                      "Enable preview features"));

                command.AddOption(new Option(
                                      "--log-path",
                                      "Enable file logging to the specified directory")
                {
                    Argument = new Argument <DirectoryInfo>
                    {
                        Name = "dir"
                    }
                });

                command.AddOption(new Option <bool>(
                                      "--verbose",
                                      "Enable verbose logging to the console"));

                var portArgument = new Argument <ushort>();

                portArgument.AddValidator(symbolResult =>
                {
                    if (symbolResult.Tokens
                        .Select(t => t.Value)
                        .Count(value => !ushort.TryParse(value, out _)) > 0)
                    {
                        return("Invalid argument for --port option");
                    }

                    return(null);
                });

                command.AddOption(new Option(
                                      "--port",
                                      "Specify the port for dotnet try to listen on")
                {
                    Argument = portArgument
                });

                command.Handler = CommandHandler.Create <InvocationContext, StartupOptions>((context, options) =>
                {
                    services.AddSingleton(_ => PackageRegistry.CreateForTryMode(
                                              options.RootDirectory,
                                              options.AddPackageSource));

                    startServer(options, context);
                });

                return(command);
            }

            Command StartInHostedMode()
            {
                var command = new Command("hosted")
                {
                    new Option <string>(
                        "--id",
                        description: "A unique id for the agent instance (e.g. its development environment id).",
                        getDefaultValue: () => Environment.MachineName),
                    new Option <bool>(
                        "--production",
                        "Specifies whether the agent is being run using production resources"),
                    new Option <bool>(
                        "--language-service",
                        "Specifies whether the agent is being run in language service-only mode"),
                    new Option <string>(
                        new[]
                    {
                        "-k",
                        "--key"
                    },
                        "The encryption key"),
                    new Option <string>(
                        new[]
                    {
                        "--ai-key",
                        "--application-insights-key"
                    },
                        "Application Insights key."),
                    new Option <string>(
                        "--region-id",
                        "A unique id for the agent region"),
                    new Option <bool>(
                        "--log-to-file",
                        "Writes a log file")
                };

                command.Description = "Starts the Try .NET agent";

                command.IsHidden = true;

                command.Handler = CommandHandler.Create <InvocationContext, StartupOptions>((context, options) =>
                {
                    services.AddSingleton(_ => PackageRegistry.CreateForHostedMode());
                    services.AddSingleton(c => new MarkdownProject(c.GetRequiredService <PackageRegistry>()));
                    startServer(options, context);
                });

                return(command);
            }

            Command Demo()
            {
                var demoCommand = new Command(
                    "demo",
                    "Learn how to create Try .NET content with an interactive demo")
                {
                    new Option <DirectoryInfo>(
                        "--output",
                        description: "Where should the demo project be written to?",
                        getDefaultValue: () => new DirectoryInfo(Directory.GetCurrentDirectory()))
                };

                demoCommand.Handler = CommandHandler.Create <DemoOptions, InvocationContext>((options, context) => { demo(options, context.Console, startServer, context); });

                return(demoCommand);
            }

            Command GitHub()
            {
                var argument = new Argument <string>
                {
                    // System.CommandLine parameter binding does lookup by name,
                    // so name the argument after the github command's string param
                    Name = nameof(TryGitHubOptions.Repo)
                };

                var github = new Command("github", "Try a GitHub repo")
                {
                    argument
                };

                github.IsHidden = true;

                github.Handler = CommandHandler.Create <TryGitHubOptions, IConsole>((repo, console) => tryGithub(repo, console));

                return(github);
            }

            Command Install()
            {
                var installCommand = new Command("install", "Install a Try .NET package")
                {
                    new Argument <string>
                    {
                        Name  = nameof(InstallOptions.PackageName),
                        Arity = ArgumentArity.ExactlyOne
                    },
                    new Option <PackageSource>("--add-source")
                };

                installCommand.IsHidden = true;

                installCommand.Handler = CommandHandler.Create <InstallOptions, IConsole>((options, console) => install(options, console));

                return(installCommand);
            }

            Command Pack()
            {
                var packCommand = new Command("pack", "Create a Try .NET package")
                {
                    new Argument <DirectoryInfo>
                    {
                        Name = nameof(PackOptions.PackTarget)
                    },
                    new Option <string>("--version", "The version of the Try .NET package"),
                    new Option <bool>("--enable-wasm", "Enables web assembly code execution")
                };

                packCommand.IsHidden = true;

                packCommand.Handler = CommandHandler.Create <PackOptions, IConsole>(
                    (options, console) =>
                {
                    return(pack(options, console));
                });

                return(packCommand);
            }

            Command Verify()
            {
                var verifyCommand = new Command("verify", "Verify Markdown files found under the root directory.")
                {
                    dirArgument
                };

                verifyCommand.Handler = CommandHandler.Create <VerifyOptions, IConsole, StartupOptions>(
                    (options, console, startupOptions) =>
                {
                    return(verify(options, console, startupOptions));
                });

                return(verifyCommand);
            }

            Command Publish()
            {
                var publishCommand = new Command("publish", "Publish code from sample projects found under the root directory into Markdown files in the target directory")
                {
                    new Option <PublishFormat>(
                        "--format",
                        description: "Format of the files to publish",
                        getDefaultValue: () => PublishFormat.Markdown),
                    new Option <IDirectoryAccessor>(
                        "--target-directory",
                        description: "The path where the output files should go. This can be the same as the root directory, which will overwrite files in place.",
                        parseArgument: result =>
                    {
                        var directory = result.Tokens
                                        .Select(t => t.Value)
                                        .Single();

                        return(new FileSystemDirectoryAccessor(directory));
                    }
                        ),
                    dirArgument
                };

                publishCommand.Handler = CommandHandler.Create <PublishOptions, IConsole, StartupOptions>(
                    (options, console, startupOptions) => publish(options, console, startupOptions));

                return(publishCommand);
            }
        }
Exemple #25
0
        public static Task <int> Main(string[] args)
        {
            var mimeOption = new Option("--mime")
            {
                Name        = "mime",
                Description = "MIME type indicating the type of data",
                Argument    = new Argument <MediaTypeHeaderValue>
                {
                    Name        = "MIME",
                    Description = "RFC 2616 compliant Media-Type header value, like text/plain",
                    Arity       = ArgumentArity.ZeroOrOne
                }
            };

            mimeOption.AddAlias("-m");
            mimeOption.Argument.AddValidator(symbol => symbol.Tokens.Select(t => t.Value)
                                             .Select(m =>
            {
                try
                {
                    _ = MediaTypeHeaderValue.Parse(m);
                    return(null);
                }
                catch (FormatException)
                {
                    return($"Invalid MIME format: '{m}'");
                }
            })
                                             .FirstOrDefault(msg => msg is string)
                                             );

            var charsetOption = new Option("--charset")
            {
                Name        = "charset",
                Description = "Add charset to mime-type",
                Argument    = new Argument
                {
                    Name        = "ENCODING",
                    Description = "Text encoding web name",
                    Arity       = ArgumentArity.ZeroOrOne
                }
            };

            charsetOption.AddAlias("-c");
            charsetOption.Argument.AddSuggestions(Encoding
                                                  .GetEncodings()
                                                  .Select(i => i.Name)
                                                  .ToList());

            var fileArgument = new Argument <FileInfo>
            {
                Name        = "FILE",
                Description = "Path to file. Omit or use '-' for STDIN",
                Arity       = ArgumentArity.ZeroOrOne
            };

            fileArgument.AddValidator(symbol => symbol.Tokens
                                      .Select(t => t.Value)
                                      .Where(p => p != "-" && !File.Exists(p))
                                      .Select(ValidationMessages.Instance.FileDoesNotExist)
                                      .FirstOrDefault()
                                      );

            var rootCommand = new RootCommand(typeof(Program).Assembly.GetCustomAttribute <AssemblyDescriptionAttribute>()?.Description)
            {
                Handler = CommandHandler.Create <ParseResult, CancellationToken>(RunAsync)
            };

            rootCommand.AddArgument(fileArgument);

            var parser = new CommandLineBuilder(rootCommand)
                         .AddOption(mimeOption)
                         .AddOption(charsetOption)
                         .UseDefaults()
                         .Build();

            return(parser.InvokeAsync(args));

            async Task RunAsync(ParseResult parseResult, CancellationToken cancelToken)
            {
                var mimeValue = parseResult.FindResultFor(mimeOption)?
                                .GetValueOrDefault <MediaTypeHeaderValue>();
                var charsetValue = parseResult.FindResultFor(charsetOption)?
                                   .GetValueOrDefault <string>();

                if (charsetValue is string)
                {
                    if (mimeValue is null)
                    {
                        mimeValue = new MediaTypeHeaderValue("text/plain");
                    }
                    if (string.IsNullOrEmpty(mimeValue.CharSet))
                    {
                        mimeValue.CharSet = charsetValue;
                    }
                }

                var mimeString = mimeValue?.ToString();

                var    fileResult = parseResult.FindResultFor(fileArgument);
                Stream fileStream;

                if (fileResult is null || fileResult.Tokens.Single().Value == "-")
                {
                    fileStream = Console.OpenStandardInput();
                }
Exemple #26
0
        private static int MiddlewarePipeline(params string[] args)
        {
            // Create some options and a parser
            var optionThatTakesInt = new Option <int[]>(
                name: "--int-option",
                description: "An option whose argument is parsed as an int[]",
                getDefaultValue: () => new int[] { 1, 2, 3 })
            {
                Arity    = ArgumentArity.OneOrMore,
                IsHidden = false
            };

            optionThatTakesInt.AddAlias("-i");

            // optionThatTakesInt.
            var optionThatTakesBool = new Option <bool>(
                name: "--bool-option",
                description: "An option whose argument is parsed as a bool")
            {
                Arity = ArgumentArity.ZeroOrOne,
            };

            optionThatTakesBool.AddAlias("-b");

            var optionThatTakesFileInfo = new Option <FileInfo>(
                name: "--file-option",
                description: "An option whose argument is parsed as a FileInfo")
            {
                Arity = ArgumentArity.ExactlyOne
            };

            // Add them to the root command
            // var rootCommand = new RootCommand();
            var rootCommand = new RootCommand("My sample app");

            rootCommand.AddAlias("pgapp");

            // rootCommand.AddOption(optionThatTakesInt);
            // rootCommand.AddOption(optionThatTakesBool);
            // rootCommand.AddOption(optionThatTakesFileInfo);

            // ※ Argument顺序重要
            Argument argument = new Argument()
            {
                Name        = "playground",
                ValueType   = typeof(string),
                Description = "默认参数"
            };

            // Suggest信息会显示在help中,并且会覆盖argument.name
            argument.AddCompletions(new string[]
            {
                "Suggest1",
                "Suggest2",
                "substring suggest"
            });
            // rootCommand.AddArgument(argument);
            Argument <string> argument1 = new Argument <string>("arg1")
            {
                Description = "string参数"
            };

            argument1.Completions.Add(new SimpleSuggestSource());
            // rootCommand.AddArgument(argument1);
            Argument <int> argument2 = new Argument <int>("arg2");

            argument2.AddCompletions(c =>
            {
                // Console.WriteLine($"textToMatch:\u001b[31m{textToMatch}\u001b[0m");
                return(new string[]
                {
                    "world"
                });
            });
            // rootCommand.AddArgument(argument2);

            // ※ handler中可以乱序
            rootCommand.Handler = CommandHandler.Create <InvocationContext, string, int, string, int[], bool, FileInfo>((context, playground, arg2, arg1, intOption, boolOption, fileOption) =>
            {
                Console.WriteLine("Arguments:");
                Console.WriteLine($"\tplayground:{playground}");
                Console.WriteLine($"\targ1:{arg1}");
                Console.WriteLine($"\targ2:{arg2}");

                Console.WriteLine("Options:");
                foreach (var item in intOption)
                {
                    Console.WriteLine($"\tThe value for --int-option is: {item}");
                }
                Console.WriteLine($"\tThe value for --bool-option is: {boolOption}");
                Console.WriteLine($"\tThe value for --file-option is: {fileOption?.FullName ?? "null"}");
            });

            // rootCommand.Handler = CommandHandler.Create((IConsole console, CancellationToken token) =>
            // {
            //     return 0;
            // });

            // return rootCommand.InvokeAsync(new string[] { "-b" }).GetAwaiter().GetResult();
            // return rootCommand.InvokeAsync(new string[] { "-i:1", "-i:2", "-b" }).GetAwaiter().GetResult();

            // Console.WriteLine("inited");

            rootCommand.AddCommand(BuildSubcommand());
            rootCommand.AddCommand(BuildErrorSubcommand());
            rootCommand.AddGlobalOption(new Option("--global", "global option sample"));// 全局选项,适用到所有子命令
            rootCommand.AddOption(optionThatTakesInt);
            rootCommand.AddOption(optionThatTakesBool);
            rootCommand.AddOption(optionThatTakesFileInfo);
            rootCommand.AddArgument(argument);
            rootCommand.AddArgument(argument1);
            rootCommand.AddArgument(argument2);

            var builder = new CommandLineBuilder(rootCommand)

                                                            // .EnablePositionalOptions(value: true)/* 无用 */

                          .EnablePosixBundling(value: true) /*  对无值option生效,-b */

                                                            // .ParseResponseFileAs(responseFileHandling: ResponseFileHandling.ParseArgsAsLineSeparated) /*  添加@起始参数,从文件读取命令 */
                          .ParseResponseFileAs(responseFileHandling: ResponseFileHandling.ParseArgsAsSpaceSeparated)

                          // .UseDefaults()
                                                        ////.UseVersionOption()
                          .UseHelp()
                                                        ////.UseEnvironmentVariableDirective()
                                                        ////.UseParseDirective()
                                                        ////.UseDebugDirective()
                                                        ////.UseSuggestDirective()
                                                        ////.RegisterWithDotnetSuggest()
                                                        ////.UseTypoCorrections()
                                                        ////.UseParseErrorReporting()
                                                        ////.UseExceptionHandler()
                                                        ////.CancelOnProcessTermination()

                                                        // /* 自定义帮助信息输出类 */
                                                        // .UseHelpBuilder(context =>
                                                        // {
                                                        //     return new HelpBuilder(new LocalizationResources());
                                                        // })

                          .UseVersionOption()           // 版本号选项,--version

                          .CancelOnProcessTermination() // 控制台ctrl+c取消事件

                                                        // 设置console
                          .ConfigureConsole(context =>
            {
                return(context.Console);
            })
                          .RegisterWithDotnetSuggest() // 需要安装dotnet-suggest

                          .UseDebugDirective()         // 使用[debug]指令

                                                       // 命令异常处理
                          .UseExceptionHandler((ex, context) =>
            {
                context.Console.Error.WriteLine($"ExceptionHandler<{ex.GetType()}>:\u001b[31m{ex.Message}\u001b[0m");
            })

                          // | lv  | value | MiddlewareOrderInternal      | MiddlewareOrder  |
                          // | --- | ----- | ---------------------------- | ---------------- |
                          // | 1   | -4000 | Startup                      |                  |
                          // | 2   | -3000 | ExceptionHandler             |                  |
                          // | 3   | -2600 | EnvironmentVariableDirective |                  |
                          // | 4   | -2500 | ConfigureConsole             |                  |
                          // | 5   | -2400 | RegisterWithDotnetSuggest    |                  |
                          // | 6   | -2300 | DebugDirective               |                  |
                          // | 7   | -2200 | ParseDirective               |                  |
                          // | 8   | -2000 | SuggestDirective             | ExceptionHandler |
                          // | 9   | -1900 | TypoCorrection               |                  |
                          // | 10  | -1200 | VersionOption                |                  |
                          // | 11  | -1100 | HelpOption                   |                  |
                          // | 12  | -1000 |                              | Configuration    |
                          // | 13  | 0     |                              | Default          |
                          // | 14  | 1000  | ParseErrorReporting          | ErrorReporting   |
                          // .UseHelp()/* help中间件优先级为11级 */
                          // .UseHelpBuilder(context => new HelpBuilder(context.Console))

                          // 普通中间件优先级为13级
                          .AddMiddleware(context =>
            {
                // 默认执行后续中间件
                if (context.ParseResult.Directives.TryGetValues("command", out IReadOnlyList <string> value))
                {
                    Console.WriteLine(string.Join(',', value.ToArray()));
                }
            })
                          .AddMiddleware(async(context, next) =>
            {
                // 选择执行后续中间件
                if (context.ParseResult.Directives.Contains("just-say-hi"))
                {
                    context.Console.Out.WriteLine("Hi!");
                    if (context.ParseResult.Directives.Contains("just-say-hi2"))
                    {
                        context.Console.Out.WriteLine("Hi2!");
                    }
                }
                else
                {
                    await next(context);
                }
            })
                          .AddMiddleware(async(context, next) =>
            {
                if (context.ParseResult.Directives.Contains("Simple"))
                {
                    context.InvocationResult = new SimpleResult();
                }
                await next(context);
            })
                          .UseParseDirective()
                          // 当解析失败直接返回,不会执行设置的中间件
                          .UseParseErrorReporting()

                          // 拼写错误提示
                          // 0.3.0-alpha.19317.1 bug command有参数时异常 https://github.com/dotnet/command-line-api/issues/578
                          .UseTypoCorrections()

                          // 显示argument添加的suggest,并通过指令参数搜索
                          // 指令参数表示搜索的字符串索引处单个单词
                          // 指令参数缺省为0
                          .UseSuggestDirective()
                          .Build();

            // Console.WriteLine("created");
            return(builder.InvokeAsync(args).Result);
        }