162 lines
5.7 KiB
Bash
162 lines
5.7 KiB
Bash
# bash completion for GNU make -*- shell-script -*-
|
|
|
|
function _make_target_extract_script()
|
|
{
|
|
local mode="$1"
|
|
shift
|
|
|
|
local prefix="$1"
|
|
local prefix_pat=$( printf "%s\n" "$prefix" | \
|
|
sed 's/[][\,.*^$(){}?+|/]/\\&/g' )
|
|
local basename=${prefix##*/}
|
|
local dirname_len=$(( ${#prefix} - ${#basename} ))
|
|
|
|
if [[ $mode == -d ]]; then
|
|
# display mode, only output current path component to the next slash
|
|
local output="\2"
|
|
else
|
|
# completion mode, output full path to the next slash
|
|
local output="\1\2"
|
|
fi
|
|
|
|
cat <<EOF
|
|
/^# Make data base/,/^# Files/d; # skip until files section
|
|
/^# Not a target/,/^$/ d; # skip not target blocks
|
|
/^${prefix_pat}/,/^$/! d; # skip anything user dont want
|
|
|
|
# The stuff above here describes lines that are not
|
|
# explicit targets or not targets other than special ones
|
|
# The stuff below here decides whether an explicit target
|
|
# should be output.
|
|
|
|
/^# File is an intermediate prerequisite/ {
|
|
s/^.*$//;x; # unhold target
|
|
d; # delete line
|
|
}
|
|
|
|
/^$/ { # end of target block
|
|
x; # unhold target
|
|
/^$/d; # dont print blanks
|
|
s|^\(.\{${dirname_len}\}\)\(.\{${#basename}\}[^:/]*/\{0,1\}\)[^:]*:.*$|${output}|p;
|
|
d; # hide any bugs
|
|
}
|
|
|
|
# This pattern includes a literal tab character as \t is not a portable
|
|
# representation and fails with BSD sed
|
|
/^[^# :%]\{1,\}:/ { # found target block
|
|
/^\.PHONY:/ d; # special target
|
|
/^\.SUFFIXES:/ d; # special target
|
|
/^\.DEFAULT:/ d; # special target
|
|
/^\.PRECIOUS:/ d; # special target
|
|
/^\.INTERMEDIATE:/ d; # special target
|
|
/^\.SECONDARY:/ d; # special target
|
|
/^\.SECONDEXPANSION:/ d; # special target
|
|
/^\.DELETE_ON_ERROR:/ d; # special target
|
|
/^\.IGNORE:/ d; # special target
|
|
/^\.LOW_RESOLUTION_TIME:/ d; # special target
|
|
/^\.SILENT:/ d; # special target
|
|
/^\.EXPORT_ALL_VARIABLES:/ d; # special target
|
|
/^\.NOTPARALLEL:/ d; # special target
|
|
/^\.ONESHELL:/ d; # special target
|
|
/^\.POSIX:/ d; # special target
|
|
/^\.NOEXPORT:/ d; # special target
|
|
/^\.MAKE:/ d; # special target
|
|
|
|
/^[^a-zA-Z0-9]/ d; # convention for hidden tgt
|
|
|
|
h; # hold target
|
|
d; # delete line
|
|
}
|
|
|
|
EOF
|
|
}
|
|
|
|
_make()
|
|
{
|
|
local cur prev words cword split
|
|
_init_completion -s || return
|
|
|
|
local file makef makef_dir=( "-C" "." ) makef_inc i
|
|
|
|
case $prev in
|
|
-f|--file|--makefile|-o|--old-file|--assume-old|-W|--what-if|\
|
|
--new-file|--assume-new)
|
|
_filedir
|
|
return 0
|
|
;;
|
|
-I|--include-dir|-C|--directory|-m)
|
|
_filedir -d
|
|
return 0
|
|
;;
|
|
-E)
|
|
COMPREPLY=( $( compgen -v -- "$cur" ) )
|
|
return 0
|
|
;;
|
|
--eval|-D|-V|-x)
|
|
return 0
|
|
;;
|
|
--jobs|-j)
|
|
COMPREPLY=( $( compgen -W "{1..$(( $(_ncpus)*2 ))}" -- "$cur" ) )
|
|
return 0
|
|
;;
|
|
esac
|
|
|
|
$split && return 0
|
|
|
|
if [[ "$cur" == -* ]]; then
|
|
local opts="$( _parse_help "$1" )"
|
|
[[ $opts ]] || opts="$( _parse_usage "$1" )"
|
|
COMPREPLY=( $( compgen -W "$opts" -- "$cur" ) )
|
|
[[ $COMPREPLY == *= ]] && compopt -o nospace
|
|
elif [[ $cur == *=* ]]; then
|
|
prev=${cur%%=*}
|
|
cur=${cur#*=}
|
|
local diropt
|
|
[[ ${prev,,} == *dir?(ectory) ]] && diropt=-d
|
|
_filedir $diropt
|
|
else
|
|
# before we check for makefiles, see if a path was specified
|
|
# with -C/--directory
|
|
for (( i=0; i < ${#words[@]}; i++ )); do
|
|
if [[ ${words[i]} == -@(C|-directory) ]]; then
|
|
# eval for tilde expansion
|
|
eval makef_dir=( -C "${words[i+1]}" )
|
|
break
|
|
fi
|
|
done
|
|
|
|
# before we scan for targets, see if a Makefile name was
|
|
# specified with -f/--file/--makefile
|
|
for (( i=0; i < ${#words[@]}; i++ )); do
|
|
if [[ ${words[i]} == -@(f|-?(make)file) ]]; then
|
|
# eval for tilde expansion
|
|
eval makef=( -f "${words[i+1]}" )
|
|
break
|
|
fi
|
|
done
|
|
|
|
# recognise that possible completions are only going to be displayed
|
|
# so only the base name is shown
|
|
local mode=--
|
|
if (( COMP_TYPE != 9 )); then
|
|
mode=-d # display-only mode
|
|
fi
|
|
|
|
local reset=$( set +o | command grep -F posix ); set +o posix # <(...)
|
|
COMPREPLY=( $( LC_ALL=C \
|
|
make -npq "${makef[@]}" "${makef_dir[@]}" .DEFAULT 2>/dev/null | \
|
|
sed -nf <(_make_target_extract_script $mode "$cur") ) )
|
|
$reset
|
|
|
|
if [[ $mode != -d ]]; then
|
|
# Completion will occur if there is only one suggestion
|
|
# so set options for completion based on the first one
|
|
[[ $COMPREPLY == */ ]] && compopt -o nospace
|
|
fi
|
|
|
|
fi
|
|
} &&
|
|
complete -F _make make gmake gnumake pmake colormake
|
|
|
|
# ex: ts=4 sw=4 et filetype=sh
|