c-blake / cligen

Nim library to infer/generate command-line-interfaces / option / argument parsing; Docs at
https://c-blake.github.io/cligen/
ISC License
506 stars 24 forks source link

How to pass version to `dispatchMulti`? #42

Closed kdheepak closed 5 years ago

kdheepak commented 5 years ago

Hi,

When using dispatchGen, I tend to do the following.

    dispatchGen(main, version = ("version", "cli (" & versionString & ")"))

However when using dispatchMulti, I'm not able to do the same thing:

    dispatchMulti(
        [ upload ],
        [ create ],
        [ remove ],
        [ logs ],
        [ version ],
        # version = ("version", "cli (" & version_string & ")")
    )

Is there a way for the user interface to look like the following when using dispatchMulti:

$ cli --version
v0.1.0
c-blake commented 5 years ago

Well, right now you would have to do something like this:

proc upload(x: int): int = 0
proc create(y: int): int = 1
proc remove(z: int): int = 2

import cligen
let vstr = "1.0"
dispatchMulti([ upload, version=("version", vstr) ],
              [ create, version=("version", vstr) ],
              [ remove, version=("version", vstr) ])

and require the user to invoke one of the subcommands. { I'm not sure why I can't make the whole 2-tuple a variable itself, but that was breaking. }

dispatchMulti actually just uses dispatchGen, too, which you can see if you compile with nim c -d:printMultiDisp xyz.nim. So, one could add a global option pretty easily.

However, at the moment dispatchMulti takes no parameters besides procBrackets. I think (but I am not sure) that it would be a pretty invasive code change to add some new parameter to tell dispatchMulti what the version is/and to pass it to dispatchGen. It should be easy, though, to add a global variable cligen_version initialized to something inert that when set differently tells dispatchMulti to add it to the dispatchGen call for the top-level parsing. Pull request would be welcome. (Also, one to let you pass a 2-tuple more easily.)

c-blake commented 5 years ago

Oh, and also it bears mentioning in this thread that this feature is of very limited interactive utility compared to say having one of your subcommands be version which is actually in your example. I.e., it's easier to type mycommand version than mycommand --version.

I do realize, though, that there could be some script context where you want to always be able to spell it $x --version where $x could be either single-dispatch and multiple-dispatch programs.

c-blake commented 5 years ago

So, I don't provide any way to have a short option at the global level, but otherwise just setting cligenVersion to some string works now. See test/FullyAutoMulti.nim for an example. I also refreshed my memory why you need a literal 2-tuple but was able to relax the value of that 2-tuple to be able to be a variable. See, test/Version.nim for an example of that.

c-blake commented 5 years ago

Oh, and just in case it was not obvious, you can synthesize the above variable fix with the new dispatchMulti feature to set the version in just one place:

proc upload(x: int): int = 0
proc create(y: int): int = 1
proc remove(z: int): int = 2

import cligen

cligenVersion = "1.0"
proc version() =
  echo cligenVersion

dispatchMulti([ upload, version=("version", cligenVersion) ],
              [ create, version=("version", cligenVersion) ],
              [ remove, version=("version", cligenVersion) ],
              [ version ])

Then you can get that "1.0" version string printed via any of:

./foo --version
./foo version
./foo create --version

Additionally, you can even auto-generate that version string at compile-time via staticExec from a version control repository version (as in test/Version.nim), or perhaps the name of a directory or contents of some file.