I'm trying to implement bash completion for filenames where the list of names is retrieved by another program (e.g. pulled via the network). I've got it almost working, but the automatic escaping is causing me some problems. The code below is the simplest recreation of the issue I can muster:
#!/bin/bash
_myscript()
{
local IFS=$'
'
# Debugging:
#echo
#echo "./myscript $COMP_CWORD ${COMP_WORDS[@]}"
COMPREPLY=( $(./myscript $COMP_CWORD ${COMP_WORDS[@]})
}
complete -o filenames -F _myscript myscript
Where the program that can actually retrieve the filenames is simulated by this script with the filename myscript
:
#!/bin/bash
index=$(( $1 + 2 ))
cat matches.txt | fgrep "${!index}"
The matches.txt
file referenced above is:
abc
def
ghi=jkl
mnl opq
So it properly tab completes everything if you only type the first few characters, producing the escaping that I would like:
./myscript 1 ./myscript gh<TAB> -> ... ghi\=jkl
./myscript 1 ./myscript mn<TAB> -> ... mnl\ opq
The issue is when tabbing after the equals or space, where it fails to complete:
./myscript 1 ./myscript ghi\=j<TAB> (no change)
./myscript 1 ./myscript mnl\ o<TAB> (no change)
Using the debugging it seems to be sending the following command to myscript (quotes added by me to indicate grouping only because it doesn't show up in the echo statement):
./myscript 1 ./myscript 'ghi\=j'
./myscript 1 ./myscript 'mnl\ o'
Which means my fgrep is searching for a filename that actually includes the escape character. It's taken a while to get to this point but the real question is this:
Why is it giving me an escaped version of the text I'm tab completing? When I eventually press the enter button, the escapes are going to be interpreted by bash and myscript
won't receive them. So there seems to be a difference between what I'm receiving for tab completion and what I'm receiving when the user actually presses enter.
I don't really understand why $COMP_WORDS
is being set with a version containing the escapes, when my understanding is that the array is what separates the arguments so it seems as though the escaping is unnecessary. Is there a useful function that safely removes these escapes or is my entire approach just wrong?