Coder Social home page Coder Social logo

Determine order of NamedArguments about clipr HOT 6 OPEN

nemec avatar nemec commented on May 13, 2024
Determine order of NamedArguments

from clipr.

Comments (6)

nemec avatar nemec commented on May 13, 2024

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.

prog.exe --load-config default.cfg --open-file test.txt commit -m "some commit message"
         |________________app_arguments_______________|        |____verb arguments____|

From what I can gather about your question, you may want to explore the ParseAction.Append action, which lets you combine multiple of the same arguments into a list. You can then iterate through them and correlate order by index in the list. Something like this:

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

from clipr.

RedMser avatar RedMser commented on May 13, 2024

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 true or a Const 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! 😄

from clipr.

nemec avatar nemec commented on May 13, 2024

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.

from clipr.

nemec avatar nemec commented on May 13, 2024

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, store.Name will be FooThing rather than foo or --foo - there will be no way to determine whether the user said -f 5 or --foo 5 in the command line, but IMO that should be enough.

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?

from clipr.

RedMser avatar RedMser commented on May 13, 2024

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.
I'd need to mess with it in an implementation to really see anything missing from the event system (or the EventArgs' members).

from clipr.

nemec avatar nemec commented on May 13, 2024

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.

public static void ParseArgsWithEvent()
{
var cfg = new ParserOptions();
cfg.OnParseArgument += (ctx, args) =>
{
switch (args.ArgumentName)
{
case "Foo":
Console.WriteLine("foo");
break;
case "Bar":
Console.WriteLine("bar " + args.Value.ToString());
break;
case "Function":
Console.WriteLine("function");
break;
}
};
var parser = new CliParser<OrderedArgs>(cfg);
parser.Parse("--foo --bar 5 --function".Split(), new OrderedArgs());
Console.WriteLine("--- Next ---");
parser.Parse("--bar 3 --function --foo".Split(), new OrderedArgs());
}

from clipr.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.