Code Monkey home page Code Monkey logo

commanddotnet's Introduction

Nuget NuGet Pre Release NuGet GitHub

GitHub last commit Netlify Build

Gitter Discord

CommandDotNet

A modern framework for building modern CLI apps

Out of the box support for commands, sub-commands, validations, dependency injection, piping and streaming, enums & custom types, typo suggestions, prompting, passwords, response files and much more! See the features page.

Favors POSIX conventions

Includes test tools used by the framework to test all features of the framework.

Modify and extend the functionality of the framework through configuration and middleware.

Project Status

This project is stable. Lack of new features are a result of the maturity of the library, not an indication of the liveliness of this project. We are available to fix bugs and answer questions and remain fairly responsive. There are PRs and issues in the backlog for new features that are currently low priority for the maintainers. We will accept PRs. If you haven't discussed them with us first and the change is significant, please consider the submission the beginning of a design discussion.

Support

For bugs, create an issue

For questions and feature requests, start a discussion

For a quick walkthrough of features, see our Getting Started guides

Here's a starter:

Example

Begin by creating the commands:

public class Program
{
    // this is the entry point of your application
    static int Main(string[] args)
    {
        // AppRunner<T> where T is the class defining your commands
        // You can use Program or create commands in another class
        return new AppRunner<Program>().Run(args);
    }

    // Add command with two positional arguments
    public void Add(int x, int y) => Console.WriteLine(x + y);

    // Subtract command with two positional arguments
    public void Subtract(int x, int y) => Console.WriteLine(x - y);
}

snippet source | anchor

That's it. You now have an application with two commands. Let's see about how we can call it from command line.

Assuming our application's name is calculator.dll, let's run this app from command line using dotnet. First we'll check out the auto-generated help.

$ dotnet calculator.dll --help
Usage: dotnet calculator.dll [command]

Commands:

  Add
  Subtract

Use "dotnet calculator.dll [command] --help" for more information about a command.

snippet source | anchor

From the root we can see the available commands. Instead of --help we could have used -h or -?. We'll use -h to get help for the Add command.

$ dotnet calculator.dll Add -h
Usage: dotnet calculator.dll Add <x> <y>

Arguments:

  x  <NUMBER>

  y  <NUMBER>

snippet source | anchor

Let's try it out by adding two numbers

$ dotnet calculator.dll Add 40 20
60

snippet source | anchor

CommandDotNet will validate if the arguments can be converted to the correct type.

$ dotnet calculator.dll Add a 20
'a' is not a valid Number

snippet source | anchor

Check out the docs for more examples

See our Getting Started guides to see how to improve the help documentation, test the application and utilize the many other features of CommandDotNet.

Credits ๐ŸŽ‰

Special thanks to Drew Burlingame for continuous support and contributions

commanddotnet's People

Contributors

bilal-fazlani avatar drewburlingame avatar mathiasi avatar nicolasdorier avatar raydixon avatar taori avatar tombohub 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

commanddotnet's Issues

Providing common behavior to wrap execution of a command

Hi @bilal-fazlani ,

We are adding a framework around your framework to encapsulate common use cases for our infrastructure. We'd like a hook that let's us perform some logic before the command method executes.

We were thinking a delegate on CommandRunner with a signature something like....

object OnRun(RunContext)

public class RunContext { Action RunDelegate {get; set;} AppSettings AppSettings {get; set;} CommandInfo CommandInfo {get; set;} List<ArgumentInfo> ParameterValues {get; set;}

This allows us to wrap the execution of the command in our own logic and also gives us enough metadata about the execution to understand the command.

If you approve of this approach, we can submit a PR for it.

Support constructor

Constructor should get executed when application is called without any parameters

Support for validations

Add support for

  • type validations
  • required valiations
  • error messages on validation failures
  • appropriate return codes

Type 'Decimal' is not supported'

Just leave this issue here. It was unexpectedly for me that library doesn't support decimal(as type of property in the model). So I hope someone who faced the similar issue can find this issue

Model support - composing objects to reuse common arguments

In cases where you want ubiquitous arguments (--dryrun, --verbose, --fail-fast, --customer) it would be great to define those only once so we don't have to redefine them for each command. I didn't see a way to do this.

If there isn't a way to do it, I was thinking that with the Model support you've added, if a property of the IArgumentModel class was also of type IArgumentModel, then the framework could create an instance and map those arguments as well.

What do you think?

PreExecute methods

Hi, I want to say thank you for your library. It deserves many more stars and is just awesome. Almost as good as cobra (go-package)

What I am missing are prehooks and posthooks. My use case:

I have a CLI that connects to a service and all sub commands need to establish a communication with a GRPC service. Would be easier with prehooks: https://github.com/spf13/cobra#prerun-and-postrun-hooks

Issues with 1.1.28 & 2.0.0

Issue 1
dotnet run is showing class name

image

Issue 2
dotnet run stxxxx showing command garbage and showing current command name at the top

image

Autocomplete feature

Let's try n use this library to provide autocomplete for commands & subcommands first. Then if possible, we can incorporate autocomplete for option names too.

Change usage for root app

Hi,

We are running .Net core, and global tools, so we would like to have the option to specify the "Usage:" help text.
Today it's hard coded in AppCreator.cs as: $"dotnet {Assembly.GetEntryAssembly().GetName().Name}.dll";
Would appreciate an option to override this, as the usage is not correct in regards to using global tools.

Best regards

Issues with 1.1.14

Hi there,

Thanks for getting 1.1.14 up, I've done a bit of testing with it and noticed the following issues:

Issue 1 - Commands not lower cased when using [ApplicationMetadata(Name =]
I noticed a minor issue with casing

I have defined my application such as:

AppRunner<FooApplication> appRunner = 
new AppRunner<FooApplication>(new CommandDotNet.Models.AppSettings { Case = Case.LowerCase})
.UseMicrosoftDependencyInjection(serviceProvider);

I have defined my command as follows:
[ApplicationMetadata(Name = "Info",

The command still shows up as Info instead of info

Issue 2 - Version number being printed"
I noticed the version number is being printed when run my application dotnet run. Perhaps it was left for debugging purposes?
image

Issue 3 - Help commands not showing correctly

    [ApplicationMetadata(Name = "Foo", Description = "Foo Service")]
    public class FooCommand
    {
        [ApplicationMetadata(Name = "Hello", Description = "Hello Service")]
        public async Task<bool> Download([Option]string provider = "abc")
        {

image

Dependency Injection example?

Hi there,

Great library, I was wondering how you could use dependency injection when calling

AppRunner<Calculator> appRunner = new AppRunner<Calculator>();?

I would like to inject a class in my Calculator class how would I go about doing that?

    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);
            ///------------------------------------------------

            AppRunner<Calculator> appRunner = new AppRunner<Calculator>();
            return appRunner.Run(args);
        }
    }

Example of what I'm trying to implement:
https://github.com/NLog/NLog.Extensions.Logging/wiki/Getting-started-with-.NET-Core-2---Console-application

Alias & text matching for commands

  • Support alias for commands
  • Support for string matching for commands

text matching similar to:

    git: 'puhs' is not a git command. See 'git --help'
    
    Did you mean this?
          push

Blocking creating a commanddotnet.ioc.simpleinjector

The ms & autofac ioc extensions reference the internal field AppRunner.DependencyResolver which in turn requires an "[assembly: InternalsVisibleTo("CommandDotNet.IoC.MicrosoftDependencyInjection")]" line. This prevents us from implementation a new ioc tech w/o first getting a PR merged into your master. If enough people adopt this, that class will be littered. Can DependencyResolver be converted to a property with an external setter and a private or internal getter?

Call commands from other commands

Great effort with this library, I like the new features you have been implementing

I was wondering how you would go about handling or structuring the following requirement

Say I have 3 commands
Command1, Command2 and All

For my All Command I would like to call Command1 and Command2
Currently I'm able to do this by doing the following:

[DefaultMethod]
public void AllCommand() {
   var command1 = new Command1();
   command1.DoSomethng();
}

While this works, the issue is if Command1 has dependencies IFooService this wouldn't be injected because I'm newing up commmands.

I'm just wondering how you would about structuring such a requirement?

Thanks for your time and effort

Feature request: Place parameters in the middle.

Hi,
I am not sure if it makes sense, but very often I have commands like

cli gateway get-configuration 1A827Ah66
cli gateway add-x 1A827Ah66

The 1A827Ah66 is an id or longer name and when I have to use multiple commands it is annoying to reenter it all the time. Therefore it would be more convenient to have the following syntax:

cli gateway 1A827Ah66 get-configuration 
cli gateway 1A827Ah66 add-x 

So that I only have to replace the last part. Is it somehow possible?

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.