fix(_comp_compgen_*): avoid conflicts with "-v var" - #1028
Merged
Conversation
This was referenced Aug 6, 2023
Collaborator
Author
This is an example implementation for this direction. diff --git a/bash_completion b/bash_completion
index 98c67eb0..0799824e 100644
--- a/bash_completion
+++ b/bash_completion
@@ -512,6 +512,7 @@ _comp_compgen()
local _dir=""
local _ifs=$' \t\n' _has_ifs=""
local _icmd="" _xcmd=""
+ local -a _upvars=()
local _old_nocasematch=""
if shopt -q nocasematch; then
@@ -519,7 +520,7 @@ _comp_compgen()
shopt -u nocasematch
fi
local OPTIND=1 OPTARG="" OPTERR=0 _opt
- while getopts ':av:Rc:C:lF:i:x:' _opt "$@"; do
+ while getopts ':av:U:Rc:C:lF:i:x:' _opt "$@"; do
case $_opt in
a) _append=set ;;
v)
@@ -529,6 +530,16 @@ _comp_compgen()
fi
_var=$OPTARG
;;
+ U)
+ if [[ $OPTARG == @(*[^_a-zA-Z0-9]*|[0-9]*|'') ]]; then
+ printf 'bash_completion: %s: -U: invalid variable name `%s'\''\n' "$FUNCNAME" "$OPTARG" >&2
+ return 2
+ else if [[ $OPTARG == @(_*|IFS|OPTIND|OPTARG|OPTERR) ]]; then
+ printf 'bash_completion: %s: -U: `%s'\'' unneccessary to mark upvar\n' "$FUNCNAME" "$OPTARG" >&2
+ return 2
+ fi
+ _upvars+=("$OPTARG")
+ ;;
c) _cur=$OPTARG ;;
R) _cur="" ;;
C)
@@ -573,6 +584,9 @@ _comp_compgen()
if [[ $_has_ifs ]]; then
printf 'bash_completion: %s: `-l'\'' and `-F sep'\'' are not supported for generators\n' "$FUNCNAME" >&2
return 2
+ elif ((${#_upvars[@]})); then
+ printf 'bash_completion: %s: `-U var'\'' is not supported for generator calls\n' "$FUNCNAME" >&2
+ return 2
fi
local -a _generator
@@ -653,6 +664,7 @@ _comp_compgen()
return
}
+ ((${#_upvars[@]})) && _comp_unlocal "${_upvars[@]}"
_comp_split -l ${_append:+-a} "$_var" "$_result"
} |
akinomyoga
force-pushed
the
generator-vars
branch
5 times, most recently
from
August 11, 2023 22:16
f9d23a3 to
cd39f64
Compare
Collaborator
Author
|
I decided to use the approach of the previous reply #1028 (comment). |
akinomyoga
force-pushed
the
generator-vars
branch
from
August 13, 2023 00:02
8c43bcd to
eeadd25
Compare
akinomyoga
force-pushed
the
generator-vars
branch
5 times, most recently
from
August 13, 2023 09:15
8cd81f5 to
bf16bf6
Compare
Collaborator
Author
|
Rebased & resolved conflicts. |
Collaborator
Author
|
Added fixes mentioned in #1026. |
scop
reviewed
Aug 20, 2023
scop
left a comment
Owner
There was a problem hiding this comment.
Slowly getting started with this, got some trivial bits merged out of the way.
shellcheck does not allow using a local scalar variable that has the same variable name as an array variable used in another function (SC2178,SC2179). To use array `options` in another function, we switch `options` in `_known_hosts` to an array variable (or otherwise, we will need to place disable=SC2178,SC2179 to every line using the variable as a scalar).
When `-U var` is specified for a builtin `compgen` call, variable
`var` is unlocalized by `_comp_unlocal` just before storing the result
to the target array. When `-U var` is specified for a generator call,
variable `var` is unlocalized by `_comp_unlocal` just before calling
the generator function `_comp_compgen_G2` (where `G2` is the generator
name)..
A generator should basically define local variables with the names
starting with `_`. However, a generator sometimes needs to use local
variable names that do not start with `_`. When the child generator
call with a variable name (such as `local var; _comp_compgen -v var`)
is used within the generator, the local variable can unexpectedly mask
a local variable of the upper call.
For example, the following call fails to obtain the result of
generator `mygen1` because the array `arr` is masked by the same name
of a local variable in `_comp_compgen_mygen1`.
# generator with a problem
_comp_compgen_mygen1()
{
local -a arr=(1 2 3)
_comp_compgen -av arr -- -W '4 5 6'
_comp_compgen_set "${arr[@]/#p}"
}
_comp_compgen -v arr mygen1 # fails to get the result in array `arr`
To avoid this, a generator that defines a local variable that does not
start with `_` can use the option `-U var` to unlocalize the variable
on assigning the final result.
# properly designed generator
_comp_compgen_mygen1()
{
local -a arr=(1 2 3)
_comp_compgen -av arr -- -W '4 5 6'
_comp_compgen -U arr set "${arr[@]/#p}"
}
akinomyoga
force-pushed
the
generator-vars
branch
from
August 20, 2023 21:10
de5253f to
f2df91d
Compare
Collaborator
Author
|
Rebased. |
scop
approved these changes
Aug 26, 2023
scop
left a comment
Owner
There was a problem hiding this comment.
I think it will take me quite some time to become comfortable with this, but I do see the point and think I even understand some parts of this stuff :) So let's go with this, thanks!
Collaborator
Author
|
Thanks |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
To avoid conflicts between local variables and variable names specified by
_comp_compgen -v var, the local variables basically need to have the name_foo.Handling of conflicts with internal generator calls
When a generator needs to call other generators to store results in a local variable, the local variable name cannot have the name
_foobecause it is rejected by the internal generator calls. In such a case, we first declare the variable without the underscore (e.g.foo), call the internal generator to store the result tofoo, move the results to an underscored variable (_foo), and remove the local variablefooby_comp_unlocal foo. The current version of the PR uses this approach.However, maybe this is too complicated. Another possibility is to add a new option
_comp_compgen -U footo internally perform_comp_unlocal fooimmediately before storing the results.