From 58d5176cba8bb25fe5348aadef100c083afa992f Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Sun, 31 Dec 2023 21:31:46 +0900 Subject: [PATCH 1/7] fix(aspell): use `_comp_expand_glob` against unexpected splitting --- completions/aspell | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/completions/aspell b/completions/aspell index 6b39b165338..89dae17a650 100644 --- a/completions/aspell +++ b/completions/aspell @@ -5,8 +5,7 @@ _comp_cmd_aspell__dictionary() local datadir aspell=$1 datadir=$("$aspell" config data-dir 2>/dev/null || echo /usr/lib/aspell) # First, get aliases (dicts dump does not list them) - COMPREPLY=($datadir/*.alias) - if ((${#COMPREPLY[@]})); then + if _comp_expand_glob COMPREPLY '"$datadir"/*.alias'; then COMPREPLY=("${COMPREPLY[@]%.alias}") COMPREPLY=("${COMPREPLY[@]#$datadir/}") fi From 44c1d1292fdb840640a848aab6b2827002477ee9 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Mon, 1 Jan 2024 10:39:43 +0900 Subject: [PATCH 2/7] fix(wtf): quote array assignment --- completions/wtf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/completions/wtf b/completions/wtf index 155185e30d9..c565c56672b 100644 --- a/completions/wtf +++ b/completions/wtf @@ -9,7 +9,7 @@ _comp_cmd_wtf() [[ $prev == -f ]] && _comp_compgen_filedir && return [[ ${words[*]} == *\ -f* ]] && addf= || addf=-f if [[ $cur == -* ]]; then - COMPREPLY=($addf) + COMPREPLY=(${addf:+"$addf"}) return fi From 73c5292b7a39a2f3d1ae01057e0afd3aa24c8a32 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Sun, 31 Dec 2023 23:23:11 +0900 Subject: [PATCH 3/7] refactor(gdb): use `_comp_compgen_split` to split PATH --- completions/gdb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/completions/gdb b/completions/gdb index f9d4f833299..96e9dafb3c4 100644 --- a/completions/gdb +++ b/completions/gdb @@ -25,10 +25,8 @@ _comp_cmd_gdb() # otherwise compgen -c contains Bash's built-in commands, # functions and aliases. Thus we need to retrieve the program # names manually. - IFS=":" - local path_array=($( - command sed -e 's/:\{2,\}/:/g' -e 's/^://' -e 's/:$//' <<<"$PATH" - )) + local path_array + _comp_compgen -Rv path_array split -X '' -- "$PATH" _comp_compgen_split -o plusdirs -- "$( find ${path_array[@]+"${path_array[@]}"} . -mindepth 1 \ -maxdepth 1 -not -type d -executable -printf '%f\n' \ From 346fcd46e609b7dea6c7e2ea41fa1a336d49d2ff Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Mon, 1 Jan 2024 06:06:54 +0900 Subject: [PATCH 4/7] refactor(java): refactor `_comp_cmd_java__classes` using `_comp_split` --- completions/java | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/completions/java b/completions/java index f8bbb9a864a..8ddcfafc2bc 100644 --- a/completions/java +++ b/completions/java @@ -62,22 +62,23 @@ _comp_cmd_java__classes() _comp_cmd_java__find_classpath local -a classpaths=("${REPLY[@]}") + local -a classes=() # convert package syntax to path syntax local cur=${cur//.//} # parse each classpath element for classes for i in "${classpaths[@]}"; do if [[ $i == *.@(jar|zip) && -r $i ]]; then if type zipinfo &>/dev/null; then - COMPREPLY+=($(zipinfo -1 "$i" "$cur*" 2>/dev/null | - command grep '^[^$]*\.class$')) + _comp_split -a classes "$(zipinfo -1 "$i" "$cur*" 2>/dev/null | + command grep '^[^$]*\.class$')" elif type unzip &>/dev/null; then # Last column, between entries consisting entirely of dashes - COMPREPLY+=($(unzip -lq "$i" "$cur*" 2>/dev/null | + _comp_split -a classes "$(unzip -lq "$i" "$cur*" 2>/dev/null | _comp_awk '$NF ~ /^-+$/ { flag=!flag; next }; - flag && $NF ~ /^[^$]*\.class/ { print $NF }')) + flag && $NF ~ /^[^$]*\.class/ { print $NF }')" elif type jar &>/dev/null; then - COMPREPLY+=($(jar tf "$i" "$cur" | - command grep '^[^$]*\.class$')) + _comp_split -a classes "$(jar tf "$i" "$cur" | + command grep '^[^$]*\.class$')" fi elif [[ -d $i ]]; then @@ -85,8 +86,8 @@ _comp_cmd_java__classes() _comp_compgen -v tmp -c "$i/$cur" -- -d -S . _comp_compgen -av tmp -c "$i/$cur" -- -f -X '!*.class' ((${#tmp[@]})) && - _comp_compgen -a -- -X '*\$*' -W '"${tmp[@]#$i/}"' - [[ ${COMPREPLY-} == *.class ]] || compopt -o nospace + _comp_compgen -av classes -- -X '*\$*' -W '"${tmp[@]#$i/}"' + [[ ${classes-} == *.class ]] || compopt -o nospace # FIXME: if we have foo.class and foo/, the completion # returns "foo/"... how to give precedence to files @@ -94,11 +95,12 @@ _comp_cmd_java__classes() fi done - if ((${#COMPREPLY[@]} != 0)); then + if ((${#classes[@]} != 0)); then # remove class extension - COMPREPLY=("${COMPREPLY[@]%.class}") + classes=("${classes[@]%.class}") # convert path syntax to package syntax - COMPREPLY=("${COMPREPLY[@]//\//.}") + classes=("${classes[@]//\//.}") + _comp_compgen -U classes -- -W '"${classes[@]}"' fi } From 16b9026b6f4ca849bf81afe5b76c11142ae056d4 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Mon, 1 Jan 2024 06:34:20 +0900 Subject: [PATCH 5/7] refactor(mplayer): refactor the modification to COMPREPLY --- completions/mplayer | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/completions/mplayer b/completions/mplayer index aa2bd5a3a75..7ab096a7471 100644 --- a/completions/mplayer +++ b/completions/mplayer @@ -44,14 +44,11 @@ _comp_cmd_mplayer() ;; -vobsub) if _comp_compgen_filedir '@(idx|ifo|sub)'; then - local IFS=$'\n' - COMPREPLY=($(for i in "${COMPREPLY[@]}"; do - if [[ -f $i && -r $i ]]; then - printf '%s\n' "${i%.*}" - else - printf '%s\n' "$i" + for i in "${!COMPREPLY[@]}"; do + if [[ -f ${COMPREPLY[i]} && -r ${COMPREPLY[i]} ]]; then + COMPREPLY[i]=${COMPREPLY[i]%.*} fi - done)) + done fi return ;; From 2ed45ec809e1c8975aeb70fdc0f774c359937ee7 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Mon, 1 Jan 2024 07:51:36 +0900 Subject: [PATCH 6/7] refactor(povray): use `_comp_compgen -- -X` to filter words --- completions/povray | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/completions/povray b/completions/povray index 4a9e3fa7f8c..4b15e5f27c6 100644 --- a/completions/povray +++ b/completions/povray @@ -31,10 +31,7 @@ _comp_cmd_povray() *) oext=$defoext ;; esac # complete filename corresponding to previously specified +I - COMPREPLY=($( - IFS=$'\n' - command grep '^[-+]I' <<<"${words[*]}" - )) + _comp_compgen -Rv COMPREPLY -- -X '![-+]I*' -W '"${words[@]}"' _comp_compgen -Rv COMPREPLY -- -X '' -W '"${COMPREPLY[@]#[-+]I}"' local i for i in "${!COMPREPLY[@]}"; do From cae43e938ef1c12588896981395f18e4e8b544a5 Mon Sep 17 00:00:00 2001 From: Koichi Murase Date: Mon, 1 Jan 2024 07:17:31 +0900 Subject: [PATCH 7/7] refactor(openssl): reduce redundant splitting The current code performs the splitting twice: the output of a command is first split by IFS, second joined by \n while adding the prefix `-`, and then again split by IFS, which is redundant. We may directly split the output by `_comp_compgen_split` while adding the prefix using the `-P` option. --- completions/openssl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/completions/openssl b/completions/openssl index f725c3aafb5..9dad7155f66 100644 --- a/completions/openssl +++ b/completions/openssl @@ -27,14 +27,14 @@ _comp_cmd_openssl__compgen_sections() _comp_cmd_openssl__compgen_digests() { + [[ $cur == -* ]] || return _comp_compgen_split -- "$( "$1" dgst -h 2>&1 | _comp_awk '/^-.*[ \t]to use the .* message digest algorithm/ { print $1 }' - local -a digests=($("$1" help 2>&1 | - command sed -ne '/^Message Digest commands/,/^[[:space:]]*$/p' | - command sed -e 1d)) - printf "%s\n" "${digests[@]/#/-}" )" + _comp_compgen -ac "${cur#-}" split -P "-" -- "$("$1" help 2>&1 | + command sed -ne '/^Message Digest commands/,/^[[:space:]]*$/p' | + command sed -e 1d)" } _comp_cmd_openssl()