vezel-dev / cathode

A terminal-centric replacement for the .NET console APIs.
https://docs.vezel.dev/cathode
BSD Zero Clause License
91 stars 7 forks source link

Provide a command line option parser package #33

Open alexrp opened 2 years ago

alexrp commented 2 years ago

Some kind of compromise between Mono.Options (too simple) and System.CommandLine (way too complex).

scottbilas commented 2 years ago

Might I humbly suggest something inspired by Docopt.net? (This particular library impl has serious problems, but the spec-as-docs concept gets my kudos.)

alexrp commented 2 years ago

I do like the idea behind docopt, but I'm not exactly sure yet what form this API will take. I'm thinking something vaguely along the lines of Spectre.Console.Cli, but a bit simpler.

My gut feeling is that a docopt-like implementation should sit at a higher level, essentially as a wrapper around such APIs. It could even be made AOT-friendly by using source generators to generate the relevant classes during compilation.

scottbilas commented 2 years ago

Agreed on source generators - runtime parse- (docopt, mono.options) or reflection- (spectre, powerargs) based approaches add unnecessary startup cost, and move some problems from the compiler to the debugger. Docopt used an older T4-based method to generate static types, but removed it due to maintenance cost in favor of a source generator-based approach..which is still just in the idea phase.. (https://github.com/docopt/docopt.net/pull/119).

My gut feeling is that a docopt-like implementation should sit at a higher level, essentially as a wrapper around such APIs.

Maybe I lack imagination, but I can't picture an API that would benefit docopt. All it needs is a string[]. I'd expect that any lower level processing would just be redundant or interfere with the work a docopt state machine is needing to do anyway. And a sourcegen-based docopt would be statically generating all the config types from the doc spec, so the spectre style user-defined types+attributes would have no place.

(That all said, I guess most C# users will expect a config API more like Spectre.Console.Cli, and it's got to be a lot simpler to implement.)

alexrp commented 2 years ago

I'm not super familiar with docopt but a quick skim of the page you linked made me think that a docopt library could just take a help string as input and generate (at compile time) Command/CommandSettings classes to match the specification (if we're assuming a Spectre.Console.Cli-like lower-level API). Maybe there are nuances I'm not aware of though.

scottbilas commented 2 years ago

True, it can be codegen'd from the help string, and I think the Command system would be at least one place that would make it beneficial for a docopt type library built on top of a lower level API.

But that lower API still needs to be told how parameters and aliases map onto class members and so on. Spectre.Console.Cli-type API's do this with attributes:

image

This is what I meant by redundancy - the lower-level API has to walk types and attributes and do some string parsing (as in the above example) in order to construct its in-memory spec. Yet the docopt library would have already done all that work at compile-time. It gets thrown away..

Now, if this lower level API provided a way to feed it the specification, without requiring attribute-scanning, then a docopt system could codegen that part and maintain zero-overhead startup.

alexrp commented 2 years ago

Now, if this lower level API provided a way to feed it the specification

Hmm, it would probably have to, at least if it's based on source generators as well, which is what I'd prefer. So in such a world order, both the class/attribute-based API and a docopt-like API could build on top of that low-level model API.