Table of Contents
Problem
If you use make
frequently, you may be aware that you can tab complete targets in bash. For example, $ make cl<TAB> ins<TAB>
may autocomplete to clean
then install
.
In vim, however, if you type :make <TAB>
, by default, vim attempts to autocomplete file names.
This blog post will show you how you can get vim to autocomplete <TAB>
with target names from your Makefile
instead.
Solution
I recently came across this StackOverflow question, How to list all targets in make?, in which the answer is bash's completion logic:
make -qp |
awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}' |
sort -u
This will print out a newline-delimited list of possible targets from the Makefile in your current working directory.
With this set of commands, we can write a custom vimscript function that executes them and returns the output as completion candidates for a vim command:
function! MakeCompletion() abort
return systemlist('make -qp | awk -F'':'' ''/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'' | grep -v Makefile | sort -u')
endfunction
command! -nargs=* -complete=customlist,MakeCompletion Make !make <args>
This alone is a great accomplishment. If you type :Make <TAB>
, you can cycle through all the possible make targets!
However, you may notice that if you type part of a target name and hit <TAB>
, vim will ignore the partial input and cycle through from the beginning of the list.
Improved
If you read :help :command-completion-customlist
, you will discover that the function can take 3 arguments:
The function arguments are:
ArgLead the leading portion of the argument currently being completed on
CmdLine the entire command line
CursorPos the cursor position in it (byte index)
So let's modify our MakeCompletion()
function to support filtering results based on ArgLead
:
function! MakeCompletion(A,L,P) abort
let l:targets = systemlist('make -qp | awk -F'':'' ''/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'' | grep -v Makefile | sort -u')
return filter(l:targets, 'v:val =~ "^' . a:A . '"')
endfunction
command! -nargs=* -complete=customlist,MakeCompletion Make !make <args>
Now, when you type :Make cl<TAB> ins<TAB>
, it will successfully auto-complete to :Make clean install
.
I hope you find this short vim tip helpful.
For more vim goodies, check out my vimrc.
Happy hacking!
Top comments (1)
Thanks! Just what I needed :D