@@ -2206,6 +2206,30 @@ _known_hosts_real()
22062206complete -F _known_hosts traceroute traceroute6 \
22072207 fping fping6 telnet rsh rlogin ftp dig drill mtr ssh-installkeys showmount
22082208
2209+ # Convert the word index in `words` to the index in `COMP_WORDS`.
2210+ # @param $1 Index in the array WORDS.
2211+ # @var[in,opt] words Words that contain reassmbled words.
2212+ # @var[in,opt] cword Current word index in WORDS.
2213+ # WORDS and CWORD, if any, are expected to be created by
2214+ # _comp__reassemble_words.
2215+ #
2216+ _comp__find_original_word ()
2217+ {
2218+ ret=$1
2219+
2220+ # If CWORD or WORDS are undefined, we return the first argument without any
2221+ # processing.
2222+ [[ -v cword && -v words ]] || return 0
2223+
2224+ local reassembled_offset=$1 i=0 j
2225+ for (( j = 0 ; j < reassembled_offset; j++ )) ; do
2226+ local word=${words[j]}
2227+ while [[ $word && i -lt ${# COMP_WORDS[@]} && $word == * " ${COMP_WORDS[i]} " * ]]; do
2228+ word=${word#* " ${COMP_WORDS[i++]} " }
2229+ done
2230+ done
2231+ ret=$i
2232+ }
22092233# A meta-command completion function for commands like sudo(8), which need to
22102234# first complete on a command, then complete according to that command's own
22112235# completion definition.
@@ -2215,6 +2239,11 @@ _comp_command_offset()
22152239 # rewrite current completion context before invoking
22162240 # actual command completion
22172241
2242+ # obtain the word index in COMP_WORDS
2243+ local ret
2244+ _comp__find_original_word " $1 "
2245+ local word_offset=$ret
2246+
22182247 # make changes to COMP_* local. Note that bash-4.3..5.0 have a
22192248 # bug that `local -a arr=("${arr[@]}")` fails. We instead first
22202249 # assign the values of `COMP_WORDS` to another array `comp_words`.
@@ -2224,7 +2253,7 @@ _comp_command_offset()
22242253
22252254 # find new first word position, then
22262255 # rewrite COMP_LINE and adjust COMP_POINT
2227- local word_offset= $1 i tail
2256+ local i tail
22282257 for (( i = 0 ; i < word_offset; i++ )) ; do
22292258 tail=${COMP_LINE#* " ${COMP_WORDS[i]} " }
22302259 (( COMP_POINT -= ${# COMP_LINE} - ${# tail} ))
@@ -2244,7 +2273,6 @@ _comp_command_offset()
22442273 compopt -o filenames
22452274 _comp_compgen COMPREPLY -d -c -- " $cur "
22462275 else
2247- local ret
22482276 _comp_dequote " ${COMP_WORDS[0]} " || ret=${COMP_WORDS[0]}
22492277 local cmd=$ret compcmd=$ret
22502278 local cspec=$( complete -p " $cmd " 2> /dev/null)
@@ -2325,6 +2353,12 @@ _comp_command_offset()
23252353#
23262354_comp_command ()
23272355{
2356+ # We unset the shell variable `words` locally to tell
2357+ # `_comp_command_offset` that the index is intended to be that in
2358+ # `COMP_WORDS` instead of `words`.
2359+ local words
2360+ unset -v words
2361+
23282362 local offset i
23292363
23302364 # find actual offset, as position of the first non-option
0 commit comments