I try to use the bash complete builtin to show different options for a command.
I have problems when an option contains a path like in -F/dev/null
.
Currently I'm using
#!/bin/bash
_xyz-completion ()
{
local cur
COMPREPLY=() # Array variable storing the possible completions.
cur=${COMP_WORDS[COMP_CWORD]}
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "-oOption1 -F/dev/null" -- $cur ) )
;;
esac
return 0
}
complete -F _xyz-completion -o filenames xyz
If -F
was already typed, then a Tab completes it successfully.
But if only -
was typed, then a Tab shows
null -oOption1
But I expect to see
-F/dev/null -oOption1
I tried already -F\/dev\/null
, -F//dev//null
, "-F/dev/null"
and -F\\\/dev\\\/null
It seems to be only a display problem, as the completion itself works as expected.
To comment the comments:
1)
Never mind, it's a problem also if -F is replaced by a non-option such as -Q. – Benjamin W.
It's not a problem, that the -F
looks like a option for complete
itself, as it even fails if I changed it to xOPTION1 xF/dev/null
2)
I'm wondering what compgen -W "-oOption1 -F/dev/null" -- - displays for you.
It displays (as expected)
-oOption1
-F/dev/null
As mentioned, -F
completes successfully to -F/dev/null
If you remove the -o filenames
option from complete
your example works as expected. Which makes some sense as the completions aren't filenames. This is with bash version 5.0.2(1).
So:
#!/bin/bash
_xyz-completion ()
{
local cur
COMPREPLY=() # Array variable storing the possible completions.
cur=${COMP_WORDS[COMP_CWORD]}
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "-oOption1 -F/dev/null" -- $cur ) )
;;
esac
return 0
}
complete -F _xyz-completion xyz
It definitely seems like a bug that it would truncate part of the completion when there are slashes. And only when displaying the choices, the actual completion works correctly.
EDIT:
After looking into it a little more, the filenames
option is used for escaping strings that could have spaces or other breaking characters. Basically cleaning up file names for the shell. From the Programmable Completion Built-in man page
-o filenames
:
Tell Readline that the compspec generates filenames, so it can perform any filename-specific processing (like adding a slash to directory names, quoting special characters, or suppressing trailing spaces). This option is intended to be used with shell functions specified with -F.
Apparently that includes stripping everything before and including the last slash.
EDIT2:
Here's a comment from the readline source that bash uses for file name completion. I got this from the bash repo at https://git.savannah.gnu.org/git/bash.git). The master, so 5.0 patch 3 at time of writing.
./lib/readline/complete.c line 697
/* Return the portion of PATHNAME that should be output when listing
possible completions. If we are hacking filename completion, we
are only interested in the basename, the portion following the
final slash. Otherwise, we return what we were passed. Since
printing empty strings is not very informative, if we're doing
filename completion, and the basename is the empty string, we look
for the previous slash and return the portion following that. If
there's no previous slash, we just return what we were passed. */
static char *
printable_part (char *pathname)
For filename completion, it only wants to print the basename, everything after the last slash.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With