bash-completion icon indicating copy to clipboard operation
bash-completion copied to clipboard

[RFC] Reset state of hostcomplete shopt after local unset

Open inconstante opened this issue 6 years ago • 1 comments

The patch message describes the problem that I want to fix... However, the fix, as I implemented it, causes a regression in the unit test for the _variables function.

Before this patch, completing an array reference when the array index contained the @ character worked properly:

$ declare -A assoc1=([idx]=1)
$ : ${assoc1[@<TAB>
$ : ${assoc1[@] <CURSOR>

After this patch, completion is broken:

$ declare -A assoc1=([idx]=1)
$ : ${assoc1[@<TAB>
$ : ${assoc1[${assoc1[@]} <CURSOR>

Initially, I though that the _variables function only worked if the hostcomplete shopt was unset, so I tried to unset it inside the function (see diff below), however, that didn't help, at all.

Then, I learned about the __ltrim_colon_completions function, which sounded like it would remove the duplication... However, running the completion with set -x produces exactly the same output before and after these patches.

Does anybody know how to fix this?

--- a/bash_completion
+++ b/bash_completion
@@ -610,6 +610,8 @@ _split_longopt()
 #          False (> 0) if not.
 _variables()
 {
+    local shopt_reset=$( shopt -p hostcomplete )
+    $( shopt -u hostcomplete )
     if [[ $cur =~ ^(\$(\{[!#]?)?)([A-Za-z0-9_]*)$ ]]; then
         # Completing $var / ${var / ${!var / ${#var
         if [[ $cur == \${* ]]; then
@@ -628,6 +630,7 @@ _variables()
             # Complete $var with $variable
             COMPREPLY+=( $( compgen -A variable -P '$' -- "${BASH_REMATCH[3]}" ) )
         fi
+        $( eval ${shopt_reset} )
         return 0
     elif [[ $cur =~ ^(\$\{[#!]?)([A-Za-z0-9_]*)\[([^]]*)$ ]]; then
         # Complete ${array[i with ${array[idx]}
@@ -639,11 +642,13 @@ _variables()
             COMPREPLY+=( "${BASH_REMATCH[1]}${BASH_REMATCH[2]}[${BASH_REMATCH[3]}]}" )
         fi
         __ltrim_colon_completions "$cur"    # array indexes may have colons
+        $( eval ${shopt_reset} )
         return 0
     elif [[ $cur =~ ^\$\{[#!]?[A-Za-z0-9_]*\[.*\]$ ]]; then
         # Complete ${array[idx] with ${array[idx]}
         COMPREPLY+=( "$cur}" )
         __ltrim_colon_completions "$cur"
+        $( eval ${shopt_reset} )
         return 0
     else
         case $prev in
@@ -660,10 +665,12 @@ _variables()
                     fi
                     COMPREPLY[i]=${COMPREPLY[i]#/usr/share/zoneinfo/}
                 done
+                $( eval ${shopt_reset} )
                 return 0
                 ;;
         esac
     fi
+    $( eval ${shopt_reset} )
     return 1
 }

inconstante avatar Nov 29 '18 01:11 inconstante

There's also a nice deduplicated trap recipe in https://github.com/scop/bash-completion/issues/44#issuecomment-291136367 that could be adapted to automatically reset shopt as well at return.

scop avatar May 22 '20 05:05 scop