-1

I am running compgen -c make in BASH on mac and am getting the following return values:

makepqg
makepqg
makepqg
make
makeinfo
makepqg
makepqg

But what I want and should? be getting (and do get when completing) is:

foo
bar
biz
baz

Which represent my various PHONY make rules that do automatic things.


How does one generate this list from the SHELL, generally, with the executable tool compgen?

(this is the ideal question because, from python3, subprocess is not able to simulate the interaction, and I'll have to do something more involved)


This is different than the duplicate candidate, "How do I get the targets in make (paraphrased)" in that I don't think the (non-working) command is a good answer, and this question is about compgen and make rather than make and the inner workings of make:

make -p no_targets__ 
| awk -F':' '/^[a-zA-Z0-9][^\$$#\/\\t=]*:([^=]|$$)/ {split(\$$1,A,/ /);for(i in A)print A[i]}' "
| grep -v '__\$$' "
| sort

But can I get to some kind of a solution for my high level purpose using regexes?

In my opinion, no, because compgen is easy and memorable, whereas this kludge is hard and introduces drag on any code I'd pile on top.


Also, the duplicate allows for changes to be made to the makefile.

In my case, the make file must be considered a given, or what I am doing will be less useful.

So, more specifically, given any makefile, is there a solution involving tools outside of make that can look into make and get make to output a list of its recipes as it would for bash completion.

In other words: can this be done for ANY makefile (without loss of generality) without requiring write permissions on the makefile, and without simulating the tab-tab using a tty simulator?

Chris
  • 28,822
  • 27
  • 83
  • 158
  • I'm not sure you can achieve what you want with a mere "shell completion tool", i.e., you'll probably need to rely on the domain specific language of `make`, e.g. like [this answer](https://stackoverflow.com/a/26339924/9164010) (?) – ErikMD Dec 10 '21 at 19:09
  • 1
    @ErikMD I did copy that long regex and specialized it to make. I guess if "whatever works" is the standard, then it works. – Chris Dec 10 '21 at 19:10
  • The regex has to be debugged for the awk/gawk I've got on the Mac. So, not sure whether it works either. – Chris Dec 10 '21 at 19:19
  • If your actual question is "now do I debug this Awk script" then by all means ask _that_ instead. – tripleee Dec 13 '21 at 04:55
  • @tripleee No, that is not the question. Awk is my first language and I've written entire programs in it, as I had to post process 3d models with a text processor. But a scribble scrabble bundle of regexes is never a valid answer if you want to implement something that is clean, nice, and amounts to something like the "right way". Instead of the squirrels nest, I added a known prefix to the rules I dynamically expose. But it is still the wrong answer: the right answer should be simple. I'd rather emulate tab tab than put the accepted answer in my code. – Chris Dec 13 '21 at 12:12
  • I don't disagree with that; but then isn't the correct solution to post a better answer to that question? – tripleee Dec 13 '21 at 12:13
  • @tripleee Good point. I'm thinking you can execute the tab tab emulation with expect, and I'll post that answer in a bit when I get a chance. – Chris Dec 13 '21 at 12:16

1 Answers1

1

Just a gist of it.

_make_phony() {
    COMPREPLY=( )
    # a lot of code
    COMPREPLY=( foo bar biz baz )
}
complete -F _make_phony make

Now when you type make TabTab you'll get:

foo
bar
biz
baz

Of course you'll have to parse the Makefile to extract the real PHONY, and also handle each possible option of make, like make -f Makefile.osx and others; it can really become complex.

Fravadona
  • 13,917
  • 1
  • 23
  • 35
  • Instead of this, I prefixed my rules with a simple to match pattern. There must be an easy way, or then perhaps the answer is: open up the expect, tcl or pty and emulate the user hitting tab twice. – Chris Dec 13 '21 at 12:13