docopt.nim
docopt.nim copied to clipboard
If an argument is missing, it's value is "nil" (a string), not nil (the real nil).
I have an isNil
check in my code that used to work with the older version. Now it breaks because isNil
is false due to the value being "nil," not nil
.
Please clarify (give an example that fails).
Consider the following simple example:
import docopt
const doc = """
Foo.
Usage:
doco do [--param=<some-param>]
doco (-h | --help)
doco --version
Options:
-h --help Show this screen.
-v --version Show version.
-p --param=<some-param> Some param without default value.
"""
let args = docopt(doc, version = "0.1.0")
if args["do"]:
let param = $args["--param"] # expected to be nil if not passed
echo param.isNil
echo param == "nil"
Compile and run it:
$ doco do
false
true
$ doco do -p foo
false
false
As you can see, if --param
is not provided, its value is "nil" the string, not nil the default string value.
You are converting the value to string using $
and then wondering why it's a string?
Terribly sorry. What a stupid mistake...
@BlaXpirit Still, it's a bit weird that $ applied to vkNone
value produces a non-empty string, don't you think? nil
is a valid value for string type, and it feels like a good reflection of vkNone
.
I'm asking for two reasons:
- it used to work this way; isNil did return true in this situation
- in order to check if a param was passed, I have to check if its kind is
vkNone
, which means I have to import docopt whenever I need to perform such a check.
I am sure that applying $
to a Value
never returned nil
and I don't think this is a good idea, because generally $
always returns a string.
Nim's shenanigans with imports and availability of methods is a whole another topic...
I'm sorry, it seems like I am incorrect, and $nil
returns actual nil
in Nim.
@BlaXpirit So, do you too think that $ applied to vkNone should return nil? IMHO it makes perfect sense.
@BlaXpirit
generally $ always returns a string.
There's no contradiction with my proposal. nil
is a string.
Here's another example of what looks like a problem. The following script:
let doc = """
A test program
Usage:
test [CONFIG]
Options:
CONFIG Path to configuration file
"""
import strutils
import docopt
let args = docopt(doc, version = "Test 0.1.0")
echo args
let no_config = ($args["CONFIG"]).isNil
echo no_config
Compiles without errors on Nim 0.16.0 (Ubuntu 16.04, x86_64).
When the compiled program is run with no arguments:
$ ./test
{CONFIG: nil}
false
When run with an argument:
$ ./test foo
{CONFIG: foo}
false
When run with the argument nil
(a string which just happens to be nil
):
$ ./test nil
{CONFIG: nil}
false
So how do we test for args["CONFIG"]
being nil, as distinct from the string "nil"
?
You could sort this out by providing a proc isNil*(v: Value): bool
which returns false
except for kinds vkStr
and vkList
, and returns true
for those kinds only when the corresponding field is actually nil
.