Skip to content

Commit 14887c1

Browse files
committed
implement task positional-argument handling
1 parent 22c62ff commit 14887c1

File tree

3 files changed

+79
-25
lines changed

3 files changed

+79
-25
lines changed

Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@ e end: # stop app
1111
@echo "stop app"
1212

1313
.PHONY: t test
14-
t test: # run all tests or specific test [vars: name='all']
15-
@[[ -n "$(name)" ]] && echo "run test $(name)" || echo "run test all"
14+
t test: # run all tests or specific test [vars: name]
15+
@[[ -n "$(1)" ]] && echo "run test $(1)" || echo "run test all"
16+
17+
.PHONY: tests
18+
tests: # run multiple tests [vars: names]
19+
@echo "run tests $(@)"
1620

1721
.PHONY: r repl
1822
r repl: # start shell in project environment [vars: env='']

Runfile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ s start: end # start app
55
e end: # stop app
66
echo "stop app"
77

8-
t test: # run all tests or specific test [vars: name='all']
9-
[[ -n "$(name)" ]] && echo "run test $(name)" || echo "run test all"
8+
t test: # run all tests or specific test [vars: name]
9+
[[ -n "$(1)" ]] && echo "run test $(1)" || echo "run test all"
10+
11+
tests: # run multiple tests [vars: names]
12+
echo "run tests $(@)"
1013

1114
r repl: # start shell in project environment [vars: env='']
1215
echo "start shell in project environment: $(env)"

runfile.sh

Lines changed: 68 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ echo "start app"
1818
run frontend
1919
e end: # stop app
2020
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 \$(@)"
2325
r repl: # start shell in project environment [vars: env='']
2426
echo "start shell in project environment: \$(env)"
2527
EOF
@@ -32,8 +34,11 @@ s start: end # start app
3234
e end: # stop app
3335
echo "stop app"
3436
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 \$(@)"
3742
3843
r repl: # start shell in project environment [vars: env='']
3944
echo "start shell in project environment: \$(env)"
@@ -75,7 +80,7 @@ function print-file-smartcase() {
7580
}
7681
7782
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 !" "$@"
7984
}
8085
8186
function cd-to-nearest-file() { local lower='' upper='' title=''
@@ -100,7 +105,8 @@ function cd-to-nearest-file() { local lower='' upper='' title=''
100105
}
101106
102107
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
104110
105111
# Handle various optional actions:
106112
[[ " $* " == *' --create-runfile '* || " $* " == *' --overwrite-runfile '* ]] && \
@@ -116,14 +122,14 @@ function main() ( set -euo pipefail
116122
cd-to-nearest-file runfile
117123
118124
# 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.
122128
123129
# Existing Makefile Compatibility:
124130
# 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
127133
# as the current Runfile we're executing a command for, we WON'T rewrite 'make cmd'
128134
# in this way. In that case, leaving 'make cmd' alone allows the user to reference
129135
# a command in the existing Makefile from their runfile.sh command.
@@ -157,23 +163,26 @@ function main() ( set -euo pipefail
157163
elif [[ " ${arg}" == *' -' ]]
158164
then
159165
make_args+=( "${arg}" )
160-
else
166+
elif [[ "${arg}" =~ ^[a-zA-Z0-9_-]+\= ]]
167+
then
161168
cmd_args+=( "${arg}" )
169+
else
170+
pos_args+=( "${arg}" )
162171
fi
163172
fi
164173
done
165174
166175
# ::::::::::::::::::::::::::::::::::::::::::
167176
# Construct temporary Makefile from Runfile:
168-
cat <<EOF> "${mf}"
177+
cat <<EOF> "${makefile}"
169178
.PHONY: _tasks
170179
_tasks: .tasks
171180
172181
$(
173182
sed -E \
174183
-e "s!^[[:space:]]*!\t${at}!" \
175184
-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} !" \
177186
-e "s!^\t${at}\$!!" \
178187
Runfile
179188
)
@@ -186,6 +195,36 @@ EOF
186195
# Done with temporary Makefile construction.
187196
# ::::::::::::::::::::::::::::::::::::::::::
188197
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+
189228
# --create-makefile : Write generated Makefile, open in editor (optional) then exit.
190229
# --overwrite-makefile : Can be used to overwrite when Makefile already exists.
191230
if [[ " $* " == *' --create-makefile '* || " $* " == *' --overwrite-makefile '* ]]
@@ -195,11 +234,19 @@ EOF
195234
then
196235
echo 'Makefile already exists. To overwrite, use:'
197236
echo 'make --overwrite-makefile'
198-
rm "${mf}"
237+
rm "${makefile}"
199238
exit 1
200239
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}"
203250
edit-file-smartcase makefile --confirm
204251
exit 0
205252
fi
@@ -208,8 +255,8 @@ EOF
208255
# --print-makefile : Print generated Makefile then exit.
209256
if [[ " $* " == *' --print-makefile '* ]]
210257
then
211-
print-makefile "${mf}"
212-
rm "${mf}"
258+
print-makefile "${makefile}"
259+
rm "${makefile}"
213260
exit 0
214261
fi
215262
@@ -222,10 +269,10 @@ EOF
222269
make_args+=( "${cmd}" )
223270
fi
224271
225-
make --makefile "${mf}" "${make_args[@]}" -- "${cmd_args[@]}"
272+
make --makefile "${makefile}" "${make_args[@]}" -- "${cmd_args[@]}"
226273
227274
# Clean up temporary Makefile and exit with success:
228-
rm "${mf}"
275+
rm "${makefile}"
229276
exit 0
230277
)
231278

0 commit comments

Comments
 (0)