@@ -18,8 +18,10 @@ echo "start app"
18
18
run frontend
19
19
e end: # stop app
20
20
echo "stop app"
21
- t test: # run all tests or specific test [vars: name='all']
22
- [[ -n "\$ (name)" ]] && echo "run test \$ (name)" || echo "run test all"
21
+ t test: # run all tests or specific test [vars: name]
22
+ [[ -n \$ (1) ]] && echo "run test \$ (1)" || echo "run test all"
23
+ tests: # run multiple tests [vars: names]
24
+ echo "run tests \$ (@)"
23
25
r repl: # start shell in project environment [vars: env='']
24
26
echo "start shell in project environment: \$ (env)"
25
27
EOF
@@ -32,8 +34,11 @@ s start: end # start app
32
34
e end: # stop app
33
35
echo "stop app"
34
36
35
- t test: # run all tests or specific test [vars: name='all']
36
- [[ -n "\$ (name)" ]] && echo "run test \$ (name)" || echo "run test all"
37
+ t test: # run all tests or specific test [vars: name]
38
+ [[ -n \$ (1) ]] && echo "run test \$ (1)" || echo "run test all"
39
+
40
+ tests: # run multiple tests [vars: names]
41
+ echo "run tests \$ (@)"
37
42
38
43
r repl: # start shell in project environment [vars: env='']
39
44
echo "start shell in project environment: \$ (env)"
@@ -75,7 +80,7 @@ function print-file-smartcase() {
75
80
}
76
81
77
82
function print-makefile() {
78
- sed -E "s!\t${at} make --makefile ${mf } !\t${at} make !" "$@ "
83
+ sed -E "s!\t${at} make --makefile ${makefile } !\t${at} make !" "$@ "
79
84
}
80
85
81
86
function cd-to-nearest-file() { local lower='' upper='' title=''
@@ -100,7 +105,8 @@ function cd-to-nearest-file() { local lower='' upper='' title=''
100
105
}
101
106
102
107
function main() ( set -euo pipefail
103
- local mf='' at='' ws='' rewrite="" cmd="" arg='' make_args=() cmd_args=()
108
+ local makefile='' buffer='' at='' ws='' rewrite='' cmd=''
109
+ local arg='' make_args=() cmd_args=() pos_args=() pos_arg_idx=0
104
110
105
111
# Handle various optional actions:
106
112
[[ " $* " == *' --create-runfile '* || " $* " == *' --overwrite-runfile '* ]] && \
@@ -116,14 +122,14 @@ function main() ( set -euo pipefail
116
122
cd-to-nearest-file runfile
117
123
118
124
# Local values:
119
- mf ="$( mktemp ) " # Temporary makefile which we will pass to make.
120
- at="@" # @-prefix causes make to execute commands silently.
121
- args=() # Arguments that will be passed on to invoked run command.
125
+ makefile ="$( mktemp ) " # Temporary makefile which we will pass to make.
126
+ at="@" # @-prefix causes make to execute commands silently.
127
+ args=() # Arguments that will be passed on to invoked run command.
122
128
123
129
# Existing Makefile Compatibility:
124
130
# If 'run cmd' or 'make cmd' appears within another command in a Runfile,
125
- # normally we'd rewrite these both to 'make --makefile ${mf } ' to avoid invoking
126
- # runfile.sh recursively. However, if a separate Makefile exists in the same directory
131
+ # normally we'd rewrite these to 'make --makefile ${makefile } ' to avoid invoking
132
+ # runfile.sh recursively. However, if a separate Makefile exists in same directory
127
133
# as the current Runfile we're executing a command for, we WON'T rewrite 'make cmd'
128
134
# in this way. In that case, leaving 'make cmd' alone allows the user to reference
129
135
# a command in the existing Makefile from their runfile.sh command.
@@ -157,23 +163,26 @@ function main() ( set -euo pipefail
157
163
elif [[ " ${arg} " == *' -' ]]
158
164
then
159
165
make_args+=( "${arg} " )
160
- else
166
+ elif [[ "${arg} " =~ ^[a-zA-Z0-9_-]+\= ]]
167
+ then
161
168
cmd_args+=( "${arg} " )
169
+ else
170
+ pos_args+=( "${arg} " )
162
171
fi
163
172
fi
164
173
done
165
174
166
175
# ::::::::::::::::::::::::::::::::::::::::::
167
176
# Construct temporary Makefile from Runfile:
168
- cat <<EOF> "${mf } "
177
+ cat <<EOF> "${makefile } "
169
178
.PHONY: _tasks
170
179
_tasks: .tasks
171
180
172
181
$(
173
182
sed -E \
174
183
-e " s!^[[:space:]]*!\t${at} !" \
175
184
-e " s!^\t${at} ([a-zA-Z0-9 _-]+):([a-zA-Z0-9 _-]+)?#(.*)\$ !.PHONY: \1\n\1:\2#\3!" \
176
- -e " s!^\t${at}${rewrite} !\t${at} make --makefile ${mf } !" \
185
+ -e " s!^\t${at}${rewrite} !\t${at} make --makefile ${makefile } !" \
177
186
-e " s!^\t${at} \$ !!" \
178
187
Runfile
179
188
)
186
195
# Done with temporary Makefile construction.
187
196
# ::::::::::::::::::::::::::::::::::::::::::
188
197
198
+ # Handle positional command arguments if any were provided:
199
+ if [[ " $* " != *' --print-makefile '* ]] \
200
+ && [[ " $* " != *' --create-makefile '* ]] \
201
+ && [[ " $* " != *' --overwrite-makefile '* ]]
202
+ then
203
+ buffer="$( cat " ${makefile} " ) "
204
+ if ! (( ${# pos_args[@]} ))
205
+ then
206
+ # Case where no positional args were provided:
207
+ # Replace $( @) and $( 1) $( 2) etc. in script with empty backtick expression (` ` ).
208
+ # This seems odd, but it allows tasks like: [[ -n $( 1) ]] && echo "$1 "
209
+ # to work whether or not $1 positional arg was provided. Without it, make will
210
+ # error out due to the script being interpreted as [[ -n ]]. With standard
211
+ # quotes instead of backticks, expressions like echo "$1 " will inadvertently
212
+ # print the quotes.
213
+ buffer="${buffer// \$ ([0-9@])/ \`\` } "
214
+ else
215
+ # Replace $( @) in script with concatenation of all positional args:
216
+ buffer="${buffer// \$ (@ )/ ${pos_args[*]} } "
217
+ # Replace $( 1) $( 2) etc. in script with each individual positional arg:
218
+ for arg in "${pos_args[@]} "
219
+ do
220
+ (( pos_arg_idx++ )) || true
221
+ buffer="${buffer// \$ (${pos_arg_idx} )/ ${arg} } "
222
+ done
223
+ fi
224
+ # Write buffer back to temporary makefile:
225
+ echo "${buffer} " > "${makefile} "
226
+ fi
227
+
189
228
# --create-makefile : Write generated Makefile, open in editor (optional) then exit.
190
229
# --overwrite-makefile : Can be used to overwrite when Makefile already exists.
191
230
if [[ " $* " == *' --create-makefile '* || " $* " == *' --overwrite-makefile '* ]]
@@ -195,11 +234,19 @@ EOF
195
234
then
196
235
echo 'Makefile already exists. To overwrite, use:'
197
236
echo 'make --overwrite-makefile'
198
- rm "${mf } "
237
+ rm "${makefile } "
199
238
exit 1
200
239
else
201
- print-makefile "${mf} " > ./Makefile
202
- rm "${mf} "
240
+ if grep -qE '\$ \([@0-9]\)' "${makefile} "
241
+ then
242
+ echo 'Warning: Your runfile uses positional args $( @) $( 1) $( 2) etc.'
243
+ echo "which aren't compatible with Make. You'll need to update these"
244
+ echo 'commands to accept standard Make-style named arguments:'
245
+ echo '$( abc) in your Makefile, passed to task as: $ make task abc=xyz'
246
+ echo
247
+ fi
248
+ print-makefile "${makefile} " > ./Makefile
249
+ rm "${makefile} "
203
250
edit-file-smartcase makefile --confirm
204
251
exit 0
205
252
fi
208
255
# --print-makefile : Print generated Makefile then exit.
209
256
if [[ " $* " == *' --print-makefile '* ]]
210
257
then
211
- print-makefile "${mf } "
212
- rm "${mf } "
258
+ print-makefile "${makefile } "
259
+ rm "${makefile } "
213
260
exit 0
214
261
fi
215
262
@@ -222,10 +269,10 @@ EOF
222
269
make_args+=( "${cmd} " )
223
270
fi
224
271
225
- make --makefile "${mf } " "${make_args[@]} " -- "${cmd_args[@]} "
272
+ make --makefile "${makefile } " "${make_args[@]} " -- "${cmd_args[@]} "
226
273
227
274
# Clean up temporary Makefile and exit with success:
228
- rm "${mf } "
275
+ rm "${makefile } "
229
276
exit 0
230
277
)
231
278
0 commit comments