-
Notifications
You must be signed in to change notification settings - Fork 374
/
make
229 lines (203 loc) · 8.19 KB
/
make
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# bash completion for GNU make -*- shell-script -*-
_make_target_extract_script()
{
local mode="$1"
shift
local prefix="$1"
local prefix_pat=$(command sed 's/[][\,.*^$(){}?+|/]/\\&/g' <<<"$prefix")
local basename=${prefix##*/}
local dirname_len=$((${#prefix} - ${#basename}))
# Avoid expressions like '\(.\{0\}\)', FreeBSD sed doesn't like them:
# > sed: 1: ...: RE error: empty (sub)expression
local dirname_re
((dirname_len > 0)) && dirname_re="\(.\{${dirname_len}\}\)"
if [[ ! -v dirname_re ]]; then
local output="\1"
elif [[ $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
1,/^# * Make data base/ d; # skip any makefile output
/^# * Finished Make data base/,/^# * Make data base/{
d; # skip any makefile output
}
/^# * Variables/,/^# * 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_re-}\(.\{${#basename}\}[^:]*\):.*$|${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
EOF
# don't complete with hidden targets unless we are doing a partial completion
if [[ ! ${prefix_pat} || ${prefix_pat} == */ ]]; then
cat <<EOF
/^${prefix_pat}[^a-zA-Z0-9]/d; # convention for hidden tgt
EOF
fi
cat <<EOF
h; # hold target
d; # delete line
}
EOF
}
_make()
{
local cur prev words cword split comp_args
_comp_initialize -s -- "$@" || return
local makef makef_dir=("-C" ".") i
case $prev in
--file | --makefile | --old-file | --assume-old | --what-if | --new-file | \
--assume-new | -!(-*)[foW])
_filedir
return
;;
--include-dir | --directory | -!(-*)[ICm])
_filedir -d
return
;;
-!(-*)E)
COMPREPLY=($(compgen -v -- "$cur"))
return
;;
--eval | -!(-*)[DVx])
return
;;
--jobs | -!(-*)j)
COMPREPLY=($(compgen -W "{1..$(($(_ncpus) * 2))}" -- "$cur"))
return
;;
esac
$split && return
if [[ $cur == -* ]]; then
COMPREPLY=($(
compgen -W '$(_parse_help "$1" || _parse_usage "$1")' -- "$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 = 1; i < ${#words[@]}; i++)); do
if [[ ${words[i]} == -@(C|-directory) ]]; then
# Expand tilde expansion
local ret
_comp_dequote "${words[i + 1]-}" &&
[[ -d ${ret-} ]] &&
makef_dir=(-C "$ret")
break
fi
done
# before we scan for targets, see if a Makefile name was
# specified with -f/--file/--makefile
for ((i = 1; i < ${#words[@]}; i++)); do
if [[ ${words[i]} == -@(f|-?(make)file) ]]; then
# Expand tilde expansion
local ret
_comp_dequote "${words[i + 1]-}" &&
[[ -f ${ret-} ]] &&
makef=(-f "$ret")
break
fi
done
# recognise that possible completions are only going to be displayed so
# only the base name is shown.
#
# Note: This is currently turned off because the test suite of
# bash-completion conflicts with it; it uses "set show-all-if-ambiguous
# on" (causing COMP_TYPE == 37) to retrieve the action completion
# results, and also the compact form with only the basenames is not
# essentially needed. To re-enable it, please uncomment the following
# if-statement.
local mode=--
# if ((COMP_TYPE != 9 && COMP_TYPE != 37 && COMP_TYPE != 42)); then
# mode=-d # display-only mode
# fi
local IFS=$' \t\n' script=$(_make_target_extract_script $mode "$cur")
COMPREPLY=($(LC_ALL=C \
$1 -npq __BASH_MAKE_COMPLETION__=1 \
${makef+"${makef[@]}"} "${makef_dir[@]}" .DEFAULT 2>/dev/null |
command sed -ne "$script"))
local prefix=$cur
[[ $mode == -d ]] && prefix=
if ((${#COMPREPLY[@]} > 0)); then
local -A processed paths
local target
for target in "${COMPREPLY[@]}"; do
local path=${target%/}
[[ ${processed[$path]+set} ]] && continue
processed[$path]=$target
while
if [[ ! ${paths[$path]+set} ]]; then
((paths[\$path] = 1))
else
((paths[\$path]++))
fi
[[ $path == "$prefix"*/* ]]
do
path=${path%/*}
done
done
COMPREPLY=()
local nreply=0 target
for target in "${!paths[@]}"; do
local path=$target
while [[ $path == "$prefix"*/* ]]; do
path=${path%/*}
((paths[\$path] != 1)) && continue 2
done
if [[ ${processed[$target]+set} ]]; then
COMPREPLY[nreply++]=${processed[$target]}
elif ((paths[\$target] > 1)); then
COMPREPLY[nreply++]=$target/
fi
done
fi
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 bmake
# ex: filetype=sh