How to tap into the completion of another command programmatically?
Supposing my current directory has files a1
, a2
, and a3
, then how can I make my command invoke the autocompletion of ls a
to get back a1 a2 a3
?
Is this possible?
Clarification and justification:
I chose ls
because people can relate to it. It is a contrived example that is intentionally simple so that people can understand the question without distractions, but unfortunately such examples sometimes take us on tangents. :)
Let me try to exemplify the value of this feature. I have a command called build
which, given a directory, can autocomplete to the targets that can be built in that directory. Those targets may not correspond to the files from that directory, and so glob completion (* and other wildcard characters) will not work. The targets might be mined by the build
command from a build file that I don't want to be parsing. In other words:
build path/to/dir/
TABTAB
Might give:
path/to/dir/a_target
path/to/dir/b_target
Again, a_target and b_target are not files or directories.
build
is a pre-existing command, not something I can go ahead and modify to suit my purposes. And the manner in which it comes up with the valid completions is something I certainly don't want to know or reinvent.
Now suppose I have an entire repository of build
able projects, and most of my work and therefore most of my build
work happens in only one project. In other words, I always build
targets under my/project/directory
.
So far so good.
I want to write a wrapper around the build command that doesn't require me to feed it the directory path each time I run it. I want it to know my preferred project directory (or directories, why not) and let me reference the targets without qualifying them:
So under the assumption that I have:
my/project/directory/a_target
my/project/directory/b_target
I want this:
mybuild
TABTAB
to give me:
a_target
b_target
Basically I want to decorate and simplify the behavior of build
to suit my particular needs.
I will need to write my own completion code for mybuild
, but I want it to rely on the completion for build
, because I can't ask the developers of build
to code a build listtargets
command just to make me happy. (Although that would be much more robust.) The build
command already has code somewhere that given a prefix can return all the matching targets. It's in the completion for build
, and I need to tap into it.
(Of course, when I run mybuild a_target
, I will make sure that it knows to run build my/project/directory/a_target
. I know how to implement this and it is not in scope for this question.)
I hope this illustrates why I need to tap into the completion of the build
command and invoke it as a black box.
This is a bit of an odd thing to do, and the command you need to execute depends on the number of files in the directory - none, one, or more than one. But this command works for the example case:
echo echo a$'\t'$'\t' | bash -i 2>&1 | head -3 | tail -1
The command being autocompleted is
echo a
so send that as a character stream, followed by two tab characters, into an interactive bash shell. bash
produces the autocompletion output on stderr
, so redirect that to stdout
and pipe that through head
and tail
to select one line of output from the whole. That produces, in this case, the one-line output
a1 a2 a3
But, as others say, just using
echo a*
might be easier!