Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Library] Commandline parsing #225

Closed
nyctef opened this issue Feb 13, 2019 · 13 comments
Closed

[Library] Commandline parsing #225

nyctef opened this issue Feb 13, 2019 · 13 comments

Comments

@nyctef
Copy link
Contributor

nyctef commented Feb 13, 2019

What change would you like to make to the tech radar?

Add CommandLineParser to Explore
Add NDesk.Options to Adopt
Add RedGate.Legacy.CommandLine to Endure

Why do you believe this is valuable to Redgate?

Some discussion in this thread: https://redgate.slack.com/archives/CEXRY1B0B/p1550056281025600 (thanks @chrisgeorge0911 for pointing out this should be on the radar :)

Most of our new commandline tools actually use Powershell instead of parsing their own commandline arguments, so we haven't needed a commandline parsing library in a while.

Older tools (such as the SQL Compare commandline) use the RedGate.Legacy.CommandLine package that's been pulled out of SHU - it's not ideal, but it's working well enough for the moment. I think NDesk.Options is a pretty good drop-in for these projects - it's currently being used by the existing Oracle tools and we've used for some of the pre-powershell DLM Automation tools in the past. While the project isn't under active maintenance (there's a single official nuget package from 2011), it still works, and the library itself is pretty tiny if we ever needed to take control of it for ourselves.

As an alternative, we'd like to have a go with CommandLineParser. The advantage here is that the library nicely supports having multiple 'verbs' (similar to git commit / git add / git status / etc). The reason we want to build a new commandline (instead of going for powershell) is that we believe Oracle users are much more linux-based and are less likely to adopt a solution that requires powershell. There are a few existing usages in RG, but nothing extensive: https://codesearch.red-gate.com/?q=%5CbCommandLineParser%5Cb&i=nope&files=&repos=

Where should this be on the tech radar?

Probably in radar_libraries.csv under Redgate/Public NuGet?

If this should be in the Explore ring, who is committed to exploring it?

Team Orca

@adrianbanks
Copy link
Contributor

I've used ManyConsole in production in the past and it is similar to NDesk.Options, but I found it much easier to work with.

@fffej
Copy link
Contributor

fffej commented Feb 14, 2019

NDesk.Options is in Adopt, but as far as I can tell doesn't have any maintainers? Should it be the successor Mono.Options? The package @adrianbanks mentions looks like it builds on top of Mono.Options.

@nyctef
Copy link
Contributor Author

nyctef commented Feb 14, 2019

Probably, yeah - I don't know how different Mono.Options is from NDesk.Options, but the docs look pretty similar: https://github.com/xamarin/XamarinComponents/tree/master/XPlat/Mono.Options#getting-started

@adrianbanks
Copy link
Contributor

adrianbanks commented Feb 14, 2019

I think ManyConsole was possibly originally built on NDesk.Options and has been switched over (I was surprised to see it based on Mono.Options when I looked at it the other day as I'm sure it relied on NDesk.Options when I last used it).

EDIT: It looks like NDesk.Options was renamed to Mono.Options.

@cjheppell
Copy link

We've been using Microsoft.Extensions.CommandLineUtils which has been working fine for us in Foundry.

Unfortunately it's not actively maintained by Microsoft anymore, but there's a community fork with active maintenance. We haven't found the original NuGet package lacking, though.

Only thing I'd say is that our command lines are very simple, so this package might not be enough for what's being discussed here.

@fffej
Copy link
Contributor

fffej commented Feb 15, 2019

Looking at the libraries, I'm finding it difficult to distinguish between what we should be using.

Does anyone have any strong opinions?

@cjheppell
Copy link

cjheppell commented Feb 15, 2019

I haven't used any of the other libraries mentioned in this issue, but my preference would be anything that fits the following criteria:

  • Actively maintained
  • Supports .NET Core/Standard
  • Implementing it doesn't cause its code to scatter all over the codebase with horrible annotations and whatnot
  • Ideally, auto-generation of the help/usage

After a quick browse, my vote goes to CommandLineParser to go in Explore since it seems to tick all those boxes.

@fffej
Copy link
Contributor

fffej commented Mar 13, 2019

@nyctef Sounds like we're about ready for a PR - do you want to make one that summarizes this discussion and we can resolve this?

@adrianbanks
Copy link
Contributor

adrianbanks commented Mar 13, 2019

I forgot to mention - I did some spiking a few weeks back of the command line libraries mentioned here. The code is here for anyone wanting to compare them. All of the implementations do the same thing.

From working with them all, ManyConsole gives the cleanest API as it works on a command based structure. Each command defines its options and the action to take when executed. CommandLineParser was probably the simplest to set up for a simple command line, but I couldn't find a way of doing nested commands (similar to git's command line, for example).

It's probably also worth considering this library, as it's just been released by the .Net team and is part of the .Net Foundation, so is likely to gain some traction as it looks like it might be their new way of doing command line parsing.

@ChrisHurley
Copy link
Contributor

I've found that CommandLineParser doesn't have any native support for subcommands, which makes it difficult to use for the sort of semantics (inspired by e.g. kubectl) that are used in Foundry's command lines, e.g.

estatectl get access-token a56bc4f`
estatectl get serverinfo --type mssql --connectionString "..."`

commandlineparser/commandline#69
commandlineparser/commandline#353

It's possible to work around it by handling multi-level parsing yourself in some way, but that's not ideal.

I previously evaluated System.CommandLine, mentioned by @adrianbanks, but while it's powerful I don't think it supports an attribute-based API at the moment, which makes it a bit less readable and more of a change if you're used to CommandLineParser. (They have a reflection-based prototype but it doesn't yet look viable for anything that's not very simple.)

I've found CommandLineUtils to probably be the best balance right now, supporting similar semantics to CommandLineParser but with support for subcommands, but it doesn't support option sets.

(I'm not sure where I should be recording this other than here.)

@Greg-Smulko
Copy link
Contributor

Also, CommandLineParser seems to be abandoned, really. :(
The last commit to master was on Jul 31, and my PRs (this and this) are dying there slowly since 15th Apr 2019.

I'd propose to move CommandLineParser from Explore to Endure/Retire. :(
Any thoughts from the team that uses it? @nyctef?

@allymparker
Copy link
Contributor

FWIW I'd probably prefer to use System.CommandLine over handrolling something else

@ChrisHurley
Copy link
Contributor

The main problem I have with System.CommandLine is that it still feels pretty early. The builder API is pretty flexible although verbose, but the reflection-based one (Dragonfruit) is probably too basic, and the documentation is sparse. Most significantly, its NuGet package is called System.CommandLine.Experimental and is in prerelease (which doesn't really give "use this in production" feelings). If it felt more mature then I'd probably favour it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants