Code Monkey home page Code Monkey logo

commandlineutils's Introduction

CommandLineUtils

Build Status Code Coverage NuGet NuGet Downloads

This project helps you create command line applications using .NET. It simplifies parsing arguments provided on the command line, validating user inputs, and generating help text.

The roadmap for this project is pinned to the top of the issue list.

Usage

See documentation for API reference, samples, and tutorials. See also docs/samples/ for more examples, such as:

Installing the library

This project is available as a NuGet package.

$ dotnet add package McMaster.Extensions.CommandLineUtils

Code

CommandLineApplication is the main entry point for most console apps parsing. There are two primary ways to use this API, using the builder pattern and attributes.

Attribute API

using System;
using McMaster.Extensions.CommandLineUtils;

public class Program
{
    public static int Main(string[] args)
        => CommandLineApplication.Execute<Program>(args);

    [Option(Description = "The subject")]
    public string Subject { get; } = "world";

    [Option(ShortName = "n")]
    public int Count { get; } = 1;

    private void OnExecute()
    {
        for (var i = 0; i < Count; i++)
        {
            Console.WriteLine($"Hello {Subject}!");
        }
    }
}

Builder API

using System;
using McMaster.Extensions.CommandLineUtils;

var app = new CommandLineApplication();

app.HelpOption();

var subject = app.Option("-s|--subject <SUBJECT>", "The subject", CommandOptionType.SingleValue);
subject.DefaultValue = "world";

var repeat = app.Option<int>("-n|--count <N>", "Repeat", CommandOptionType.SingleValue);
repeat.DefaultValue = 1;

app.OnExecute(() =>
{
    for (var i = 0; i < repeat.ParsedValue; i++)
    {
        Console.WriteLine($"Hello {subject.Value()}!");
    }
});

return app.Execute(args);

Utilities

The library also includes other utilities for interaction with the console. These include:

  • ArgumentEscaper - use to escape arguments when starting a new command line process.
     var args = new [] { "Arg1", "arg with space", "args ' with \" quotes" };
     Process.Start("echo", ArgumentEscaper.EscapeAndConcatenate(args));
  • Prompt - for getting feedback from users with a default answer. A few examples:
    // allows y/n responses, will return false by default in this case.
    // You may optionally change the prompt foreground and background color for
    // the message.
    Prompt.GetYesNo("Do you want to proceed?", false);
    
    // masks input as '*'
    Prompt.GetPassword("Password: ");
  • DotNetExe - finds the path to the dotnet.exe file used to start a .NET Core process
    Process.Start(DotNetExe.FullPathOrDefault(), "run");

And more! See the documentation for more API, such as IConsole, IReporter, and others.

Getting help

If you need help with this project, please ...

Project origin and status

This is a fork of Microsoft.Extensions.CommandLineUtils, which was completely abandoned by Microsoft. This project forked in 2017 and continued to make improvements. From 2017 to 2021, over 30 contributors added new features and fixed bugs. As of 2022, the project has entered maintenance mode, so no major changes are planned. See this issue for details on latest project status. This project is not abandoned -- I believe this library provides a stable API and rich feature set good enough for most developers to create command line apps in .NET -- but only the most critical of bugs will be fixed (such as security issues).

commandlineutils's People

Contributors

ajaybhargavb avatar analogrelay avatar atruskie avatar benaadams avatar brennanconroy avatar bricelam avatar davidfowl avatar dependabot[bot] avatar dougbu avatar eilon avatar haok avatar javiercn avatar jbagga avatar jerriep avatar juntaoluo avatar kichalla avatar madbhatter avatar mikeharder avatar natemcmaster avatar ntaylormullen avatar pakrym avatar pranavkm avatar rmcc13 avatar ryanbrandenburg avatar rynowak avatar scott-xu avatar theconstructor avatar tratcher avatar troydai avatar vpkopylov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

commandlineutils's Issues

NullReferenceException when calling HelloWorld.Attributes sample with -h or -? instead of --help

Description

When running dotnet .\bin\Debug\netcoreapp2.0\HelloWorld.Attributes.dll --help I get the expected output:

Usage:  [options]

Options:
  -?|-h|--help            Show help information
  -s|--subject <SUBJECT>  The subject

But when running dotnet .\bin\Debug\netcoreapp2.0\HelloWorld.Attributes.dll -h I get an error:

Usage:  [options]

Options:
  -?|-h|--help            Show help information
  -s|--subject <SUBJECT>  The subject


Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Bind[TApp](IConsole console, String[] args) in X:\Path\To\CommandLineUtils\src\CommandLineUtils\CommandLineApplication.Execute.cs:line 150
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute[TApp](IConsole console, String[] args) in X:\Path\To\CommandLineUtils\src\CommandLineUtils\CommandLineApplication.Execute.cs:line 48
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute[TApp](String[] args) in X:\Path\To\CommandLineUtils\src\CommandLineUtils\CommandLineApplication.Execute.cs:line 31
   at Program.Main(String[] args) in X:\Path\To\CommandLineUtils\samples\HelloWorld.Attributes\Program.cs:line 11

Info

  • Latest commit on master as of 2017-12-03T00:13:42Z, 1a843bd4db8d536e54f9d7ae9b58ebf53f16b521, which is newer than the latest tag v2.1.0-beta
  • Windows 10 Pro Fall Creators Update
  • dotnet --version: 2.0.0
  • Executed in PowerShell in the Visual Studio Code integrated terminal

Show Help for subcommand

Hi there

In your sample: CommandLineUtils/samples/Subcommands/Inheritance.cs

How would you go about showing app.ShowHelp() so that if you typed
dotnet run add it will show the help for the Files command

I tried the following:

protected override int OnExecute(CommandLineApplication app)
        {
            if (Files.Length == 0)
            {
                // this shows help even if the --help option isn't specified
                app.ShowHelp();
                return 1;
            }

            return 0;
        }

This seemed to work, but when I actually passed arguments it still kept showing the help
`dotnet run add files test1,test2' still showed help?

Difficult to omit short names using attributes

Hi, I'm using this library for a pretty large CLI application. One command, in particular, has many options with similar names, for example:

            [Option(Description = "...")]
            public string AnalysisIdentifier { get; set; }

            [Option(Description = "...")]
            public TimeAlignment AlignToMinute { get; set; } = TimeAlignment.None;

            [Option(Description = "...")]
            public bool WhenExitCopyLog { get; set; }

            [Option(Description = "...")]
            public bool WhenExitCopyConfig { get; set; }

The automatic short name generator complains if two short names are the same (fair enough) but what I'd like to do is disable short names for lesser-used options. I've tried:

I realise I could use the template string form and omit the short name part, but I've got a couple hundred options over a dozen subcommands and I don't want to maintain a separate string for all of those options (the auto kebab casing for full names is a great help!).

What do you think?

I've got three ideas:

  • Consider using "" to represent a not having short name
  • Adding a bool NoShortName property to OptionAttribute (eww)
  • Or, I could implement my own LongOptionAttribute class which will not set ShortName because it won't have the Configure method from OptionAttribute
    • It seems the extensibility options of OptionAttributeBase are limited however

Documentation

Hi Nate,

I just started using this library and there are so many good things in here (for example the dependency injection and conventions). But sadly it is not very easy to get to grips with all of the concepts, or even know of their existence unless you work through the sample apps and answers for previous Issues. Also, the API reference in the docs is good for reference, but not very helpful to explain the concepts.

I'd love to help you sort out the docs, but I don't just want to jump in without checking with you first.

I blog regularly and worked for Auth0 on their docs, so I am comfortable with writing and doing this for you. I am also familiar with using DocFx, as I have used it for some of the Auth0 libraries I wrote.

So before I just start hammering away, do you have any ideas in your mind with regards to the outline for the docs of the various parts needing to be addressed?

Sub-command async OnExecute

Hello,

is it a bug, that program is taken the control before async sub-command OnExecute is done?

a demo example:

static int Main(string[] args)
        {
            var app = new CommandLineApplication();
        app.HelpOption("-h|--help");
        var optionSubject = app.Option("-s|--subject <SUBJECT>", "The subject", CommandOptionType.SingleValue);

        app.Command("subCmd", cmd =>
        {
            cmd.FullName = "Sub-command";
            cmd.Description = "Demo sub-command";
            cmd.ExtendedHelpText = "An extended help text...";
            cmd.HelpOption();
            var subCmdArg = cmd.Argument("SubArg", "The argument");

            cmd.OnExecute(async () =>
            {
                Console.WriteLine("sub-command starting ...");
                await Task.Delay(4000);
                Console.WriteLine("... sub-command: done - arg: " + subCmdArg.Value);
            });
        });

        app.OnExecute(async () =>
        {
            var subject = optionSubject.HasValue()
                ? optionSubject.Value()
                : "world";

            Console.Write($"Hello");

            // This pause here is just for indication that some awaitable operation could happens here.
            await Task.Delay(5000);
            Console.WriteLine($" {subject}!");
            return 0;
        });

        var result = app.Execute(args);
       Console.WriteLine("Press any key to end...");
        Console.ReadKey();
       return result;
     }

Convention based api

i have added an extension method to CommandLineApplication to support convention based command handling. see here https://github.com/shovonnn/artisancommandline

i tried to create a pull request for this repo. but it wont compile. few too many error. maybe cause of netcore1.x
i am on a tight schedule at the moment. so can't work much.

Unable to start Subcommands example

When Subcommands project is being started it prompts to choose for one of 3 options.
When the option 3 is chosen - the app just exits without allowing to interact with fake-npm command.

Unable to search the natemcmaster/CommandLineUtils codebase on GitHub

The Problem

Try searching for ResponseFileParser.

Sorry, forked repositories are not currently searchable.
You could try searching the parent repository.

Details

https://github.com/blog/1381-a-whole-new-code-search
"Repository forks will not be searchable unless the fork has more stars than the parent repository."

Suggested Solutions

Get More Stars

We can advertise and be awesome, then maybe we can get more stars than aspnet/Common. But then we have to continue to get more stars as the more and more people find and star aspnet/Common. Seems like it could be a battle as aspnet/Common has a free advertising mechanism, being connected to Microsoft.

Contact GitHub Support to Unlink the Projects

StackOverflow knows all things.
https://stackoverflow.com/a/16052845/5167537
"You can contact github support and ask them to switch your repository to "normal mode".

On this page, "Commit was made in a fork" paragraph, it is explained that one has to go through support to switch. Therefore, it is likely that there is no way to do that by yourself (unless you destroy and recreate your repo which is explained before... if you do so be careful if you have tickets or a wiki attached to your project as they will be deleted!)." -- Thomas Moulard

Generated help output formats (markdown, man page, html)

Keeping docs in sync with code is a pain. Let's automate this, if we can. We already have a generate which produces console output. Would be awesome if it could produce that output in a format that could be piped to a file.

tool --help:man > tool.1.man
tool --help:html > tool-help.html

Allow supply a custom help generator to Execute<T> methods

Presently I believe it is not possible to provide an IHelpGenerator to the CommandLineApplication.ExecuteAsync<MainArgs>() method.

It would be good to add support for this: As a use case, I'd like to inject extra metadata (outside the scope of this tool) into help messages

A simple solution is to add another overload to ExecuteAsync.

A more interesting idea might be to allow for creating a CommandLineApplication instance, which can then be modified, and to add an instance method version of Execute<T> and ExecuteAsync<T> which builds off the existing CommandLineApplication instance. This approach might prove more general (fewer ways to configure the same thing, allows access to other functionality like ValidationErrorHandler) and allow for other interesting things (like mixed builder and reflection generation).

I'm happy to make a contribution but would appreciate guidance on public APIs.

Allow to override short option

Awesome work!

I have Delay1 and Delay2 options, which obviously clash in "-d"
Would be great if I could specify just the short override to "-d1" and "-d2"!

Dependency Injection example?

Hi there I was wondering if you have a dependency injection example?

Usually I would use something like below but I'm not sure how I would call your code?

 class Program
    {
        static int Main(string[] args)
        {          
            //  setup our DI
            var services = new ServiceCollection();            
            services.AddTransient<IHelloService, HelloService>();      
            var serviceProvider = services.BuildServiceProvider();
           
            // ---------------------------------------------------
           // Not sure how to use this ??? 
            var app = serviceProvider.GetService<Calculator>();
            //app.Run(args);
            ///------------------------------------------------

      
        }
    }

Support for custom value parsers

In the vein of automating as much as possible, it would be nice to be able to supply our own value parsers to the library. This is useful when an application has its own data structures because it removes boilerplate from argument parsing.

For example, we are parsing DateTimeOffsets, TimeSpans, Color structs, and some other domain-specific types.

If you think this would be a valuable contribution I'd be happy to implement it, but I'd appreciate a suggestion on how I should extend the public API. A trivial (but perhaps naive) way to do it would be to add an AddParser method ValueParserProvider.

Attribute binding

Minimal spec

public class Program
{
    [Argument(0)]
    public string Command { get; set; }

    [Option]
    public string Message { get; set; }

    [Option("-F <file>")]
    public string File { get; set; }

    [Option]
    public bool Amend { get; set; }

    [Option("--no-edit")]
    public bool NoEdit { get; set; }

    public static void Main(string[] args)
     => CommandLineApplication.Execute<Program>(args);
    
    private void OnExecute()
    {}
}

Designate Required vs Optional Parameters/Options

Currently, it is up to the application developer using CommandLineUtils to validate command line input and display an appropriate error if an Option that is required is left out. I propose that CommandLineUtils take on this responsibility, allowing the library user to designate parameters as required and provide appropriate feedback to the user when the parameter is not provided.

This may be a nice feature to do after #8 so the user of the library need only add an attribute of [Required] to make this designation.

Add example for "app subject command -arg" CLI

I would like to build a CLI where commands are related to subjects, like the Docker CLI:

  • docker container ls -a
  • docker image ls -a
  • docker container run --name some-redis -d redis

Where docker is the application, container / image etc. the subject and ls / run etc. the command, with commands belonging to the subject and with arguments only applying to the specific command.

The subcommand example only used app command -arg, so the level of "subjects" is missing. But it seems to be possible with building a hierarchy with the Parent attribute, at least from how I understand the subcommand tests.

It would be nice to have some kind of documentation about how to "nest" subcommands to create a Docker-like CLI.

And a question: In a Docker-like CLI it shouldn't be possible to use multiple subjects in one line, e.g. docker container ls -a image ls -a. But for example this line in the tests looks like that's currently possible when using subcommands in CommandLineUtils. Is there a way to restrict that?

Parsing should not use current culture by default

Currently, value parsers use the current culture for parsing (that is: no culture is specified). This means that on systems not running on an en-US locale, problems will occur because scripts & response files are non-portable (my 1.234 is your 1,234 and vice versa, and the same with dates).

If all parsing code were to use the Invariant culture by default, these problems would disappear.

CommandParsingException: Missing value for option 'opt'

Exception throws when user leaves option values blank.

Unhandled Exception: McMaster.Extensions.CommandLineUtils.CommandParsingException: Missing value for option 'opt'
   at McMaster.Extensions.CommandLineUtils.CommandLineProcessor.ProcessOption()
   at McMaster.Extensions.CommandLineUtils.CommandLineProcessor.ProcessNext()
   at McMaster.Extensions.CommandLineUtils.CommandLineProcessor.Process()
   at McMaster.Extensions.CommandLineUtils.ReflectionAppBuilder`1.Bind(IConsole console, String[] args)
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute[TApp](IConsole console, String[] args)
   at Program.Main(String[] args)

Is there any possibility to control this exception with a more global like solution? It is currently a blocker for my requirements, because it cannot be controlled. The property 'ThrowOnUnexpectedArgument' does not affect the behavior. A similar way would be awesome. Maybe the property can be considered in the function.

Within CommandLineProcessor.cs the exception simply throws. In my opinion, there must be a more sensitive solution. I tried to implement an validation attribute with the latest release to check whether the value is set or not. It does not work. The exception has been thrown before. Maybe it would be better to output (custom) error message without having the problem, that the application crashed before.

I've seen there are new values for CommandOptionTypes. Is the desired solution to set the value 'SingleOrNoValue' to prevent the exception?

Thanks for the clarification.

Add more API for parameter validation

In #20, I added initial work to support validating parameters before OnExecute is called. I added the .IsRequired() extension method for CommandOption and CommandArgument. I also added support for using ValidationAttribute in the attribute binding API.

I'd like to expand the API to include commonly used validations. This might include

  • Validate the value is in a set of options
  • Validate that set by using an enum type
  • File paths (invalid chars, assert file exists)
  • A builder API to match the built-in .NET ValidationAttributes
    • EmailAddressAttribute
    • RangeAttribute
    • Regex
    • etc.

[Feature Request] Option.IsSpecified

Flags are one of the most common kinds of options in CLIs, but as is, there is no way to tell if an Optional is called without values or not called at all.

History and purpose: how this is project came to be, and what it's for

git mv {Microsoft => McMaster}.Extensions.CommandLineUtils

History

The ASP.NET Core team is in the business of producing a web framework, and not in producing .NET libraries in general. In the early days of what later became ASP.NET Core, Microsoft.Extensions.CommandLineUtils was created as a requirement of producing dnx and ASP.NET vNext. It was never intended to be the Microsoft-official way to write command line apps. After later refactoring of the architecture of dnx into dotnet, and reassignments of resources, the ASP.NET Core team no longer maintains much command-line code, so they decided to stop active development on their CommandLineUtils library. See dotnet/extensions#257.

What this is

Hence, I've forked the project. This project will maintain and improve upon the 1.0 and 1.1 versions of the library.

Fork is the operative word here. Not branch, not update, not replace.

Goals

  • Patches, minor bug fixes to API originally in Microsoft.Extensions.CommandLineUtils (thank you Apache 2.0 license)
  • Improvements. Include more non-breaking changes and new API that make it easier to write command line applications.
  • Maintenance. Keeping up with the continual shift in .NET. PCL => dnxcore50 => dotnet5.1 => netstandard. There has been lots of churn, and I expect there will continue to be. I'll attempt to keep pace.

Non-goal

  • This is unofficial. Don't expect Microsoft-official support.
  • Replacing Microsoft.Extensions.CommandLineUtils. Someone at Microsoft may attempt to restart active dev work on this. If so, bravo. There will be welcome to merge this code, which will also use the Apache license.
  • Competing for an official System.* namespace. Although the .NET team has been drafting System.CommandLine for a long time, it is not yet generally available and has no set roadmap.

Future

This repo is open to community contributions under the Apache 2.0 License. Please read the contributing guidelines, and tag me @natemcmaster in the pull-request.

Cheers,
Nate. 🍻

Add support for TypeConverter

Followup to #59

We should

  1. Add a TypeConverterParserAdapter. Implements IValueParser and takes an instance of TypeConverter.
  2. Update ValueParserProvider to fallback to TypeConverterAttribute when present and return a TypeConverterParserAdapter.

As a bonus, we could either

  • Update OptionAttributeConvention/ArgumentConvention to honor TypeConverterAttribute
  • or, update those conventions to make it possible to override how the IValueParser is provided.

OnExecute Extension method breaks async actions

The OnExecute extension method provides a way to pass an Action delegate rather than a Func<int> delegate, but it also breaks if the delegate is an async method.

        /// <summary>
        /// Sets <see cref="CommandLineApplication.Invoke"/> with a return code of <c>0</c>.
        /// </summary>
        /// <param name="app"></param>
        /// <param name="action"></param>
        public static void OnExecute(this CommandLineApplication app, Action action)
            => app.OnExecute(() =>
                {
                    action();
                    return 0;
                });

This breaks (because the method is not awaited):

app.OnExecute(async () => {
    ...
    if(someReason)
        throw new SomeException();
});

But this works:

app.OnExecute(async () => {
    ...
    if(someReason)
        throw new SomeException();
    return 0;
});

File path argument with leading/trailing quotes throwing Exception

First off, thank you for forking this and continuing to work on it!

Many CLI apps let you pass in a file path argument as such --filepath="C:\Users\foo\file" (Windows) and --filepath="/home/foo/file" (Linux). When trying to do this with a C# Console app, the quotes are escaped as "\"C:\\Users\\foo\\file\"" and "\"/home/foo/file\"". This causes an exception to be thrown when using LegalFilePathAttribute because new FileInfo(path) throws a System.NotSupportedException with message "The given path's format is not supported.". I understand that this is not a bug from this library. I'd like to open a conversation about supporting this type of argument behavior.

How to Create A Standalone Command/Application

I know this isn't really the forum for this, but currently I am using this project my small CLI util. But so far I can only find resources online, that indicate that when I want to run a dontet console app, I need to invoke it as such:

dotnet my-data-loader.dll --foo bar or during debug/dev dotnet run -- --foo bar

Are there any docs / resources online that use this project (either in its current or prior states), that explain how to go from the examples above to something like:

my-data-loader --foo .

Thanks in advance :)

Rename pkg just "CommandLineUtils"?

Because shorter is better.

I chose "McMaster.Extensions.CommandLineUtils" because it was very similar to the original "Microsoft.Extensions.CommandLineUtils". I don't really love that my name is in the title though. Plus long package names are annoying to type out all the way.

cc @ScotiaBaker

question(s): creating sub-commands on runtime; command.Invoke() row in the code

Hi,

  1. I have already defined couple of classes similar in Subcommands sample. (I use the inheritance).

Now, I wonder, whether it is possible to add a code in one of that already defined Sub-commands class, which will create inner sub-comands programmatically. (I face to a list of sub-comands definition, which comes from an external service, which could continuously grow, I would like to map that metadata to generate the CommandLineUtils sub-command structure on the fly).
From other point of view - is it possible to combine the attribute SubCommand with a code for defining of sub-commands?

  1. it might relate to 1) I am not so sure though, - I little investigated the source code, I wonder about the place command.Invoke(); in Bind(IConsole console, string[] args) method of the ReflectionAppBuilder class. What is the purpose of calling it? It sounds to me the command has already been processed at that time, while it is going to be is invoked further in the case of being matched as the target command.
    Could you, please, give me a little code snippet example, how to inject a code from such a command class to be invoked at that "command.Invoke()" time?

TIA,
Mojmir

Support lower versions of netstandard

Currently CLU targets either full .NET Framework 4.5 or the new .NET Standard 2.0.

The advice from Microsoft for library authors is to target the lowest version of .NET Standard that you can get away with.

To support CLU on more .NET platforms out of the box, it would be better to see if lower versions of .NET Standard can be targeted.

Optional argument for the option

Is it possible to implement the following logic:
--option mandatory_value [optional_value1] [optional_value2]
without making to specify --option flag multiple times?

Help option prints incorrect ShortName

With the latest NuGet release, an option is available to set the short name of an option, but the help message outputs what seems like an autogenerated (incorrect) one.

[Option(CommandOptionType.SingleValue, Description = "...", ValueName = "...", ShortName = "c")]
public string ConfigPath { get; set; }

[Option(CommandOptionType.SingleValue, Description = "...", ValueName = "...", ShortName = "s")]
public string CSharpPath { get; set; }

The following is the output line from help:

-c|--config-path ¥<CONFIG_PATH> ...
-c|--csharp-path ¥<CSHARP_PATH> ...

The options parses correctly when passed but the help text is misleading.

Don't validate when showing information

I'm trying to create a command line application with a single required argument ("version"):

var versionArgument = app.Argument("version", "The version to set the project as.").IsRequired();

As expected, I get an error message when trying to run my program without specifying this argument:

$ dotnet bin/Release/netcoreapp2.0/dotnet-setversion.dll
The version field is required.
Specify --help for a list of available options and commands.

However, I don't expect to get this error when displaying information (help or version), but that's what currently happens:

$ dotnet bin/Release/netcoreapp2.0/dotnet-setversion.dll --help
Usage: dotnet-setversion [arguments] [options]

Arguments:
  version  The version to set the project as.

Options:
  -h|--help  Show help information
  -f|--file  Identifies the csproj file to update. Looks in the current working directory if not set.
The version field is required.
Specify --help for a list of available options and commands.

Design: builder API for parsing args into .NET types

Problem
Users who prefer the builder API can't take advantage of the automatic type parsing available in the attribute api for int, List<T>, etc. Part of the difficulty is that CommandLineApplication, CommandArgument, and CommandOption only provide string-based properties.

Proposal
Add CommandOption<T> and CommandArgument<T>.

There is acts as an implicit requirement that values can be parsed to typeof(T).

For custom types, users can provide a custom converter to parse string into typeof(T). CLU will provide parsers for most commonly used types like int, double, bool, etc.

Usage

public static int Main(string[] args)
{
    var app = new CommandLineApplication();

    CommandArgument<int> arg = app.Argument<int>("arg", "argument");
    CommandOption<int> option = app.Option<int>("--arg", CommandOptionType.SingleValue)
        .Accepts().Range(0, 100);

    CommandOption<IPAddress> option2 = app.Option<IPAddress>("--addres", CommandOptionType.SingleValue)
        .UseConverter(val => IPAddress.Parse(val));

    app.OnExecute(() =>
    {
        int[] values = option.Values;
    });

    return app.Execute(args);
}

How to not throw when using the attribute API

I've looked into the code and there doesn't seem to be a way to prevent throwing when you use the attribute API. I know you can set the property on CommandLineApplication instances, but CommandLineApplication.Execute<Program>(args) doesn't give you such object?

The alternative would be to add the argument on the Execute static methods and pass it on the ReflectionAppBuilder?

Support inheritance for help option

Neither of the HelpOption methods in the builder API provide the ability to specify that the option should be inherited. It is common to use the same help option for subcommands, so it would be nice to specify the option once on the root CommandLineApplication instance and not have to do it for every subcommand.

I also think since this is such a common practice for CLI tools (see git or dotnet), the help option should be inherited by default, but this could be considered a breaking change.

In the event that this feature is rejected, I would like to point out that the generated help from calling the .ShowHelp method suggests the help option for subcommands even if there is no help option specified on them.

Tab completion

Make it possible to write an app that supports tab completion in bash, powershell, and others.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.