Allow checking whether optionals provided explicitly#187
Allow checking whether optionals provided explicitly#187matejak merged 4 commits intomatejak:masterfrom
Conversation
|
Posting this PR to get some feedback, it's why I haven't written any tests. Let me know if this is a better way to implement this. I think this feature is really useful. |
|
Very interesting, would you mind adding tests? You basically have to modify e.g. https://github.com/matejak/argbash/blob/master/tests/regressiontests/test-simple.m4, adding an option that would print Also, could you give a shot to documenting this in https://github.com/matejak/argbash/blob/master/doc/guide.rst#using-parsing-results? |
@matejak I have added two tests. The initial implementation would fail on
In addition to that, I've changed all instances of /bin/bash to /usr/bin/env bash (or env -S bash -e for the cases where it was bash -e). This is because on my system I do not have a /bin/bash, /usr/bin/env bash is supposed to support more systems. See https://askubuntu.com/questions/1402718/is-the-same-usr-bin-env-bash-than-bin-bash Let me know if you want to include those two extra commits or not, I can remove them if necessary. Short documentation string also added. |
fc899f3 to
5a06fe6
Compare
|
Great, tests have revealed the problem with non-bash shells that don't have arrays. What about an alternative approach that would use e.g. |
|
FTR, this PR fixes: #185 |
This sounds like a good idea but can lead to collisions. I've pushed a commit that uses |
8f91b27 to
ede3635
Compare
|
Fixed the shellcheck error in the test. |
There was a problem hiding this comment.
Thanks, I see two minor issues that need addressing for the time being.
Generally, I like your solution very much.
I will help you with tests, so please bear with me for a couple of days.
Finally, please add yourself to AUTHORS file, respecting the alphabetical ordering :-)
tests/regressiontests/Makefile
Outdated
| ERROR="require exactly 1" $(REVERSE) $< | ||
| $< pos -o 'uf ta' | grep -q 'OPT_S=uf ta,POS_S=pos,' | ||
| test -z "$(SHELLCHECK)" || $(SHELLCHECK) "$(TESTDIR)/test-simple.sh" | ||
| test-simple: $(TESTDIR)/test-simple.sh |
There was a problem hiding this comment.
Note to self - I have to refresh my memory how the test definitions work, this feels as unnecessary copy-pasting.
matejak
left a comment
There was a problem hiding this comment.
Great, I have pointed out a test optimization path for the script and also for the Makefile.
I have been thinking about this feature in general, and I came to a conclusion that the feature should be optional, because the target group is small, and having this on by default would generate larger parsing code for everybody.
There is a precedent for that - the ARG_POSITIONAL_DOUBLEDASH or ARGBASH_SET_DELIM allow you to set properties of the parsing code in a script-centric (not generator-centric) way.
It's not a big deal and I can help you with that - it is matter of defining a macro, and instead of having the literal assignment to the _supplied_... variable, invoke that macro that will either assign stuff, or won't do anything.
Do you have any thoughts on this or on the name of the macro?
I'm not sure on this compromise, but I agree that this feature may add a lot of ultimately unused lines. Even if we add an One alternative is to tag an optional argument so we can choose which optionals to record. For instance, making another ARG: Alternatively, the "set supplied" flag can be added to the argument list for ARG_*, but since our arguments to
Not to mention that we must then provide all preceding optionals to make supplied work. What about a separate @matejak what are your thoughts on this? Would this be easy to implement with m4? |
|
Thank you for your points! |
9634ccd to
6af4f26
Compare
|
@matejak |
|
Would it be preferable to have |
|
Thinking of squashing commit Default-initialize supplied_arg=0 for ARGBASH_INDICATE_SUPPLIED into the previous one, but leaving it as a separate commit for now to see if the solution is acceptable. |
|
Great, I like it very much. I have a couple of suggestions, but they are related to code style rather than to behavior. I find your PR really impressive regarding the complexity of the language the project is written in. That's amazing! Were you able to get meaningful help from an AI, or was it all your doing? |
I did run make check from resources for each build. These are OK locally, so not sure why CI fails. Does it use conditional tests based on what's installed on the system perhaps? I only see CI complain about Only had an AI chatbot explain to me m4sugar, other than that the biggest hurdle was figuring out the build system (why invoke make from resources? It's not intuitive, a root-dir makefile makes more sense to me) and wrapping it in a |
cb3a2bf to
e462db6
Compare
|
Added a commit that fails when we use |
I have added some pointers toward unittests, and you can also add tests that are supposed to fail generation like here: A gentest testing e.g. infinitely many arguments that are not supported in Dash uses gen-test-infinity.m4 under the hood as the file that shouldn't compile by argbash with posix output. One more thing before the merge - could you rebase the PR against the current master branch? There are some commits showing up that are already merged. |
a839fae to
154be12
Compare
Since boolean optionals default to "off" we have no way to
check if a boolean optional was actually specified on the command line.
The ability to check if a boolean optional has been given is useful in
cases where we source values from a configuration file where we want any
explicitly given arguments to override the configuration.
An example that mostly works is (for plain optionals with an empty default):
test -f ~/.standard-values-for-this-script && source "$_"
MYOPT="${MYOPT:-$_arg_myopt}"
... # Code using MYOPT
This works since optionals can default to an empty string. We still are
not entirely sure if the optional was actually passed here, but it tends
to be "good enough" in most cases.
In the case where `myopt` is boolean, the above case would always use
"off" if the argument was not specified, thus overriding the sourced
configuration file.
This patch introduces `_supplied_<argname>`, a value that gets set to 1
if an argument is supplied for that option, otherwise it's set to 0.
This must be enabled on a per-argument basis by declaring:
ARGBASH_INDICATE_SUPPLIED([long arg name])
Where `long arg name` matches the argument name for any
`ARG_OPTIONAL_*`.
This allows us to do the following:
test -f ~/.standard-values-for-this-script && source "$_"
if [ "$_supplied_arg_myopt" = 1 ]; then
MYOPT="$_arg_myopt" # We override
fi
... # Code using MYOPT
|
I've changed the logic for the subset checking and decoupled the fatal so the unittest can test the subset logic. Additionally, we now also do not allow optional incr, repeated, and action to be tagged as ARGBASH_INDICATE_SUPPLIED; it makes no sense to do so, since we already have the information needed to figure out if an argument was supplied. |
matejak
left a comment
There was a problem hiding this comment.
Well done, thank you for your heroic effort!
Allow checking whether optionals provided explicitly
Since boolean optionals default to "off" we have no way to
check if a boolean optional was actually specified on the command line.
The ability to check if a boolean optional has been given is useful in
cases where we source values from a configuration file where we want any
explicitly given arguments to override the configuration.
An example that mostly works is (for plain optionals with an empty default):
This works since optionals can default to an empty string. We still are
not entirely sure if the optional was actually passed here, but it tends
to be "good enough" in most cases.
In the case where
myoptis boolean, the above case would always use"off" if the argument was not specified, thus overriding the sourced
configuration file.
This patch introduces
_supplied_<argname>, a value that gets set to 1if an argument is supplied for that option, otherwise it's set to 0.
This must be enabled on a per-argument basis by declaring:
Where
long arg namematches the argument name for anyARG_OPTIONAL_*.This allows us to do the following: