Skip to content

Parse command-line arguments directly into your POCOs with a simple, yet complete and elegant fluent API. Supports nested verbs, specifying arguments by index, long or short name and is quite configurable and extensible.

License

Notifications You must be signed in to change notification settings

ModernRonin/FluentArgumentParser

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

85 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FluentArgumentParser

CI Status NuGet NuGet PRs Welcome

Summary

There are several packages out there for parsing of command-line arguments, but not one of them fulfills everything I think such a library should cover.

What are these requirements?

  • populates POCOs
  • is not dependent on attributes (personally I find attributes, especially those with parameters, create a lot of noise when reading code)
  • deals with verbs, like git, and nested verbs, too
  • allows passing arguments by index, by long name and by short name
  • produces good-looking and useful help
  • possible to work with just the POCOs without any further configuration - for small in-house tools one often doesn't want to spend a lot of time with setting up these options
  • good defaults, but at the same time configurable and extensible

Quick Start - zero configuration

Let's look at the simplest scenario. For more advanced examples, take a look here.

You want to model a single action and don't care too much about the names of the options or help-text, you just want to get over this argument parsing as quickly as possible.

// this is the info you want to get from the commandline arguments - you just define it as a regular POCO
public class Rectangle
{
    public int X { get; set; }
    public int Y { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
    public Filling Filling { get; set; } = Filling.Solid;
}

// and in your Main you do:
static int Main(string[] args)
{
    var parser = ParserFactory.Create("sometool", "somedescription");
    parser.DefaultVerb<Rectangle>();
    switch (parser.Parse(args))
    {
        case HelpResult help:
            Console.WriteLine(help.Text);
            return help.IsResultOfInvalidInput ? -1 : 0;
        case Rectangle rectangle:
            // do whatever you need to do
    }
}

Now what are valid inputs for this setup? Here are a few examples, together with how they will fill the properties of the Rectangle instance:

Argument string Rectangle properties
10 11 12 13 X:10, Y:11, Width:12, Height:13, Filling:Filling.Solid
10 11 -h=13 -w=12 --filling=Hatched X:10, Y:11, Width:12, Height:13, Filling:Filling.Hatched
-x=10 -y=11 -h=13 -w=12 Hatched X:10, Y:11, Width:12, Height:13, Filling:Filling.Hatched

And what would be the content of the help.Text property in the code-sample above?

sometool
somedescription

Usage:
sometool --x=<value> --y=<value> --width=<value> --height=<value> [--filling=<value>]


Required arguments:
--x, -x       int
--y, -y       int
--width, -w   int
--height, -h  int

Optional arguments:
--filling, -f  None, Hatched, Solid
               default: Solid

Examples:
sometool 10 20 30 40
sometool 10 20 30 40 Solid
sometool --x=10 --y=20 --width=30 --height=40 --filling=Solid
sometool -x=10 -y=20 -w=30 -h=40 -f=Solid
sometool -h=40 -f=Solid -x=10 -y=20 -w=30

long parameter names are case-sensitive
short parameter names are not case-sensitive
command names are not case-sensitive

Things to note:

  • if you are fine with the default naming, you can just pop in your configuration objects and be done with it.
  • if you set defaults for properties (different from the standard defaults), they are automatically assumed to be optional with the default value you set. In the example above Rectangle.Filling is such a case: it's automatically understood to be an optional parameter with the default value Filling.Solid.
  • the Parse method returns an object on which you can switch, using a language facility we've had now for a while. The types you need to handle are all your own POCOs that you have defined as verbs and the special type HelpResult
  • HelpResult is automatically returned when the arguments contain an explicit call for help, like sometool help or sometool ? or, if you have multiple verbs, sometool help myverb

More Info

Contributing

If you want to contribute, you are more than welcome. Fork the repository, make your desired changes, and create a pull request into the source repository default branch (you can read more about the fork and pull model here)

.NET version

The solution requires .NET 6.x SDK installed on your machine.

Paket

This solution uses Paket, a dependency manager for .NET projects. To get started with the solution, run:

dotnet tool restore
dotnet paket restore

This will restore all necessary packages in order to run the solution.

Labels

Check out the issues page. There are a few issues marked as good-first-issue and a few others as help-wanted.

Furthermore, issues marked as needs-design would benefit from discussion about how they should ideally work, both for end-users and for library-users.

Last not least, there are a few ideas marked as do-people-need-this- for these, it would be very interesting to get as many opinions as possible.

License

The license is Creative Commons BY-SA 4.0. In essence this means you are free to use and distribute and change this tool however you see fit, as long as you provide a link to the license and share any customizations/changes you might perform under the same license.

About

Parse command-line arguments directly into your POCOs with a simple, yet complete and elegant fluent API. Supports nested verbs, specifying arguments by index, long or short name and is quite configurable and extensible.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published