Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile variable autocompletion in bash

Let's say my Makefile is something like:

DIR :=#

foobar:

   ls ${DIR}

When i type

mak[tab] f[tab]

it gives correctly

make foobar

But

make foobar D[tab]

doesn't do the magic

make foobar DIR=

So my question is: is there a way to autocomplete Makefile variables too (aside targets) in bash?

like image 477
Luca Braglia Avatar asked Sep 10 '14 13:09

Luca Braglia


People also ask

How do I use autocompletion in bash?

Bash completion is a bash function that allows you to auto complete commands or arguments by typing partially commands or arguments, then pressing the [Tab] key. This will help you when writing the bash command in terminal.

Does bash have autocomplete?

The programmable completion feature in Bash permits typing a partial command, then pressing the [Tab] key to auto-complete the command sequence. [1] If multiple completions are possible, then [Tab] lists them all. Let's see how it works. Tab completion also works for variables and path names.


1 Answers

This answer is far from complete. To grep all variables in a Makefile we use make -p to print the Makefile database:

# GNU Make 3.81
# Copyright (C) 2006  Free Software Foundation, Inc.
# This is free software; see the source for copying conditions.
# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.

# This program built for x86_64-pc-linux-gnu

# Make data base, printed on Mon Oct 13 13:36:12 2014

# Variables

# automatic
<D = $(patsubst %/,%,$(dir $<))
# automatic
?F = $(notdir $?)
# environment
DESKTOP_SESSION = kde-plasma
# ...
# makefile (from `Makefile', line 1)
DIR := 

We are looking for lines starting with # makefile (from 'Makefile', line xy) and extract the name of the following variable:

$ make -p | sed -n '/# makefile (from/ {n; p;}'
MAKEFILE_LIST :=  Makefile
DIR :=

In the next step we remove everything but the variable name (everything after :=):

$ make -p Makefile | sed -n '/# makefile (from/ {n; s/^\([^.#:= ]\+\) *:\?=.*$/\1/p;}'
MAKEFILE_LIST
DIR

The following lines demonstrate how it could be done:

_make_variables()
{
  # get current completion
  local cur=${COMP_WORDS[COMP_CWORD]}
  # get list of possible makefile variables
  local var=$(make -p Makefile | sed -n '/# makefile (from/ {n; s/^\([^.#:= ]\+\) *:\?=.*$/\1=/p;}')
  # don't add a space after completion
  compopt -o nospace

  # find possible matches
  COMPREPLY=( $(compgen -W "${var}" -- ${cur}) )
}

# use _make_variables to complete make arguments
complete -F _make_variables make

Now make D[tab] results in make DIR=.

Sadly you will loose all the file and target completion with this approach. Also it would be useful to remove some more variables (e.g. MAKEFILE_LIST) from the completion output.

Maybe it is worth to fill a wish/bug report against the bash-completion project to add this feature.

like image 194
sgibb Avatar answered Oct 17 '22 19:10

sgibb