I am currently working on a shell script I called makeyourself.sh
(linked to /usr/bin/mys
) which automatically installs a debian package from source (via apt-get source -b $1
).
So I decided to add an autocomplete function for the package name which is given as the first parameter: sudo mys panth<tab><tab>
should then list every package beginning with panth
— my try was as follows:
complete -C "apt-cache --no-generate pkgnames" mys
But it does not seem to work: when I press the tab key as mentioned above, at changes the parameter to mys
, which returns me sudo mys mys
.
What am I doing wrong? Do I have to specify the location in the command where complete
has to insert the string which shall be completed, like {}
or $1
?
I use ElementaryOS, a Linux distribution based on Ubuntu. The script is a standard *.sh shell script which uses the standard #!/bin/bash
Best Answer
As you suspect, the command receives some information about what to complete. This is documented in the manual, but not in the documentation of the
complete
builtin, you need to read the introductory section on programmable completion.So the command is called with three parameters:
The same parameters are passed to completion functions (
complete -F somefunction
). Note that whether you use a function or a command, it is your job to filter desired matches.With what you tried, the command that ends up being executed is
apt-cache --no-generate pkgnames mys '' mys
. This prints a list of package names that start withmys
(apt-cache pkgnames
only looks at the first operand). The longest common prefix ismys
, so bash starts completingmys
and expects you to select the next letter.Given that the arguments are appended to the command (not passed as positional parameters — the argument to
-C
is parsed as a shell command), there is no easy way to parse them. The simplest solution is to use a wrapper function.