nerai / NConsoleMenu

Console menus are easy to build, complex menus are supported, and using them is simple and quick
MIT License
35 stars 3 forks source link

Allow parsing of multiple args for a command #102

Open selmaohneh opened 5 years ago

selmaohneh commented 5 years ago

Allow stuff like

menu.Add("greet", (x,y) => Greet(x,y), "Greets a name a number of times.");

Would be great to have multiple parsed arguments instead of a single string.

nerai commented 5 years ago

Do I understand this correctly: You want to add a menu entry. When this entry is called like

$ greet Jon 4

It should call the action body with the two parameters Jon and 4, i.e. it should call

`Greet("Jon","4")`

Is that right?

I think the only generic approach to this would be to add something like a regex, that parses the argument and fills in the varargs of the action body. This could probably be done in the library itself. But why not just parse the regex in the action body directly? You have full control then.

That is to say, I would probably do it like this:

menu.Add ("greet", s => {
    var regex = new Regex (@"(?<name>[^ ]*) (?<times>[0-9]*)");
    var match = regex.Match (s);
    var name = match.Groups["name"].Value;
    var times = int.Parse (match.Groups["times"].Value);
    for (int i = 0; i < times; i++) {
        Console.WriteLine ($"Hello {name}!");
    }
}, "Greets a name a number of times."); 

$ greet Jon 3
Hello Jon!
Hello Jon!
Hello Jon!
selmaohneh commented 5 years ago

You understand it right. :) In addition I would even like to call Greet("Jon", 4), i.e. with the second value directly parsed to an int. It would be very convinient to have the parsing done in the library instead of writing it everytime on my own. Currently I do that in combintation with PowerArgs. Having both of your libraries work together feels like a custom git bash with my own commands :) . So, in summary:

Yeah, it works your way, but it is not that convinient. Maybe think about adding a argument parsing similar to PowerArgs.

Let me know your decision.

EDIT:

I know this has no high priority. In addition I think it is not that trivial, since it would involve reflection stuff. Maybe using PowerArgs in combination is the right way... I don't want to invent the wheel again, you don't want the dependency to PowerArgs, I guess...

nerai commented 5 years ago

I did not know about PowerArgs, it looks like a nice library. Thanks for showing! I see some synergy in adding it here. However, it is also a significant change and dependency that I need to examine in detail. Currently I sadly lack the time, so I want to postpone this for now. Sorry!

For your use case, I'm not sure if it is possible, but what comes to mind is deriving from CMenuItem. This subclass could then implement PowerArgs, and you could create instances from it. Is that possible with PowerArgs? If your menu items are large anyway, this would probably be easier to maintain, too.

What sadly does not work at the moment is using the predefined Add-style methods like menu.Add ("x", ...) in combination with PowerArgs. Deriving from CMenuItem is required.

However, I'll add a factory method in the next patch. Then your own class gets constructed when you call Add. Maybe that helps with this effort.

nerai commented 5 years ago

It's in the master branch. I'll push it to Nuget later, too.