| 1 | #!/usr/bin/env bash |
| 2 | |
| 3 | brt_run_shell() { |
| 4 | local sh="${SHELL:-/bin/bash}" |
| 5 | local base="${sh##*/}" |
| 6 | |
| 7 | case "$base" in |
| 8 | zsh) zsh -ic "$1" ;; |
| 9 | bash) bash -ic "$1" ;; |
| 10 | *) bash -c "$1" ;; |
| 11 | esac |
| 12 | } |
| 13 | |
| 14 | brt_run_split_chain() { |
| 15 | local chain="$1" |
| 16 | local part |
| 17 | local IFS=';' |
| 18 | read -ra parts <<< "$chain" |
| 19 | for part in "${parts[@]}"; do |
| 20 | part="${part#"${part%%[![:space:]]*}"}" |
| 21 | part="${part%"${part##*[![:space:]]}"}" |
| 22 | [[ -n "$part" ]] || continue |
| 23 | printf '%s\0' "$part" |
| 24 | done |
| 25 | } |
| 26 | |
| 27 | brt_run_build_script() { |
| 28 | local -a parts=("$@") |
| 29 | local part script="" idx=1 |
| 30 | |
| 31 | for part in "${parts[@]}"; do |
| 32 | if [[ "$part" =~ ^wait[[:space:]]+([0-9]+(\.[0-9]+)?)$ ]]; then |
| 33 | local secs="${BASH_REMATCH[1]}" |
| 34 | script+="printf '%b\\n' '\033[36m●\033[0m Waiting ${secs}s...'; sleep ${secs};" |
| 35 | continue |
| 36 | fi |
| 37 | if [[ "$part" == wait ]]; then |
| 38 | brt_error "wait requires seconds: wait 5" |
| 39 | exit 1 |
| 40 | fi |
| 41 | script+="printf '%b\\n' '\033[36m●\033[0m [${idx}] ${part//\'/\'\\\'\'}';" |
| 42 | script+="${part};" |
| 43 | script+='_brt_run_rc=$?; if (( _brt_run_rc != 0 )); then exit $_brt_run_rc; fi;' |
| 44 | ((idx++)) |
| 45 | done |
| 46 | |
| 47 | printf '%s' "$script" |
| 48 | } |
| 49 | |
| 50 | brt_run_from_args() { |
| 51 | local -a parts=() |
| 52 | local buf="" |
| 53 | |
| 54 | while (($#)); do |
| 55 | if [[ "$1" == "wait" ]]; then |
| 56 | [[ -n "$buf" ]] && parts+=("$buf") && buf="" |
| 57 | if (( $# < 2 )) || ! [[ "$2" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then |
| 58 | brt_error "wait requires seconds: brt -run ... wait 2 ..." |
| 59 | exit 1 |
| 60 | fi |
| 61 | parts+=("wait $2") |
| 62 | shift 2 |
| 63 | continue |
| 64 | fi |
| 65 | if [[ -n "$buf" ]]; then |
| 66 | buf+=" $1" |
| 67 | else |
| 68 | buf="$1" |
| 69 | fi |
| 70 | shift |
| 71 | done |
| 72 | [[ -n "$buf" ]] && parts+=("$buf") |
| 73 | |
| 74 | printf '%s\0' "${parts[@]}" |
| 75 | } |
| 76 | |
| 77 | brt_run() { |
| 78 | if (($# == 0)); then |
| 79 | brt_error 'Usage: brt -run <cmd;wait N;cmd...>' |
| 80 | echo 'Examples:' |
| 81 | echo " brt -run 'echo hi;wait 2;echo bye'" |
| 82 | echo ' brt -run echo hi wait 2 echo bye' |
| 83 | echo ' brt -run my_zsh_function wait 1 other_function' |
| 84 | exit 1 |
| 85 | fi |
| 86 | |
| 87 | brt_info "Running command chain..." |
| 88 | |
| 89 | local -a parts=() |
| 90 | if (($# == 1)) && [[ "$1" == *";"* ]]; then |
| 91 | while IFS= read -r -d '' part; do |
| 92 | parts+=("$part") |
| 93 | done < <(brt_run_split_chain "$1") |
| 94 | else |
| 95 | while IFS= read -r -d '' part; do |
| 96 | parts+=("$part") |
| 97 | done < <(brt_run_from_args "$@") |
| 98 | fi |
| 99 | |
| 100 | local script status |
| 101 | script=$(brt_run_build_script "${parts[@]}") |
| 102 | brt_run_shell "$script" |
| 103 | status=$? |
| 104 | if (( status != 0 )); then |
| 105 | brt_error "Command chain failed with exit code ${status}" |
| 106 | exit "$status" |
| 107 | fi |
| 108 | |
| 109 | brt_ok "Chain completed" |
| 110 | } |
| 111 | |