-
Notifications
You must be signed in to change notification settings - Fork 9
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
Determine order of NamedArguments #49
Comments
Can you give a specific example of what you are trying to do? I understand what you mean with ffmpeg, but I am having a bit of trouble understanding the problem when mixed with verbs. Arguments are completely independent from verbs, and the program and each verb has its own set of independent arguments, like below, and verbs should not prevent you from implementing named arguments. They do restrict positional arguments in the main program, but positional arguments will then work within the verb.
From what I can gather about your question, you may want to explore the void Main()
{
var args = "-f mp4 -w1024 -l768 -f wav -w 512 -l 512".Split();
var opt = CliParser.Parse<Options>(args);
if (opt.Filetype.Count != opt.Width.Count || opt.Filetype.Count != opt.Length.Count)
{
throw new Exception("Must provide same number of parameters for each");
}
foreach (var tup in opt.Filetype
.Zip(opt.Width, (f, w) => new { f, w })
.Zip(opt.Length, (fw, l) => new { Filetype = fw.f, Width = fw.w, Length= l }))
{
Console.WriteLine("{0}: {1}x{2}", tup.Filetype, tup.Width, tup.Length);
}
}
public class Options
{
[NamedArgument('f', Action=ParseAction.Append)]
public List<string> Filetype { get; set; }
[NamedArgument('w', Action=ParseAction.Append)]
public List<int> Width { get; set; }
[NamedArgument('l', Action=ParseAction.Append)]
public List<int> Length { get; set; }
} |
Thanks for taking your time @nemec ! In my case, I have a program where I would want the command line to function not only as a way of specifying settings for the program, but to also be able to execute functions. These need to be called in the order that they are specified, since each flag would manipulate data in certain ways. The system you proposed would definitely work in certain cases, but only for being able to detect the order of the same command being used multiple times, which would limit what I am trying to accomplish. Verbs don't directly have any role in this situation. I only looked up on what different data structures existed in clipr and they all do not seem to be a solution to this problem. So here's a hopefully more comprehensible example of what I am trying to achieve: // Initialize arguments - these should be substitutable with the short variants as well
var args1 = "--foo --bar 5 --function";
var args2 = "--bar 3 --function --foo";
// Example parser (could parse args2 as well)
var parser = new CliParser<Options>(new Options());
parser.Parse(args1);
// Executing functions based on their order
foreach (var flag in parser.Arguments)
{
switch (flag.Name)
{
case "foo":
Console.WriteLine("foo");
break;
case "bar":
Console.WriteLine("bar" + flag.Value.ToString());
break;
case "function":
Console.WriteLine("function");
break;
}
}
// Output for args1:
// foo
// bar5
// function
// Output for args2:
// bar3
// function
// foo Obviously, above code would not compile. The Options class would need argument definitions which work the way they usually do (for --function for example, it could store a value Essentially I would want to be able to go through the list of NamedArguments as they were specified, and optionally get the value as it was specified directly from the argument instance (otherwise, it would suffice getting it from the respective property from the Options instance). Again, thanks for your help and for this convenient library! 😄 |
Thanks for providing more details, that's a very interesting idea. I will give some thought to what it would take to implement this in the code. |
Hey @RedMser I am taking a look at this now and am considering adding an event that is triggered immediately after a parameter and its values are parsed. You will have to manage what exactly happens (function execute, print, etc.) within the handler, but the handlers will be required to execute in left-to-right parsing order within an object. For the event data, I am considering invoking the event with an EventArgs that contains the option property name and a the value of the parsed argument. Note that given the below options class, class Options
{
[NamedArgument('f', 'foo')]
public int FooThing { get; set; }
} From your end it will look something like this: var args1 = "--foo --bar 5 --function";
var args2 = "--bar 3 --function --foo";
Action<object, ParsedEventArg> act = (sender, store) => {
switch (store.Name)
{
case "FooThing":
Console.WriteLine("foo");
break;
case "BarThing":
Console.WriteLine("bar" + store.Value.ToString());
break;
case "Function":
Console.WriteLine("function");
break;
}
};
var popts = new ParserOptions();
popts.OnParse += act;
var parser = new CliParser<Options>(new Options(), ParserOptions=popts);
parser.Parse(args1); Thoughts? |
Seems like a solid way to solve the problem! Retrieving the exact name of the flag entered by the user indeed is nothing really required, since both the short and long names are supposed to be synonyms anyway. |
Hey @RedMser I just checked in an implementation of my solution described above. I am putting it in the 2.0 branch, so I have no idea when it will be officially released, but once I update the codebase for a newer .NET Core I will probably release a beta version on NuGet. Let me know if you have any other suggestions, or if I missed something. clipr/src/clipr.Sample/Program.cs Lines 402 to 427 in 69892a0
|
Unless I misunderstood the differences between PositionalArguments and NamedArguments, you can currently not have a NamedArgument and determine its position in the list of command line arguments.
This would be useful as you could allow different commands to be executed in a certain order without being restricted by the Verbs system (e.g.
prog.exe --load-config default.cfg --open-file test.txt
).Similar use case is shown in FFMPEG's argument system, where you refer to input media files by their order in the argument list, or certain flags only apply to the previous input.
Although untested, this may be worked around by implementing setters of the argument's properties which then increment a counter for determining the order. In that case, the parsing order will have to be clearly defined.
Thanks for your hard work,
RedMser
The text was updated successfully, but these errors were encountered: