-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability for users to elide ':' or '=' when CLI authors pass a #7297
Conversation
non-empty partial symbol table. Behavior should be identical to the old behavior if empty partial symbol tables are passed. "Partialness" of the symbol table refers to the fact that one need only specify option keys that are toggles/booleans/do not take arguments, hence the "NoArg" suffixes in shortNoArg and longNoArg. commandLineParams() returns seq[TaintedString], so use that consistently in getopt() and initOptParser(seq[TaintedString]) dropping the taint at the quoting stage just as with the paramStr() logic. Fix capitalization inconsistency of cmdLongOption. Export OptParser.cmd and OptParser.pos so that, at least *in principle*, users of this API can handle "--" option processing termination or some "git-like" sub-command stop word with a separate option sub-syntax. { Eg., ``case p.key of "": echo "trailing non-option args: ", p.cmd[p.pos..^1]`` or ``case p.kind of cmdArgument: if p.key == "mysubcmd": ...``. } Really, searching for the last delimiter before p.pos is probably needed to frame the trailing text..Not the nicest API, but still possible with effort.
There are obviously some judgement call choices in this idea. E.g., one could flip the sense of the partial table to have the CLI author specify which options take args instead of which do not take args. In my experience, programs with many option keys (like, e.g., the nim compiler itself) are about 2/3 option keys with args. So NoArgs is the "smaller" case needing less maintenance. It would not be hard to take either kind of list -- taking and not taking args, or some other parameter determining the logical sense of the tables and so on and so on, but that can get complicated to explain and CLI authors can mispredict which fork is easier for them (e.g., starting off with mostly toggles and evolving to mostly argument-taking). Just fixing on the "special" case of no arguments seemed simple, effective, and maybe on average ~3X easier than the typical full symbol table. |
Also, I am happy to add some material to the documentation comment/changelog.md and assume you would want that, but I figured first I would see if you liked the approach. |
lib/pure/parseopt.nim
Outdated
inShortState: bool | ||
shortNoArg: string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be of type set[char]
. longNoArg
should still be a seq to avoid the dependency I guess. Also @[]
is easier to use.
lib/pure/parseopt.nim
Outdated
@@ -78,11 +80,14 @@ when declared(os.paramCount): | |||
# we cannot provide this for NimRtl creation on Posix, because we can't | |||
# access the command line arguments then! | |||
|
|||
proc initOptParser*(cmdline = ""): OptParser = | |||
proc initOptParser*(cmdline = "", | |||
shortNoArg="", longNoArg: seq[string] = @[]): OptParser = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, shortNoArg
should be set[char]
.
Yes, plus IMO keys with args are to be preferred (--switch:on|off) for flexibility. |
I made the requested changes. Personally, I find string constants easier, but I can see both sides. This is slightly off-topic, but while I have your |
Yeah, probably we should do something like this... |
Well ... if we're serious about Unicode |
IMO we shouldn't overcomplicate |
Well, it's only a fully optional partial symbol table with the only extra work being for boolean/toggle/no-argument option keys. If CLI authors want the old behavior, the defaults give it. If CLI authors want to provide CLI users with more POSIX-style option syntax then this PR enables that, too. Do you really want to force CLI authors wanting to provide more standard/common option syntax to use external to libraries/roll their own? |
The PR seems simple enough and I think |
Ok. Well, I documented the changes for this PR. This should be purely added functionality not a breaking change. Doing the full tokenization first with |
Oh, one thing the documentation reminded me to ask you about is whether you like |
I went ahead and optimistically changed to NoVal and consider this PR good to go unless you really loved the "NoArg" naming. Other possibilities you might like better might be "Bool" or "Toggle" - if you prefer to refer more to the semantics of the option keys than the syntax of their parsing. It is a syntax optionality adjustment, though. The naming doesn't matter much to me, but we probably should not change once it's settled. |
This is a nice improvement but would it be possible to add some additional usage examples? |
@mjoud - fair enough. The theme of the documentation for this module seems to be to keep things pretty terse. I added one for the final An example handling |
lib/pure/parseopt.nim
Outdated
## (as provided by the ``OS`` module) is taken. | ||
## (as provided by the ``OS`` module) is taken. If ``shortNoVal`` is | ||
## provided command users need not delimit short option keys and values | ||
## with a ':' or '='. If ``longNoVal`` is provided command users need not |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is provided command users need not
maybe this can be changed?
This requires a test case, apart from that it's fine. |
Ok. Done. It would be nice someday to re-do the parser to be token-oriented from Also, this is way off-topic, but there is a comment in the code related to POSIX not making |
Ok, but I don't want to make usage of this knowledge. :-) |
Yah...I suspected you would say that. :-) |
…m-lang#7297) * Add ability for users to elide ':' or '=' when CLI authors pass a non-empty partial symbol table. Behavior should be identical to the old behavior if empty partial symbol tables are passed. "Partialness" of the symbol table refers to the fact that one need only specify option keys that are toggles/booleans/do not take arguments, hence the "NoArg" suffixes in shortNoArg and longNoArg. commandLineParams() returns seq[TaintedString], so use that consistently in getopt() and initOptParser(seq[TaintedString]) dropping the taint at the quoting stage just as with the paramStr() logic. Fix capitalization inconsistency of cmdLongOption. Export OptParser.cmd and OptParser.pos so that, at least *in principle*, users of this API can handle "--" option processing termination or some "git-like" sub-command stop word with a separate option sub-syntax. { Eg., ``case p.key of "": echo "trailing non-option args: ", p.cmd[p.pos..^1]`` or ``case p.kind of cmdArgument: if p.key == "mysubcmd": ...``. } Really, searching for the last delimiter before p.pos is probably needed to frame the trailing text..Not the nicest API, but still possible with effort. * Make requested changes from string to seq[char] (see nim-lang#7297) * Document new behavior and elaborate on some special cases. * NoArg => NoVal to be less ambiguous/more clear. * Add more documentation and an example snippet. * Tweak language. Clarify still using ':'/'=' is ok. * Add a test case for new NoVal behavior.
``parseopt`` more token-oriented (see nim-lang/Nim#7297 (comment) ), but hasn't seemed interested in parseopt3 re-write.
non-empty partial symbol table. Behavior should be identical to the
old behavior if empty partial symbol tables are passed. "Partialness"
of the symbol table refers to the fact that one need only specify
option keys that are toggles/booleans/do not take arguments, hence
the "NoArg" suffixes in shortNoArg and longNoArg.
commandLineParams() returns seq[TaintedString], so use that consistently
in getopt() and initOptParser(seq[TaintedString]) dropping the taint at
the quoting stage just as with the paramStr() logic.
Fix capitalization inconsistency of cmdLongOption.
Export OptParser.cmd and OptParser.pos so that, at least in principle,
users of this API can handle "--" option processing termination or some
"git-like" sub-command stop word with a separate option sub-syntax.
{ Eg.,
case p.key of "": echo "trailing non-option args: ", p.cmd[p.pos..^1]
or
case p.kind of cmdArgument: if p.key == "mysubcmd": ...
. } Really,searching for the last delimiter before p.pos is probably needed to frame
the trailing text..Not the nicest API, but still possible with effort.
This is a follow up to https://forum.nim-lang.org/t/3592 where it sounded
like it would be welcome.