Bash: Getting a command's completion output pr

2019-02-24 06:35发布

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, but 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. 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

build is a pre-existing command, not something I can go ahead and modify to suit my purposes. And the manner in which it extracts its targets is something I certainly don't want to know.

Now suppose I have an entire repository of buildable projects, and most of my work and therefore most of my build work happens in only one project. In other words, I always build some target under my/project/directory.

So far so good.

So 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/directoryb_target

I want this:

mybuildTABTAB

to give me:

a_target
b_target

Of course I will need to write completion code for mybuild, but I want it to rely on the completion for build, because I can't just go and ask the developers of build to code a build listtargets command just to make me happy. That feature is already there, in the completion for build, and I need to tap into it.

(Of course, when I run mybuild a_target, it will know to run build my/project/directory/a_target, and that I know how to implement and is not in scope for this question.)

I hope this illustrates why I need to tap into the completion of the build command and use it as a black box.

3条回答
Explosion°爆炸
2楼-- · 2019-02-24 06:42

Bash has something similar to this called globbing.

So for example in your case you could run the command

echo a*

Which would produce:

a1 a2 a3

This is very useful where you have spaces in the names of your files as you can say

for i in a*
do
   echo $i
done

And it would work for a1 as well as a 1

查看更多
相关推荐>>
3楼-- · 2019-02-24 07:03

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!

查看更多
The star\"
4楼-- · 2019-02-24 07:07

Auto-completion is a feature provided by your shell (e.g. bash). The shell will try to offer auto-complete suggestions based on the context of the command you're trying to run and the environment. E.g. it knows that some commands will work on files and can offer some auto-completion based on file paths. But the command itself is not aware on how the arguments it has been run with have been specified, either by the user or with help of auto-completion.

查看更多
登录 后发表回答