c-blake / cligen

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

API change/change in return value of dispatch_* procs? #83

Closed kaushalmodi closed 5 years ago

kaushalmodi commented 5 years ago

Hello,

I have this snippet like this in few of my packages:

when isMainModule:
  import cligen
  const
    url = "https://github.com/OrgTangle/ntangle"
  dispatchGen(ntangle
              , usage = "\nNAME\n  ntangle - $doc\n" &
                "USAGE\n  $command $args\n\n" &
                "OPTIONS\n$options\n" &
                "URL\n  " & url & "\n"
              , help = { "version": "write the version to stdout" }
  )
  if paramCount()==0:
    quit(dispatch_ntangle(@["--help"]))    # This is line 564 referenced in the backtrace below.
  else:
    quit(dispatch_ntangle(commandLineParams()))

Ref: https://github.com/c-blake/cligen/issues/27#issuecomment-387819439

That works with the latest cligen release as of today (0.9.18). But after nimble install cligen@#HEAD, I get this error:

ntangle.nim(564, 9) Error: type mismatch: got <void>
but expected one of:
proc quit(errormsg: string; errorcode = QuitFailure)
proc quit(errorcode: int = QuitSuccess)

expression: quit(dispatchntangle(@["--help"],
                     "Command-line utility for Tangling of Org mode documents", "\nNAME\n  ntangle - $doc\nUSAGE\n  $command $args\n\nOPTIONS\n$options\nURL\n  https://github.com/OrgTangle/ntangle\n",
                     "", "", false))
stack trace: (most recent call last)
../../../../../../pkgs/nim/devel/lib/system/nimscript.nim(351)
../../../../../nim/nim/config.nims(231) muslTask
../../../../../../pkgs/nim/devel/lib/system/nimscript.nim(252) selfExec
/home/kmodi/stow/pkgs/nim/devel/lib/system/nimscript.nim(252, 7) Error: unhandled exception: FAILED: /home/kmodi/stow/pkgs/nim/devel/bin/nim c -d:musl -d:release --opt:size  src/ntangle.nim

I am using Nim built from devel branch 160a03464310d8a9e1ffaf83d73904df3439df78.

c-blake commented 5 years ago

Yeah. The way you manually call a generated dispatcher has changed quite a bit. Now the dispatcher has the same return type (including void) as the wrapped proc. While I hope to someday have an exported template that makes calling them about as easy as cligenCall(dispatch_ntangle()), right now you have to do your own try:/except:. Just doing one of your two if branches:

try:
  dispatch_ntangle(@[ "--help" ])
except HelpOnly, VersionOnly: quit(0)
except ParseError: quit(1)

You could probably do the try/except around the whole if statement with the quit()s removed. Also, you should not need to pass commandLineParams(). It should default to that.

This is sort of in the RELEASE_NOTES.md, but a) that is giant and b) I don't really have step-by-step-what-to-change instructions there. This basically is to support calling and dispatching but necessarily exiting the program. See https://github.com/c-blake/cligen/issues/47

c-blake commented 5 years ago

Also, the new mergeParams gives you an entirely other way to do what you want there which you might like better. You can import cligen and somewhere before dispatch (not even dispatchGen) add --help if cmdLine.len == 0. There's an example of more complex usage in the current README.md just before "Even More Controls and Details". If you have a lot of commands like that, you could probably even do it just once and include your mergeParams override/local scope definition between the import and dispatch.

kaushalmodi commented 5 years ago

@c-blake Thanks for the mergeParams suggestion.

I haven't thoroughly tested, but looks like this works!

diff --git a/src/ntangle.nim b/src/ntangle.nim
index e571f99..3ded605 100644
--- a/src/ntangle.nim
+++ b/src/ntangle.nim
@@ -553,14 +553,17 @@ when isMainModule:
   import cligen
   const
     url = "https://github.com/OrgTangle/ntangle"
-  dispatchGen(ntangle
-              , usage = "\nNAME\n  ntangle - $doc\n" &
-                "USAGE\n  $command $args\n\n" &
-                "OPTIONS\n$options\n" &
-                "URL\n  " & url & "\n"
-              , help = { "version": "write the version to stdout" }
+
+  # https://github.com/c-blake/cligen/issues/83#issuecomment-444951772
+  proc mergeParams(cmdNames: seq[string], cmdLine=commandLineParams()): seq[string] =
+    result = cmdLine
+    if cmdLine.len == 0:
+      result.add("--help")
+
+  dispatch(ntangle
+           , usage = "\nNAME\n  ntangle - $doc\n" &
+             "USAGE\n  $command $args\n\n" &
+             "OPTIONS\n$options\n" &
+             "URL\n  " & url & "\n"
+           , help = { "version": "write the version to stdout" }
   )
-  if paramCount()==0:
-    quit(dispatch_ntangle(@["--help"]))
-  else:
-    quit(dispatch_ntangle(commandLineParams()))
c-blake commented 5 years ago

Looks good to me. I had been thinking of the even simpler:

proc mergeParams(cmdNames: seq[string], cmdLine=commandLineParams()): seq[string] =
  result = if cmdLine.len == 0: @[ "--help" ] else: cmdLine
c-blake commented 5 years ago

Sorry for the hassle, Kaushal. People keep requesting all these new features and some have slightly breaking changes like this. So, now cligen is basically a seq[string] from anywhere via mergeParams -> either partially parsed seq[ClParse] converter and/or seq[string] -> dispatch operation. I have tried to keep the simple usage simple or maybe make it even simpler, though.

kaushalmodi commented 5 years ago

Sorry for the hassle, Kaushal.

No worries. I am completely fine with breaking changes. As I want to be on the top of the things, I just set up weekly Travis crons ( https://travis-ci.org/OrgTangle/ntangle/builds ). It's using this that I became aware of this breaking change.

No problem as long as an equivalent (and even better way in this case) is available :)

Keep up the good work! đź‘Ť

c-blake commented 5 years ago

Cool. Thanks.