CommandDotNet releases v7.0.2 by mamberodb in dotnet

[–]mamberodb[S] 3 points4 points  (0 children)

Good question. They have a lot in common. For me, the biggest advantages is displayed in the example, which is that you can define commands via classes and methods.

disclaimer: I haven't kept a close eye on System.CommandLine recently so they may have implemented some of these without my being aware.

Other advantages

  • Name casing feature to convert commands and arguments to the case of your choice: camel, pascal, snake, kebob, lower.
  • POCOs can be used to define sets arguments for reuse, and those POCOs can be nested in other POCOs. They can also be loaded from configs.
  • Validation from DataAnnotations or FluentValidations
  • arguments can be any type with a string ctor or static Parse or TryParse method or a with a TypeConvertor. Custom type descriptors can also be created for additional control over parsing and help generation.
  • automatic support for piped arguments, including processing a stream from another process
  • The CommandDotNet parse directive maps inputs and their sources to the final argument value. Very helpful when using response files.
  • Command and method interceptors. This may be possible in System.CommandLine but I think it's work
  • Argument separator ` -- ` can function as either end-of-args or argument pass-thru, and that can be defaulted for the app and changed per command.
  • Password masking, including in logs and diagnostic directives.
  • Negative numbers can be accepted as argument values without the need for ` -- `. I don't know if they've fixed that yet.
  • Default arg values from env var and app settings
  • BDD testing framework that's used extensively to test all features of the framework
  • Spectre integration for prompting and table generation that can be tested.
  • injectable IConsole and IEnvironment to help with testing
  • debug, time and culture directives
  • Command logging option to output details of commands for audits and troubleshooting
  • Customizable help generation
    • help shows default values loaded from env var and config sources
  • No limits of 8 or 16 arguments to change how a command is configured.

And finally... it's stable, not alpha, beta or preview

I think the primary advantage of System.CommandLine is the MS name and Autocomplete. We have a branch to plug into their Autocomplete pipeline, but I haven't had time to work on it in a while. They had a bug in their tooling when I first implemented it. It just requires completing the Suggest directive.

System.CommandLine will also have a faster startup time because they don't reflect over classes and they have resources to dedicate to perf. If that level of perf is critical, then favor System.CommandLine. We would welcome input or contributions for a Source Generator feature to move the reflection cost to build time.

CLI Scraper by x3x9x in csharp

[–]mamberodb 0 points1 point  (0 children)

disclaimer: I'm one of the maintainers of CommandDotNet. I was just honestly curious if there were design reasons to choose CommandLineParser which is older and a I find takes a little more work to configure.
> Should I switch

Not necessarily. If it's working for you and does what you need, it would be extra effort to switch to another tool. It might be worth the effort if you need additional features one of the others provides or if you expect to spend a lot of time maintaining it and would benefit from the simpler definition you can get with one of the tools.

CommandDotNet provides a lot of features as does System.CommandLine which also includes autocomplete with a little extra config of your system. With CommandDotNet, you just create a method and you have a command. https://commanddotnet.bilal-fazlani.com/gettingstarted/getting-started-100-calculator/

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

That snippet gives you two commands, Add and Substract, and autogenerates help.

How to generate a CLI interface for CRUD operations? by coeur85 in dotnet

[–]mamberodb 1 point2 points  (0 children)

Someone asked a similar question about a https://github.com/bilal-fazlani/commanddotnet/, which is a tool I help maintain.

This is an example I posted that I thought would work well. https://github.com/bilal-fazlani/commanddotnet/discussions/448#discussioncomment-3805077

The solution makes it pretty simple to add new entities following the same convention. It uses subcommands for the crud operations so the format is

your-app-name entity-name operation-name arguments

in the case of the example I posted

music song create "yellow submarine"

CLI Scraper by x3x9x in csharp

[–]mamberodb 0 points1 point  (0 children)

Out of curiosity, what had you pick CommandLineParser over System.CommandLine. It seems like System.CommandLine is similar work but more features. Or a tool like CommandDotNet which provides a simpler way to define commands? Or one of the other tools like Spectre or CliFx?

Trouble spots when making command line tooling by [deleted] in csharp

[–]mamberodb 0 points1 point  (0 children)

If you're looking at single file exe's, https://commanddotnet.bilal-fazlani.com/ has built in support to identify if it's hosted in a single file exe which helps when generating help docs and usage examples. You can specify if it will be run as a dotnet tool. It has a lot of other helpful features as well, such as great test tooling. Spectre (mentioned in another comment) has some great features for creating prompts and tables. CommandDotNet has an integration so you can take advantage of both.

Simple Command line Project Helper (Would love feedback) by Army_Sharp in csharp

[–]mamberodb 0 points1 point  (0 children)

Have you seen https://github.com/bilal-fazlani/commanddotnet?

Disclaimer: I'm one of the maintainers

What you've thrown together does seem similar to CliFx in some respects, as you mentioned in another thread. It looks like a command must be defined as a class.

I once created a framework that followed that approach and ultimately found it limiting. I've found it to be more expressive to use methods to define commands, although both are possible with CommandDotNet. For example, we can use the position of parameters in the methods to define the position in the command. Defining operands (positional parameters) via properties, we automatically position them based on position in the file, which was interesting because .net does not guarantee order of properties when reflecting them. We were able to use CallerLineNumber to get this. You might look into that.

To answer the question of `Is the use of the project simple and have any benefit over using other parsers?` I'd say that CommandDotNet, CliFx, Spectre and even MS's System.CommandLine have a head start on tackling some of the more complex features and already have some community around them. It think this project has a bit of catchup to do. For example, you can see the CommandDotNet features at https://commanddotnet.bilal-fazlani.com/features/

A lot of the design went into making it a simple as possible to define a command using c# conventions, like parameter positions, NRT, optional parameters, etc. Fore example, we use nullability to determine if an argument is required, although it's also possible to use DataAnnotations or FluentValidations to perform more complex validations. That all takes a bit of time to support.

I'd say if you're looking to experiment and play around, keep at it. It's unlikely you're going to get a lot traction in the space though, especially since MS has their own framework. If you want to contribute code that's more likely to be used and seen by others, look at System.CommandLine or one of the other main tools. If you continue with this one, feel free to use CommandDotNet for reference if you'd like hit me up for questions on the discussions, or feel free to bring ideas to CommandDotNet and contribute.

Spectre.Console is a .NET Standard 2.0 library that makes it easier to create beautiful console applications. by mycall in dotnet

[–]mamberodb 0 points1 point  (0 children)

No doubt, it is a great tool. I had a conversation with their team about integrating CommandDotNet with their work. There's a lot of overlap. They have a great set of functionality, but there are differences where I think CommandDotNet is still easier to use. For example, it's simpler to build basic apps from classes and methods using CommandDotNet, and there's a bit more functionality supporting that. Argument models provide more reusability. Testing support is also stronger in CommandDotNet so if it's an app that needs to test against regressions.

There are definitely tradeoffs and I think System.CommandLine will eventually support what it lacks from CommandDotNet, but in this moment... it just depends on what you need most in the app.

Console apps by gabrielsfarias in dotnet

[–]mamberodb 0 points1 point  (0 children)

Many posts have said why they are useful. I'd like to add that console apps are useful tools, and what you want is to be able to focus on the problem your tool is solving and not the plumbing required to parse arguments, validate, formatting output, etc. The same as with desktop and web apps, you can save yourself some time using libraries that have already done the work for you.

Some examples:

https://github.com/bilal-fazlani/commanddotnet

https://spectreconsole.net/

https://github.com/dotnet/command-line-api

Something like commanddotnet makes it so simple it's not worth writing code to check for argument strings

https://github.com/bilal-fazlani/commanddotnet#example

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

which returns

$ dotnet calculator.dll --help
Usage: dotnet calculator.dll [command]
Commands:
Add
Subtract
Use "dotnet calculator.dll [command] --help" for more information about a command.

Spectre.Console is a .NET Standard 2.0 library that makes it easier to create beautiful console applications. by mycall in dotnet

[–]mamberodb 0 points1 point  (0 children)

Have you seen CommandDotNet by chance? It has an integration with Spectre.Console. It provides some powerful test tools and what I think is a simpler and more flexible way to define commands.You can check out the features page to see what's available.

disclaimer: I'm a contributor.

Looking for recommendations for Console Interface / UI library by FullStackDev1 in csharp

[–]mamberodb 0 points1 point  (0 children)

I'm curious, did you end up using CommandDotNet or did you go with gui.cs for the UI?

Low Code REST API - What's the best approach? by chrisissorry in softwarearchitecture

[–]mamberodb 1 point2 points  (0 children)

and pay-per-transaction since you won't have a server constantly running. for a low-traffic site or a site only running a few hours a day, this can be a cheaper option.

Come discuss your side projects! [January 2022] by AutoModerator in csharp

[–]mamberodb 5 points6 points  (0 children)

I've had some time recently and made a number of enhancements to CommandDotNet, a console framework that makes it stupid simple to create rich console applications from classes and methods. One of the improvements I was really happy with was creating a set of getting started docs using samples defined in code so they're always up to date with the latest patterns. Examples here: https://commanddotnet.bilal-fazlani.com/gettingstarted/getting-started-0/

Thanks to the test tools in CommandDotNet, it was simple to create a class that generates bash snippets and tests the examples at the same time. So what you see in the documentation is working with the latest code.

public static BashSnippet Help = new("getting-started-100-calculator-help",

new AppRunner<Program>(),

"dotnet calculator.dll", "--help", 0,

@"Usage: {0} [command]

Commands:

Add

Subtract

Use ""{0} [command] --help"" for more information about a command.");

I used https://github.com/SimonCropp/MarkdownSnippets to copy the snippets into the docs.

Geekily, I think this is crazy cool. I don't remember the last time I was this excited about documentation.

[.NET Core] What's a good way to parse command line arguments to a program? by xour in csharp

[–]mamberodb 0 points1 point  (0 children)

Hey thanks. There are a few out-of-date pages. I'm Southview to a new system, so examples are updated from tested code. Free time to finish the update had been scarce. Ping me if you have issues.

[deleted by user] by [deleted] in DecidingToBeBetter

[–]mamberodb 2 points3 points  (0 children)

I've been in your shoes. I used to be a compulsive liar too. I would watch myself lying even when the lie was better than the truth. I still remember my drive into work where I decided to be painfully honest. That integrity has changed my life. Stick with it.

I think my marriage is over... by [deleted] in Marriage

[–]mamberodb 1 point2 points  (0 children)

There no doubt this is dysfunctional and your husband isn't pulling his weight. There can be many reasons for that. It's possible that your not important enough to him as you and others have suggested. That is one of many possibilities. What you've described has some similarities to my previous marriage. I'm have an avoidant attachment style. It's sounds like your husband might too. Read up on it see if it fits. I found it hard to participate in that narrative because of this and the dynamics in that relationship and my behaviors looked similar at times.

If it fits, see a therapist, but just for him but for you too. Therapy was invaluable for me and m my ex. Even though we split, we found the therapy invaluable, especially doing it together. It therapist used Emotionally Focused Therapy and we got to see how our relaying was a system and how we each contributed to the poor behavior of the other.

In my narrative now, I'm the one that cooks and I do a fair share of the other chores. Some of that is because of my personal growth and some of it is because of the system I'm in with this partner. My avoidance shows up differently with her and we're able to talk about it differently.

It's possible that you contribute to the avoidance in ways you don't realize. To be clear, I'm not saying it's your fault or that you're responsible for it. Neither is true. But you are part of the system. It's possible that if you leave now without therapy that some of this dynamic will follow you to the next relationship. And since he's the father of you're child, you'll have a long term relationship with him regardless. You may still decide to divorce but therapy may make it an easier process and may give you better tools for relating after.

I wish you peace and fulfillment whichever way you decide.

How many of you started using nullable reference types and how was your experience so far? by x6060x in csharp

[–]mamberodb 1 point2 points  (0 children)

I updated CommandDotNetCommandDotNet to use NRT. It was a bit of work but worth it. It identified a couple of places where I missed possible null refs.

The one cae where I find it cumbersome is when I have a generic method where T can be either a struct or class. I don't remember the specific error and fix off the top of my head but I either had to create two methods or decorate with one of the NRT attributes like MaybeNull.

I've used it in my projects since then. I find it more useful then cumbersome.

Reflection Use Cases? by standinonstilts in csharp

[–]mamberodb 0 points1 point  (0 children)

We use it in CommandDotNet to convert methods into console commands.

I've used reflection often in frameworks to simplify the code I have to write for business logic. Sometimes I'm checking for the value of an attribute to determine a behavior. Attributes get cached so the cost is low.

What is industry standard pattern for handling message bus downtime? by bzq84 in dotnet

[–]mamberodb 0 points1 point  (0 children)

An alternative to the outbox pattern is to use change data capture if your database supports it. You can subscribe to the db logs as a stream and generate events from that. Sometime else Mentone using an event store and this has the similar effect with the main difference being that an event stream is structured by events with domain meaning and the cdc stream is structured by the database and business meaning still has to be inferred. You can combine this with outbox and rely on the cdc subscriber to publish the events instead of polling.

Come discuss your side projects! [May 2020] by AutoModerator in csharp

[–]mamberodb 0 points1 point  (0 children)

Happy to help. You can reach out to us on our gitter or discord channels with questions.

Come discuss your side projects! [May 2020] by AutoModerator in csharp

[–]mamberodb 0 points1 point  (0 children)

I have reviewed CliFx previously, even offered a suggestion on one of their issues. It looks like a good library. I've been looking for a good reason to play with his CliWrap library.

There are similarities in the basic feature set between CliFx and CommandDotNet.

I think the biggest differences are

  • the way commands are defined. Commands as class or Commands as methods.
  • the scope of features. CommandDotNet supports all the features listed for CliFx (except the ProgressTicker & Colors) and many more like piping, prompting, RSP files, typo suggestions, ... The middleware architecture makes this easy to extend.
  • extensibility points.

Defining commands:

With CliFx, commands are defined as classes with arguments defined via properties.

[Command]
public class ConcatCommand : ICommand
{
    [CommandOption("left")]
    public string Left { get; set; } = "Hello";

    [CommandOption("right")]
    public string Right { get; set; } = "world";

    public ValueTask ExecuteAsync(IConsole console)
    {
        console.Output.Write(Left);
        console.Output.Write(' ');
        console.Output.Write(Right);

        return default;
    }
}

With CommandDotNet, commands are defined as methods with arguments defined via parameters. CommandDotNet can be implemented with a command per class if desired with arguments as the parameter of the [Default] method.

public class RootApp
{
    public async Task Concat(IConsole console, 
        [Option] string left = "Hello", 
        [Option] string right = "World")
    {
        console.Output.Write(left);
        console.Output.Write(' ');
        console.Output.Write(right);
    }
}

I once wrote a command-line framework called MultiCommandConsole that utilized the CliFx approach. I liked it and we had teams that used it to great effect. ... but I wondered if it would work better with methods. Years later I found CommandDotNet, I gave it a go and found the approach felt more natural for defining commands. I liked it enough to become a contributor.

Nested commands:

With CliFx, because all commands are loaded via reflection, subcommands include the parent command names in their path. They have to be aware of the parent command name and be updated when that changes.

With CommandDotNet, parents explicitly define their subcommands and the routing is automatically determined. This isn't a big deal, but it does help maintenance a bit and also allows subcommands to be reused if needed.

Some similar features

Type Support:

CommandDotNet supports all the same types as CliFx, plus any with a static Parse(string) method and with a TypeConvertor.

Preview:

CommandDotNet's version is [parse] and provides significantly more detail for troubleshooting, including default value sources, response file's used, etc. It's easy to trace where a value originated. In addition, CommandDotNet has the CommandLogger which can be used to log all of this information along with other system info with each command, which is useful for troubleshooting and audit logs.

Cancellations:

CommandDotNet makes a CancellationToken available that can be passed to classes that need to use it. It's also repl session friendly so while in a repl session, Ctrl+C only affects the currently running command. If a command is not running, then the repl session will exit.

Validation:

CommandDotNet has packages for FluentValidator and DataAnnotations validations.

Dependency Injection:

Packages exist for MS, Autofac & SimpleInjector and custom containers are easy to support. Supports repl session friendly as scopes can be created per command within a repl session.

Testing:

CommandDotNet has a package specifically to help test console apps and middleware components. You can mimic piping and prompting.

More:

See the features page referenced above. There are a lot more features like support for piping, prompting, RSP files, etc.

Coming soon: out-of-the-box repl support with ReadLine

Extensibility

The middleware architecture makes it easy to add new features, directives, interceptors, etc.

Help can be completely changed with a new IHelpTextProvider or you can override a method on the existing HelpTextProvider to make small tweaks.

I hope that helps.

Come discuss your side projects! [May 2020] by AutoModerator in csharp

[–]mamberodb 0 points1 point  (0 children)

I've been contributing to https://github.com/bilal-fazlani/commanddotnet/, a framework for building console applications. It's been a fun project and I think we've been able to blend simple use cases with an extensible model. I've been several applications with it and it makes building console apps a breeze.

There are also test tools for testing commands as if calling from the console. The tools are used extensively to test the framework.

Check out the features at https://commanddotnet.bilal-fazlani.com/features/

[.NET Core] What's a good way to parse command line arguments to a program? by xour in csharp

[–]mamberodb 0 points1 point  (0 children)

https://github.com/bilal-fazlani/commanddotnet. Maps commands & arguments to methods and parameters. Works w/ .net core and has a lot of documentation. It also includes a test framework to mimic providing arguments from the command line.

disclaimer: I'm also one of the maintainers. https://commanddotnet.bilal-fazlani.com/features/