nick-lucas / entrypoint Goto Github PK
View Code? Open in Web Editor NEWComposable CLI Argument Parser for all modern .Net platforms.
Home Page: https://nick-lucas.github.io/EntryPoint/
License: MIT License
Composable CLI Argument Parser for all modern .Net platforms.
Home Page: https://nick-lucas.github.io/EntryPoint/
License: MIT License
If LongName or ShortName have not been provided on 1 or more options, then ValidateTokensForDuplicateOptions
will throw
.Net string[] args has some reliance on the shell for what it receives. Need to check for inconsistencies like Quotes not being stripped
Todo
This might be me doing something very silly, so I apologise if that is the case but..
If I try and pass a file path as an operand (like c:\some\path
) by the time it gets to the method that handles the command the slashes are removed.
If however I escape them in the input it works as intended. Is there a way around this? Its not too much of a big deal for me at the moment (as I am using this primarily on Linux at the moment so I am never encountering \
as a path separator) but it does mean that dragging and dropping files onto an exe with this setup doesn't work which is a shame.
A new Attribute to mark two options as exclusive, or strictly inclusive of another option would be useful for validation on the user side.
Something like:
OptionRelationship(
Relationship = OptionRelationshipEnum.DependsOn | ExclusiveOf,
OptionProperty = nameof(MyProperty))
Since we now have Model.Operands it would be more consistent to move this down a layer
This will break EntryPoint as it stands, since arguments are combined again in order to be parsed.
As shown below, quoted sections get split, and lists are also split correctly.
Need to tweak tokenisation to expect these conditions
Source:
public class Program {
public static void Main(string[] args) {
foreach (var arg in args) {
Console.WriteLine($"Arg: {arg}");
}
Console.Read();
}
}
For instance if we have:
--log
--log-level
When --log is provided, then it can be matched to --log-level, because the current solution uses .StartsWith
for simplicities sake
Properties could be initialised on the model directly, instead of by EntryPoint.
Is there any advantage to calculating the value later?
Currently Ints will probably map fine to Enums, but strings may not.
Support for recognising and mapping these properly would be good
-o --option REQUIRED
-o --option [string]
Utility [-a] [-o | --option value] [operands]
This exception is the base class for all exceptions which are intended to have their message displayed to the user
The readme works fairly well for now, but would benefit from being fleshed out like Limebean
Currently the IEEE standard is enforced, where operands must come after everything else.
it is quite common on CLIs to support operands coming before options.
we should support this to increase usability
Such as Range(0, 60) for numbers, Regex() validation, etc.
This is a nice to have, although quite easy to do by the application developer, and potentially more flexible that way.
Right now there is no explicit validation for this.
It may be preferable to enforce this using constructors, and this is possible before 1.0
Otherwise some validation on the model would be best, if forcing named arguments is preferable.
Right now a user may have to read the entire documentation to get an idea of a complete implementation
Need to update documentation for all of this.
APIs can and are changing before 1.0, but it's not explicitly mentioned in the current pages.
Hi, thank you for your work on this library. It has helped us build a clean command line program.
Waiting on the Console.ReadLine()
is breaking my unit tests. They just hang there. Since no output is captured by xUnit, it was laborious to find the problem.
Would you consider removing the ReadLine
call?
As seen in #46, it would help with self documentation for new developers if this message gave some advice on what they may be looking for.
Priority to fix
Not the most common type, and some work on the help generator may be needed for option value structure
The new DocFX site does not container these links in the navbar, and it was quite nice to have before.
Let's add them back!
This is still not nailed down pre-1.0, and I'm not totally happy with the developer workflow.
Things like 'ignore required' when --help is invoked, leave EntryPoint in a footgun position, if a developer doesn't realise they should check .HelpRequested
after parsing.
0.9.5 is out there, but may yet change again.
A current example is detailed here: https://nick-lucas.github.io/EntryPoint/
Right now a standard form list: item1,item2,item3
will be passed back as a string.
If the Tokeniser and Parser can recognise this, then we can populate a List<T>
on the ApplicationOptions
It would be nice if you could write methods which act as entry points for particular commands, ASP.NET Core style.
Take git
for example:
git checkout <ref> [-b -f]
git add <path> [-a]
So you could implement it like:
[Route("checkout {ref}")]
public int Checkout(string ref, [Option(ShortName = "b")] bool create, [Option(ShortName = "f", LongName = "force")] bool force)
{
// code...
}
[Route("checkout {path}")]
public int Add([FromRoute]string path, [Switch('a')] bool all)
{
}
Currently if we have a default command, and the user mis-types a command name, the default will take control and be passed the broken command as the first argument.
We can then end up in a situation where the wrong command is called, or the correct command is called but in an invalid args state, which causes unclear exceptions to bubble back up that are intended for more specific scenarios.
By validating inputs before throwing any other sort of exception, we can get around this.
Enums should be recognised ad have their options listed
For instance for an Int property, the user provides a string, we should handle this with a UserFacingException
Right now Commands pass string[] args
on to their methods.
Suggestion here is to allow methods to define arguments in their parameters, similarly to ASP.Net
Another halfway solution would be to pre-parse a CliArguments
implementation and pass this in (A arguments) where A : BaseCliArguments
Currently stands at:
Possible solution is: DocFX
/// <summary>
/// .Net Behaviour Observations
///
/// .Net automatically tokenises command line arguments and passes them to the program as `string[] args`
///
/// .Net Core does not provide raw access to the original string due to x-platform concerns,
/// see: https://github.com/dotnet/coreclr/issues/3103
/// This may change in the future
///
/// .Net tokenisation does a few things:
/// * Split on Whitespace (Good)
/// * Protects quoted contiguous text which means:
/// ` "1 23",456 ` transforms to a single token: ` 1 23,456 ` (Good)
/// * Strips quotes, even on list tokens, which means
/// ` "1,23",456 ` transforms to a single token: ` 1,23,456 ` (BAD)
///
/// This behaviour needs to be worked with by the Tokeniser.
///
/// The latter behaviour is un-workable and needs to be communicated as a limitation,
/// and communicated to the .Net team
///
/// </summary>
Passing such valid argument on command line
program.exe command --path "C:\path\to\dir"
will result in getting the following from args!
bool trueValue = args.Path == "C:pathtodir";
When falling back to Environment.GetCommandLineArgs()
we need to ignore the first entry.
This causes Cli.Parse and Cli.Execute to fail when not given their string[] args
explicitly.
Attributes could be available for fields as well. I don't see any need to generate more code by declaring unnecessary properties.
Since we can now map operands to variables, it may not make sense to include those which we've used
This might be a breaking change, so some sort of option should be provided.
Currently when a subclass of UserFacingException is thrown it bubbles up to the Cli.MethodName call.
It might be a good idea to let developers override this on CliArguments/Commands classes in the same way which the help generator can be overridden, using a virtual method with a common-sense default implementation.
It's not totally obvious when first building a CLI that --help is doing nothing because you haven't implemented it.
Would be best to provide a default implementation and advertise it can be overiden, in the docs
It would be useful to provide easy access to secrets, and validate that they've been provided, in the same manner as option-parameters
A new attribute could be used to map positional operands much like Options are mapped.
Something like:
[Operand(
Position = 1,
[ParameterDefaultBehaviour],
[ParameterDefaultValue])]
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.