Add procedure dispatch module
This adds a module which allows very easy dispatch of procedures from the parsed arguments.
I think this would be a really nice addition! I've often wanted to have more type safe control over docopt.
@Vindaar, unfortunately this version of docopt does the parsing of the string and such on runtime. This means that it is not possible to create a type-safe dispatcher without essentially re-implementing docopt. What this does is simply to implement a dispatcher over the table of values that docopt provides. It will throw runtime errors if it is unable to convert the value to the correct type though.
Oh, yes. I'm aware of that @PMunch. That's why I was talking on IRC the other day about completely changing the docopt "input" structure to either not completely rely on strings, but rather a Nim DSL (imo the string approach is mainly because most languages don't provide Nim's macro powers). Of course then it's not completely docopt anymore. Or alternatively parse the string at CT.
In this context regarding type safety I was only referring to not having to extract the typed data manually from the variant values at runtime.
Ah, yes in that case this is exactly what you want. But yeah, best would be to parse the docopt format on compile-time, then allow you to register dispatch commands and such which would add type-checking and good fallbacks. This would not only make it possible to craft even more type-safe interfaces, but it would also mean that the argument parser would be much faster as it wouldn't have to parse the docopt format every time the program is run.
Regarding this PR: the idea is probably good but I will not reasonably be able to review it. At this point basically any member of Nim community would be a better reviewer than me. I would encourage you to "crowd-source" a (thorough) code review, then I'd take that into account.
Regarding compile-time. Sure, that should be the end-goal and would be an amazing showcase of the strength of the language. Back when I still cared, the blocker was the unavailability of regex at compile time. Now as I understand, that's available. The space is totally open to write a completely new version. (I will not do it, to be clear). FWIW I do think that it still should be done by parsing the docopt string, definitely not a DSL.
Regarding compile-time. Sure, that should be the end-goal and would be an amazing showcase of the strength of the language. Back when I still cared, the blocker was the unavailability of regex at compile time. Now as I understand, that's available. The space is totally open to write a completely new version. (I will not do it, to be clear). FWIW I do think that it still should be done by parsing the docopt string, definitely not a DSL.
I agree that it should be done by parsing the docopt string and not a DSL. And I'm currently looking into doing a compile-time implementation, but this will be pushed as a separate project.
I would encourage you to "crowd-source" a (thorough) code review, then I'd take that into account.
btw, this is still the case, despite my (minimal) review comments
Fixed the various things that were commented about, and added support for custom types in signatures while I was at it
Looks really great to me now (barring the 2 small typos)!
Rebased onto the current master and fixed compilation on Nim 1.4.0.
Can anyone vouch that 2fdff42518c891422609edcbb14b800d6c41cfe1 is the simplest solution?
getImplon enum type symbols now returns field syms instead of idents. This helps with writing typed macros. The old behavior for backwards compatibility can be restored with--useVersion:1.0.
It seems to be pretty much the only way to do it: https://irclogs.nim-lang.org/02-11-2020.html#11:25:51, and from the creator of Nim himself: https://irclogs.nim-lang.org/02-11-2020.html#12:47:14. So at least until a new version of Nim comes around with something like this in the standard library this is the easiest (and pretty much only) way. I'll make a PR to swap it out if something like this ends up in the stdlib though.
As for the thing you copy-pasted, forcing people to use the --useVersion:1.0 isn't great as it has project-wide consequences. And creating a solution like this that works both on older version and is the way going forward is decidedly a better option.
Oh I wasn't implying anything about --useVersion:1.0.
OK thanks. I'll probably merge this after I take another look.
Can anyone vouch that 2fdff42 is the simplest solution?
Aside from what PMunch already answered, yes it really is. I use similar code in my macros where required and other people do the same.
@oprypin how's that second look coming along? I was rebuilding an older project of mine and noticed it was still pinned to my fork.
Still no word on this?
Hi. Yeaaah at this point I can say with certainty: This project is abandoned. Sorry.
Or actually at that point, why not just merge it :D I'll do that today and release afterwards
@oprypin Hey, can you just release new version because right now if you install via nimble install docopt the dispatch module doesn't work! Actually if you go to the directorium ~/.nimble/pkgs/docopt-0.6.8/docopt/ there is no dispatch.nim file..
Thanks :relaxed:
Aah sorry :cry: I've been looking at it in my todo list for a while and not actually doing it
I tagged https://github.com/docopt/docopt.nim/releases/tag/v0.7.0 now
@oprypin And dispatch module still doesn't work, it gives me the following error on compile: Error: attempting to call undeclared routine: 'strip' in dispatch.nim (ln 99, 19)?
Well, I have no idea how Nim works by now, contributions definitely welcome.
@grey4owl I'll have a look at this after the weekend. For now you probably have to use an older Nim version
@grey4owl, not entirely sure how you ended up with that error. If I clone the repo, cd into the examples folder, and compile dispatch.nim it works just fine. And I'm able to run it and get it to dispatch as I would expect. This is with both latest Nim and devel.
And everything passes in CI, including the dispatch example https://github.com/docopt/docopt.nim/actions/runs/3210603085 https://github.com/docopt/docopt.nim/blob/master/examples/dispatch.nim https://github.com/docopt/docopt.nim/blob/master/docopt.nimble
@PMunch Everything works fine now.. I wonder if it is possible to set a custom message when a wrong / non-existent argument is entered and when no argument is entered so that it does not show the default usage message every time but something custom? I already made a custom help menu, I just set help = false and made my own, but I would also like to change those messages so that they don't show the default usage string from the doc..
@PMunch Actually I made a custom message if no argument was entered, but how do I handle the output message if a wrong / non-existent argument is entered?