-
- Notifications
You must be signed in to change notification settings - Fork 95
Refactor repeatable+unique args and flag args #504
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
Conversation
…es in the input elements
| @pcrockett - please see the updated description of this PR, and review if you can. |
| did a quick glance, looks good so far. i'll be interested in testing it a bit. i've never personally used subcommands -- i suppose it's not a problem if a "parent" command defines a flag with the same name as the "child" command... lumping them all into the same arg makes sense to me in any case. |
It might be, if both are repeatable and unique and with the same name... The implementation is at the top edge of complexity I am willing to introduce for this fix, so if there are ways to simply it, I would love that, but if fixing this edge-of-the-edge case complicates it, I would avoid it. Thinking about it more, I don't see this as an issue. Test bashly.yml name: cli flags: - long: --file arg: path repeatable: true unique: true commands: - name: download flags: - long: --file arg: path repeatable: true unique: truevalid command line: output: |
pcrockett left a comment
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.
i checked out the code and tested it on my machine, looked at the resulting bash diff.
looks great. only two comments are entirely nitpicky, feel free to ignore.
| > elif [[ ! "${args['{{ arg.name }}']}" =~ \"$1\" ]]; then | ||
| > args['{{ arg.name }}']="${args[{{ arg.name }}]} \"$1\"" | ||
| > elif [[ -z "${unique_lookup["{{ arg.name }}:$escaped"]:-}" ]]; then | ||
| > args['{{ arg.name }}']="${args[{{ arg.name }}]} $escaped" |
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.
not an important detail, just a nitpicky inconsistency: single quotes on the left, no single quotes on the right.
| > args['{{ arg.name }}']="${args[{{ arg.name }}]} $escaped" | |
| > args['{{ arg.name }}']="${args['{{ arg.name }}']} $escaped" |
same issue on line 22 below this
| > escaped="$(printf '%q' "$1")" | ||
| > {{ condition }} [[ -z ${args['{{ arg.name }}']+x} ]]; then | ||
| if arg.repeatable | ||
| > args['{{ arg.name }}']="\"$1\"" | ||
| > args['{{ arg.name }}']="$escaped" | ||
| if arg.unique | ||
| > unique_lookup["{{ arg.name }}:$escaped"]=1 | ||
| end | ||
| > shift | ||
| if arg.unique | ||
| > elif [[ ! "${args['{{ arg.name }}']}" =~ \"$1\" ]]; then | ||
| > args['{{ arg.name }}']="${args[{{ arg.name }}]} \"$1\"" | ||
| > elif [[ -z "${unique_lookup["{{ arg.name }}:$escaped"]:-}" ]]; then | ||
| > args['{{ arg.name }}']="${args[{{ arg.name }}]} $escaped" | ||
| > unique_lookup["{{ arg.name }}:$escaped"]=1 | ||
| > shift | ||
| > else | ||
| > shift | ||
| else | ||
| > else | ||
| > args['{{ arg.name }}']="${args[{{ arg.name }}]} \"$1\"" | ||
| > args['{{ arg.name }}']="${args[{{ arg.name }}]} $escaped" | ||
| > shift | ||
| end |
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.
i notice this section of code produces something like:
escaped="$(printf '%q' "$1")" if [[ -z ${args['term']+x} ]]; then args['term']="$escaped" unique_lookup["term:$escaped"]=1 shift elif [[ -z "${unique_lookup["term:$escaped"]:-}" ]]; then args['term']="${args[term]} $escaped" unique_lookup["term:$escaped"]=1 shift else shift fidunno if it would be more complex, or less, to simplify the logic a bit:
escaped="$(printf '%q' "$1")" if [[ -z ${args['term']+x} ]]; then args['term']="$escaped" unique_lookup["term:$escaped"]=1 elif [[ -z "${unique_lookup["term:$escaped"]:-}" ]]; then args['term']="${args[term]} $escaped" unique_lookup["term:$escaped"]=1 fi shiftThere 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.
Thanks.
I am updating both your comments.
In regards to the last comment, there was also another issue when there were more than one args defined. The assignment of escaped="$(printf '%q' "$1")" appeared more than once, and not in the correct place.
This YAML demonstrated it.
name: cli args: - name: path - name: term repeatable: true unique: trueBugged
*) # :command.parse_requirements_case # :command.parse_requirements_case_repeatable escaped="$(printf '%q' "$1")" if [[ -z ${args['path']+x} ]]; then args['path']=$1 shift escaped="$(printf '%q' "$1")" elif [[ -z ${args['term']+x} ]]; then args['term']="$escaped" unique_lookup["term:$escaped"]=1 shift elif [[ -z "${unique_lookup["term:$escaped"]:-}" ]]; then args['term']="${args[term]} $escaped" unique_lookup["term:$escaped"]=1 shift else shift fi ;;Fixed
*) # :command.parse_requirements_case # :command.parse_requirements_case_repeatable escaped="$(printf '%q' "$1")" if [[ -z ${args['path']+x} ]]; then args['path']="$1" elif [[ -z ${args['term']+x} ]]; then args['term']="$escaped" unique_lookup["term:$escaped"]=1 elif [[ -z "${unique_lookup["term:$escaped"]:-}" ]]; then args['term']="${args['term']} $escaped" unique_lookup["term:$escaped"]=1 fi shift ;;| Oo, good catch. Surprised a test didn't catch it. Worth adding to the test suite? |
The code it generates is valid, so no way to catch it failing (but maybe I can catch it failing the Are we ready to merge? |
| Oh, right. Just escaping wouldn't affect global state... Yes. Merge that sucker. |
Closes #503
This PR changes how repeatable unique args and flag args are handled. The following changes were made:
Changes in
CommandmodelCommand#deep_commandsnow accepts the optional keyword arginclude_self. If provided,selfwill be prepended to the resulting array. This is needed for the newCommand#has_unique_args_or_flags?method.Command#has_unique_args_or_flags?which returns true if the command, or any child command has even one flag or flag arg defined asunique. This is needed for the conditional insertion of an array declaration in therun()function.Changes in the generated bash script
run()function will now define an additional associative array,unique_lookup, which is used as a tool for validating uniqueness. This is internal only, and users should not concern themselves with this array.unique_lkookuparray. The key will contain the arg/flag name and its value - for example:--file:path/to/file.escaped="$(printf '%q' "$1")"."a" "b c"it will bea b\ c. This is still compatible with theevalway of converting it back to array, but if anyone has used this string as is, it might break.