1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
# 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}}[^:/]*/?)[^:]*:.*$,${output},p
d # hide any bugs
}
/^[^#\t:%]+:/ { # 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 | grep -F posix ); set +o posix # for <(...)
COMPREPLY=( $( LC_ALL=C \
make -npq "${makef[@]}" "${makef_dir[@]}" .DEFAULT 2>/dev/null | \
sed -nrf <(_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
|