Skip to content

Commit 80d4e62

Browse files
committed
Fixes CI, gradient
1 parent 25218bf commit 80d4e62

10 files changed

Lines changed: 129 additions & 170 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
run: brew install shellcheck bats-core
2626

2727
- name: shellcheck
28-
run: shellcheck install.sh global/install-global.sh examples/*.sh
28+
run: shellcheck install.sh global/install-global.sh lib/examples/*.sh
2929

3030
- name: bats
3131
run: bats test/

‎CONTRIBUTING.md‎

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,11 @@ never exercises the gradient/color code paths):
2727
mkdir -p /tmp/run-smoke && cd /tmp/run-smoke
2828
bash /path/to/run-sh/install.sh --examples
2929
./run
30-
./run new hello
3130
./run hello
32-
./run help hello
3331
```
3432

3533
## Design notes
3634

37-
- `install.sh` and `global/install-global.sh` are meant to be curl-piped
38-
standalone, so all generated file content (the `run` dispatcher,
39-
`.runrc`, `colors.sh`, the `run new` boilerplate, the global `run`
40-
script) is embedded as heredocs directly in these two files — there is
41-
no `templates/` directory to keep in sync.
4235
- Target bash is 3.2 (stock macOS) — avoid associative arrays, `${var,,}`,
4336
`mapfile`, and other bash-4+ features.
4437
- `render_run_file` writes its heredoc straight to a temp file rather than

‎README.md‎

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
> [!CAUTION]
2+
> This is work in progress, use on your own risk.
3+
14
# run.sh
25

36
A Makefile replacement written in pure bash. No DSL, no runtime dependencies,
@@ -6,7 +9,7 @@ no build step — just scripts.
69
## Install
710

811
```sh
9-
curl -fsSL https://raw.githubusercontent.com/imgproxy/run-sh/main/install.sh | bash -e
12+
curl -fsSL https://raw.githubusercontent.com/imgproxy/run-sh/refs/heads/main/install.sh | bash -s -- -e
1013
```
1114

1215
This sets up, in the current project:
@@ -22,15 +25,13 @@ folder for task files.
2225

2326
```sh
2427
./run # list available tasks
25-
./run help <task> # show a task's usage
2628
./run <task> [args...]
27-
./run new <task> # scaffold a new task file
2829
```
2930

3031
## Optional: global command
3132

3233
```sh
33-
curl -fsSL https://raw.githubusercontent.com/imgproxy/run-sh/main/install.sh | bash -s -- -g
34+
curl -fsSL https://raw.githubusercontent.com/imgproxy/run-sh/refs/heads/main/install.sh | bash -s -- -e -g
3435
```
3536

3637
Installs `run` to `~/.local/bin`, which walks up from your current directory
@@ -58,8 +59,44 @@ main() {
5859
}
5960
```
6061

61-
Scaffold one with `./run new <name>`, or see `examples/` for zero-arg,
62-
positional-arg, flag-parsing, and task-composition patterns.
62+
See `examples/` for zero-arg, positional-arg, flag-parsing, and
63+
task-composition patterns.
64+
65+
## Dependencies
66+
67+
Compose tasks with `depends_on` inside a task's `main()`:
68+
69+
```sh
70+
main() {
71+
depends_on build test
72+
echo "deploying..."
73+
}
74+
```
75+
76+
`depends_on` runs each named task in order and stops at the first failure.
77+
78+
## External libraries
79+
80+
run.sh itself has no runtime dependencies, but your tasks can use any tool you
81+
already have installed. Install libraries the same way you normally would
82+
(Homebrew, apt, npm, pip, etc.) and call them from your task files.
83+
84+
For reusable helpers, source them from `.runrc`:
85+
86+
```sh
87+
# .runrc
88+
. "$TASK_ROOT/vendor/some-lib.sh"
89+
```
90+
91+
Use the built-in `require_tool` helper to fail early with a friendly message
92+
when a required command is missing:
93+
94+
```sh
95+
main() {
96+
require_tool jq "jq is required (https://jqlang.github.io/jq/)"
97+
jq '.version' package.json
98+
}
99+
```
63100

64101
## Philosophy
65102

‎docs/index.html‎

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ <h1>run.sh</h1>
2020

2121
<div class="install">
2222
<code
23-
id="install-cmd">curl -fsSL https://raw.githubusercontent.com/imgproxy/run-sh/main/install.sh | bash -e -g</code>
23+
id="install-cmd">curl -fsSL https://raw.githubusercontent.com/imgproxy/run-sh/refs/heads/main/install.sh | bash -s -- -e -g</code>
2424
<button class="copy-btn" onclick="copyInstall(this)">copy</button>
2525
</div>
2626

@@ -57,9 +57,26 @@ <h2>A task looks like this</h2>
5757
<section>
5858
<h2>Usage</h2>
5959
<pre class="snippet"><code>./run # list available tasks
60-
./run help &lt;task&gt; # show a task's usage
61-
./run &lt;task&gt; [args...]
62-
./run new &lt;task&gt; # scaffold a new task file</code></pre>
60+
./run &lt;task&gt; [args...]</code></pre>
61+
</section>
62+
63+
<section>
64+
<h2>Dependencies</h2>
65+
<p>
66+
Compose tasks with <code>depends_on</code> inside a task's <code>main()</code>.
67+
It runs each named task in order and stops at the first failure.
68+
</p>
69+
<pre class="snippet"><code>main() {
70+
depends_on build test
71+
echo "deploying..."
72+
}</code></pre>
73+
</section>
74+
75+
<section>
76+
<p>
77+
Want to know more? Check the documentation at:
78+
<a href="https://github.com/imgproxy/run-sh">github.com/imgproxy/run-sh</a>
79+
</p>
6380
</section>
6481

6582
<footer>

‎install.sh‎

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,35 @@ run_colors_enabled() {
2323
[ "$n" -ge 8 ] 2>/dev/null
2424
}
2525

26-
run_gradient_text() {
27-
local text="$1"
26+
run_color_echo() {
27+
local color="$1" text="$2"
2828
if ! run_colors_enabled; then
2929
printf '%s' "$text"
3030
return
3131
fi
3232
local ncolors
3333
ncolors="$(tput colors 2>/dev/null || echo 0)"
34-
if [ "$ncolors" -lt 256 ]; then
35-
printf '%s%s%s' "$(tput bold)" "$text" "$(tput sgr0)"
36-
return
34+
if [ "$ncolors" -ge 256 ]; then
35+
case "$color" in
36+
red) printf '\033[38;5;196m%s' "$text" ;;
37+
green) printf '\033[38;5;34m%s' "$text" ;;
38+
blue) printf '\033[38;5;21m%s' "$text" ;;
39+
cyan) printf '\033[38;5;45m%s' "$text" ;;
40+
magenta) printf '\033[38;5;201m%s' "$text" ;;
41+
neon) printf '\033[38;5;82m%s' "$text" ;;
42+
*) printf '%s' "$text" ;;
43+
esac
44+
else
45+
case "$color" in
46+
red) printf '\033[31m%s' "$text" ;;
47+
green) printf '\033[32m%s' "$text" ;;
48+
blue) printf '\033[34m%s' "$text" ;;
49+
cyan) printf '\033[36m%s' "$text" ;;
50+
magenta) printf '\033[35m%s' "$text" ;;
51+
neon) printf '\033[1;32m%s' "$text" ;;
52+
*) printf '%s' "$text" ;;
53+
esac
3754
fi
38-
local i=0 len=${#text} start=63 end=201
39-
local span=$((end - start))
40-
while [ "$i" -lt "$len" ]; do
41-
local ch="${text:$i:1}"
42-
local denom=$((len > 1 ? len - 1 : 1))
43-
local color=$((start + (span * i) / denom))
44-
printf '\033[38;5;%sm%s' "$color" "$ch"
45-
i=$((i + 1))
46-
done
4755
printf '%s' "$(tput sgr0)"
4856
}
4957

@@ -243,7 +251,7 @@ install_local() {
243251
fi
244252

245253
printf '\n'
246-
run_gradient_text "run.sh $RUN_VERSION installed"
254+
run_color_echo neon "run.sh $RUN_VERSION installed"
247255
printf '\n\nNext: ./run\n'
248256
}
249257

@@ -252,8 +260,8 @@ RUN_INSTALL_GLOBAL=0
252260

253261
while [ $# -gt 0 ]; do
254262
case "$1" in
255-
-e) RUN_INSTALL_EXAMPLES=1; shift ;;
256-
-g) RUN_INSTALL_GLOBAL=1; shift ;;
263+
-e|--examples) RUN_INSTALL_EXAMPLES=1; shift ;;
264+
-g|--global) RUN_INSTALL_GLOBAL=1; shift ;;
257265
-h|--help)
258266
cat <<EOF
259267
Usage: install.sh [-e] [-g]

‎lib/run.sh‎

Lines changed: 12 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -25,72 +25,30 @@ depends_on() {
2525

2626
cmd_list() {
2727
printf '\n'
28-
run_gradient_text "run.sh" 2>/dev/null || printf 'run.sh'
28+
run_color_echo neon "run.sh" 2>/dev/null || printf 'run.sh'
2929
printf ' — tasks in this project\n\n'
30-
local f name
30+
local f name has_tasks=0
3131
for f in "$TASK_DIR"/*.sh; do
3232
[ -e "$f" ] || continue
33+
has_tasks=1
3334
name="$(basename "$f" .sh)"
3435
# shellcheck disable=SC1090
3536
printf ' %-15s %s\n' "$name" "$(. "$f"; description)"
3637
done
37-
printf '\n'
38-
}
39-
40-
cmd_help() {
41-
local task="${1:-}"
42-
if [ -z "$task" ] || [ ! -f "$TASK_DIR/$task.sh" ]; then
43-
echo "error: unknown task '$task'" >&2
44-
cmd_list >&2
45-
exit 1
46-
fi
47-
# shellcheck disable=SC1090
48-
. "$TASK_DIR/$task.sh"
49-
description
50-
echo
51-
help
52-
}
53-
54-
cmd_new() {
55-
local name="${1:-}"
56-
case "$name" in
57-
"") echo "usage: ./run new <task-name>" >&2; return 1 ;;
58-
run) echo "error: 'run' is reserved (the dispatcher script)" >&2; return 1 ;;
59-
*[!a-zA-Z0-9_-]*) echo "error: task name must be alnum/underscore/hyphen" >&2; return 1 ;;
60-
esac
61-
local target="$TASK_DIR/$name.sh"
62-
if [ -e "$target" ] && [ "${2:-}" != "--force" ]; then
63-
echo "error: $target already exists (use --force to overwrite)" >&2
64-
return 1
38+
if [ "$has_tasks" -eq 0 ]; then
39+
printf ' No tasks yet.\n\n'
40+
printf ' Create your first task by adding a file at %s/<name>.sh:\n\n' "$(basename "$TASK_DIR")"
41+
printf ' #!/usr/bin/env bash\n'
42+
printf ' description() { echo "One-line summary"; }\n'
43+
printf ' help() { echo "Usage: ./run <name> [args...]"; }\n'
44+
printf ' main() { echo "task logic goes here, receives \\"$@\\""; }\n\n'
45+
printf ' Or scaffold examples with: bash install.sh --examples\n'
6546
fi
66-
cat > "$target" <<TASK_BOILERPLATE
67-
#!/usr/bin/env bash
68-
# Sourced by ./run — do not execute directly.
69-
70-
description() {
71-
echo "TODO: one-line description of $name"
72-
}
73-
74-
help() {
75-
cat <<'EOF'
76-
Usage: ./run $name [args...]
77-
78-
TODO: describe usage.
79-
EOF
80-
}
81-
82-
main() {
83-
echo "TODO: implement $name"
84-
}
85-
TASK_BOILERPLATE
86-
run_gradient_text "created" 2>/dev/null || printf 'created'
87-
printf ' %s\n' "$target"
47+
printf '\n'
8848
}
8949

9050
case "${1:-}" in
9151
"") cmd_list ;;
92-
help) shift; cmd_help "$@" ;;
93-
new) shift; cmd_new "$@" ;;
9452
*)
9553
task="$1"; shift
9654
if [ ! -f "$TASK_DIR/$task.sh" ]; then

‎lib/runrc.sh‎

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require_arg() {
1212
fi
1313
}
1414

15-
# --- terminal color/gradient helpers (used by ./run and available to tasks) ---
15+
# --- terminal color helpers (used by ./run and available to tasks) ---
1616

1717
run_colors_enabled() {
1818
[ -n "${NO_COLOR:-}" ] && return 1
@@ -22,26 +22,34 @@ run_colors_enabled() {
2222
[ "$n" -ge 8 ] 2>/dev/null
2323
}
2424

25-
run_gradient_text() {
26-
local text="$1"
25+
run_color_echo() {
26+
local color="$1" text="$2"
2727
if ! run_colors_enabled; then
2828
printf '%s' "$text"
2929
return
3030
fi
3131
local ncolors
3232
ncolors="$(tput colors 2>/dev/null || echo 0)"
33-
if [ "$ncolors" -lt 256 ]; then
34-
printf '%s%s%s' "$(tput bold)" "$text" "$(tput sgr0)"
35-
return
33+
if [ "$ncolors" -ge 256 ]; then
34+
case "$color" in
35+
red) printf '\033[38;5;196m%s' "$text" ;;
36+
green) printf '\033[38;5;34m%s' "$text" ;;
37+
blue) printf '\033[38;5;21m%s' "$text" ;;
38+
cyan) printf '\033[38;5;45m%s' "$text" ;;
39+
magenta) printf '\033[38;5;201m%s' "$text" ;;
40+
neon) printf '\033[38;5;82m%s' "$text" ;;
41+
*) printf '%s' "$text" ;;
42+
esac
43+
else
44+
case "$color" in
45+
red) printf '\033[31m%s' "$text" ;;
46+
green) printf '\033[32m%s' "$text" ;;
47+
blue) printf '\033[34m%s' "$text" ;;
48+
cyan) printf '\033[36m%s' "$text" ;;
49+
magenta) printf '\033[35m%s' "$text" ;;
50+
neon) printf '\033[1;32m%s' "$text" ;;
51+
*) printf '%s' "$text" ;;
52+
esac
3653
fi
37-
local i=0 len=${#text} start=63 end=201
38-
local span=$((end - start))
39-
while [ "$i" -lt "$len" ]; do
40-
local ch="${text:$i:1}"
41-
local denom=$((len > 1 ? len - 1 : 1))
42-
local color=$((start + (span * i) / denom))
43-
printf '\033[38;5;%sm%s' "$color" "$ch"
44-
i=$((i + 1))
45-
done
4654
printf '%s' "$(tput sgr0)"
4755
}

0 commit comments

Comments
 (0)