Comments (23)
Options are supposed to be optional. ;-) If you are wrapping a valid proc
with all defaulted parameters that can be invoke correctly as foo()
then ./foo
should also work with no arguments. So, I think you'll probably agree the defaults are right here. Conceptually, it sounds like you may have one or more mandatory parameters.
That said, you can do this use dispatchGen
and call the generated dispatcher yourself. E.g.,:
proc foo(a=0, b=5.0) = discard
import cligen, os
dispatchGen(foo)
quit(dispatch_foo(if paramCount() > 0: commandLineParams() else: @[ "--help" ]))
from cligen.
There may be a useful new feature request embedded in this question, though..A kind of "standalone option" which if given means none of the mandatory parameters are actually mandatory (i.e., if one of those is present then the dispatcher acts as if every mandatory parameter had been in ImplicitDefault
).
from cligen.
No, if you have proc yadda(..., blah="", ..)
that should get an empty string default value and be considered optional. The node kind won't be nnkEmpty, but some node for a string literal (which happens to be the empty string).
from cligen.
The short answer is the dispatcher is designed to be called from inside a quit()
.
The long answer has to do with return value behaviors/translation/echoResult
, etc. See the "Exit Code Behavior" section in DETAILS.md
.
Another way to think about it is that, in cligen
s view, a command is a one-shot proc invocation. The Nim compiler would be happy enough if you just did discard dispatch_nistow()
, but then a command-syntax error would not necessarily exit with an error code.
from cligen.
You're welcome. Yeah. Just string literals for now. Identifiers in the macro $
setting just get their name lifted. I'll let you know if I figure out a way to get it evaluated..Then things like that fancy staticExec
become possible, or a staticRead
to grab a string out of a file, etc.
from cligen.
Conceptually, it sounds like you may have one or more mandatory parameters.
Right.. am trying to figure out how to make them optional.. having no luck..
I now have:
proc nistow*(version=false, simulate=false, verbose=false, force=false, app: string, dest: string) =
But I want to make nistow -v
work and not have cligen throw this error:
Missing these required parameters:
app
dest
Run command with -h for more details.
from cligen.
Well, you have a call with required string params app
and dest
, right? It looks like you are defaulting dest
to getHomeDir()
(in the current git-available version), and you want to error out if app
is not provided. So, what am I missing? Did you want a full help message with missing mandatory parameters? I kinda figured those were most likely typos/misspellings of things/etc and the short message would be ok in this context.
from cligen.
Oh, wait...I see. I looked at your code more carefully. You want -v
to print a version and exit. That is not really supported behavior even with dispatchGen
. You will probably need a wrapper proc to handle that which checks if version_only: write_version(); quit()
. This sort of thing is necessary in most cases where the "one-shot control flow" of the command and API are not really in sync.
from cligen.
Hmm. Even that may not be enough to block the missing mandatory error out. You may have to default those mandatory strings to something like "REQUIRED" yourself and check them in a wrapper proc.
from cligen.
Thanks for giving your time to this discussion. Please bear with me as I am very much inexperienced in Nim.. And so the dumb questions follow..
you have a call with required string params app and dest, right?
Thanks. I reiterated with that proc
signature to finally realize that all arguments are required. Being used to a lisp flavor, is there a way to mark a proc
parameter as optional?
So, what am I missing? Did you want a full help message with missing mandatory parameters?
As you later realize, I am just expecting the proc to evaluate below and quit, and not care if the mandatory args have values.
if version:
writeVersion()
quit()
FYI, I am working in this branch: https://github.com/kaushalmodi/nistow/tree/use-cligen
That is not really supported behavior even with dispatchGen
I have a lot of reading to do to understand what dispatchGen actually does.. I see that it is defined in cligen.nim
. Also I have yet to learn Nim macros.
You may have to default those mandatory strings to something like "REQUIRED" yourself and check them in a wrapper proc.
Yes, that's what finally worked.. I was confused for a long time as to what makes a switch mandatory vs not. I was trying to default the values of those string switches to ""
, but apparently a string arg not being set is the same as being set to ""
in Nim?
There may be a useful new feature request embedded in this question, though..A kind of "standalone option" which if given means none of the mandatory parameters are actually mandatory
That would be great! Thanks!
from cligen.
Ok. I added that feature. Check out test/ImplicitDefault.nim
to see how to use. Basically you just tack on a mandatoryOverrides = @["version"]
. It's starting to get kind of far from the idea that the proc being auto-wrapped is something besides a command, though. A special invocation mode that overrides everything else is not unheard of for an API call, though.
from cligen.
Ok. I added that feature.
Wow! Let me try that out. Thanks!
from cligen.
To answer one question/confusion implicit in your longer reply, Nim will just default uninitialized values to something, depending on the type (unless you use the {.noinit.}
pragma). cligen
decides on whether something is optional or mandatory based on an explicit assignment construct being syntactically present in the proc signature (by whether the [1].kind == nnkEmpty
is true).
from cligen.
by whether the [1].kind == nnkEmpty is true
So that condition is true even when I explicitly set the arg to ""
(empty string)?
from cligen.
No, if you have proc yadda(..., blah="", ..) that should get an empty string default value and be considered optional.
You are right! (kaushalmodi-forks/nistow@dd096a0), may be I am just going crazy..
from cligen.
Basically you just tack on a mandatoryOverrides = @["version"]
Thanks, that works! (kaushalmodi-forks/nistow@e6189ae).
from cligen.
You're welcome. I'm not really so happy with ImplicitDefault
and mandatoryOverride
because they actually create command syntax which would be disallowed as a Nim proc invocation. With a proc invocation, the caller needs to provide non-defaulted parameters. cligen
generates the call and always provides all params. So, Nim is happy. There was kind of a gradual evolution (from suppress
even) of command syntax that is more flexible than the proc call syntax, though I would prefer it not go any further, if possible.
from cligen.
With a proc invocation, the caller needs to provide non-defaulted parameters. cligen generates the call and always provides all params. So, Nim is happy.
Thanks, I am now gradually understanding the role of cligen better.
There was kind of a gradual evolution (from suppress even) of command syntax that is more flexible than the proc call syntax
I have no idea about suppress
, but it's alright, I am learning things as needed :)
And here's the last commit (kaushalmodi-forks/nistow@16f4cc9) where I made the --help
be passed to the dispatch if user passes no switches.
Just one question with that.. Why is the quit
needed? I obviously tried to see what happens, and not surprisingly an error:
... nistow.nim(91, 18) Error: expression 'dispatchnistow(if
... ## "is greater" operator. This is the same as ``y < x``.
... 0 < paramCount(): commandLineParams() else: @["--help"],
... "Stow 0.1.0 (Manage your dotfiles easily)", "${prelude}$command $args\L$doc Options(opt-arg sep :|=|spc):\L$options$sep",
... "", "")' is of type 'int' and has to be discarded; start of expression here: nistow.nim(81, 2)
from cligen.
Hey. I don't know if you are still interested, but I just introduced a better way to handle "--version". See the new test/Version.nim
program for example usage. The new way has the parser-dispatcher do all the work outside the API call. The CLI author provides the name of the long option (e.g. "version" or "Version") and a version string. The API code doesn't need to know anything about cligen
. That is cleaner separation more in keeping with the overall cligen
design.
{ This is more advanced and slightly off topic, but that version string could almost be something "automagic" like staticExec "git log -1 | head -n1"
except currently this fails because Nim evaluates all the macro stuff before the staticExec
. So, for now use a real string like "0.5.0"
. }
from cligen.
@c-blake Thanks! It works! kaushalmodi-forks/nistow@db5e38f.
Though, I tried setting the version to a const and use the const var instead of the string "0.1.0" in that commit, and it printed the identifier as-is i.e. did not evaluate it.
from cligen.
Thanks, btw you need to update the module version in cligen.nimble.
from cligen.
Oops. Thanks. There are definitely too many little things to remember to do when releasing. I should script it all.
from cligen.
I should script it all.
Create a Nim package for that ;-)
Inspiration: https://github.com/goreleaser/goreleaser
from cligen.
Related Issues (20)
- Unhelpful compilation error when "short" param name is given as string HOT 5
- `parseHelps` fails on a single element HOT 6
- FR: Display textual representations of available enum values in the `clValType` column HOT 9
- How do I make global options? HOT 14
- [Bug] nim 1.0.6/1.4.8 doesn't have isNaN/isnan HOT 3
- How to use `--version`? HOT 4
- truncate default args in help menu HOT 5
- Sharing param help messages between commands HOT 2
- Some tiny remarks HOT 1
- Removing entries from a seq results in a non-zero exit HOT 10
- Setting `clCfg.helpSyntax = ""` doesn't prevent inclusion of the syntax into the binary HOT 15
- No error for passing non-static table to `help` or `short` of `dispatch` HOT 1
- No interpolation of const values in a literal passed to `help` or `short` of `dispatch` HOT 9
- [Feature request] Support for std/options HOT 7
- Sync `clCfg.version` with package HOT 3
- turning off prefix completion? HOT 14
- How to bold usage and clCfg.useHdr text from code? HOT 16
- `--help` on the multicommand programs without the command should at least list the available commands HOT 13
- "Bad enum value" response starts to and then doesn't list alternatives to the empty string HOT 2
- `strUt` requires Nim 1.2+ HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cligen.