#!/usr/bin/env sh # Parts of a shell library {{{ die() { error "$1"; if [ -n "$2" ]; then exit "$2"; else exit 1; fi } print() { # The direct usage is intended as `print` is rather lowlevel # shellcheck disable=2059 printf "$*"; }; println() { # The direct usage is intended as `println` is rather lowlevel # shellcheck disable=2059 printf "$*\n"; }; eprint() { >&2 print "$@"; }; eprintln() { >&2 println "$@"; }; if [ -n "$NO_COLOR" ];then error() { eprintln "==> ERROR:" "$*"; }; warning() { eprintln "==> WARNING:" "$*"; }; debug() { [ -n "$SHELL_LIBRARY_DEBUG" ] && eprintln "==> [Debug:]" "$*"; }; debug2() { [ -n "$SHELL_LIBRARY_DEBUG" ] && eprintln " -> [Debug:]" "$*"; }; msg() { eprintln "==>" "$*"; }; msg2() { eprintln " ->" "$*"; }; prompt() { eprint "..>" "$*"; }; else # See https://stackoverflow.com/a/33206814 for ansi codes error() { eprintln "\033[1;91m==> ERROR:\033[0m" "\033[1;93m$*\033[0m"; }; warning() { eprintln "\033[1;91m==> WARNING:\033[0m" "\033[1;93m$*\033[0m"; }; debug() { [ -n "$SHELL_LIBRARY_DEBUG" ] && eprintln "\033[1;94m==> [Debug:]\033[0m" "\033[1;93m$*\033[0m"; }; debug2() { [ -n "$SHELL_LIBRARY_DEBUG" ] && eprintln "\033[1;94m -> [Debug:]\033[0m" "\033[1;93m$*\033[0m"; }; msg() { eprintln "\033[1;96m==>\033[0m" "\033[1;93m$*\033[0m"; }; msg2() { eprintln "\033[1;96m ->\033[0m" "\033[1;93m$*\033[0m"; }; prompt() { eprint "\033[1;96m..>\033[0m" "\033[1;93m$*\033[0m"; }; fi mktmp() { ensure_tmp_dir; mktemp -p "$SHELL_LIBRARY_TEMP_PREFIX_DIR"; } ensure_tmp_dir() { if ! [ -d "$SHELL_LIBRARY_TEMP_PREFIX_DIR" ];then SHELL_LIBRARY_TEMP_PREFIX_DIR="$(mktemp -d)"; fi }; # A new version of tmp, which allows you to specify the commandline args as normal # arguments tmp() { if echo "$1" | grep -E ' ' -q; then warn "Detected an old version of tmp, as there are spaces in the input string!" fi TEMP_DIR_WITH_DEL="$(mktmp)"; "$@" 1> "$TEMP_DIR_WITH_DEL"; echo "$TEMP_DIR_WITH_DEL"; }; # Takes a path to search as argument. # Also takes further arguments as names to search for. # Prints the path to a file, if a file matching the given name is found. search_dir_for_file() { [ -d "$1" ] || die "Arg $1 is not a directory"; directory="$1" && shift 1; while read -r dir_entry; do dir_entry_count=$((dir_entry_count + 1)); dir_entry_basename="$(basename "$dir_entry")"; for name in "$@";do if [ "$name" = "$dir_entry_basename" ]; then println "$dir_entry"; fi done done < "$(tmp fd . "$directory" --type file --max-depth 1)" print ""; } # Returns the path to the directory which contains all the specified files: # `search_upward_files file1 file2 file3` returns a path containing file1 ... search_upward_files() { directory="$(pwd)"; final_directory=""; output="$(mktmp)"; while [ "$(wc -l < "$output")" = 0 ]; do search_dir_for_file "$directory" "$@" > "$output"; directory="$(dirname "$directory")"; if [ "$directory" = "/" ]; then warning "We bailed out, as there seems to be no directory containing $*"; final_directory=""; return; fi done final_directory="$(dirname "$(head -n1 "$output")")"; print "$final_directory"; } # }}} help() { cat << EOF A test manager (for trixy integration tests) USAGE: ./scripts/tests [OPTIONS] COMMAND OPTIONS: --help | -h Display this help and exit. COMMANDS: update [TESTNAME] Updates the 'expected.md' file of a test with TESTNAME, if TESTNAME is blank, all tests are updated. new TESTNAME Generates a new test from the '.template' directory and drops you into an editor for the 'input.tri' file. It will also generate the 'expected.md' file, after you close the editor. ARGUMENTS: TESTNAME | *([a-zA-Z0-9]) := [[ false ]] The name of a test. (The notation above is only really useful, when the shell library is employed to generate a completion script.) EOF } ROOT_DIR="$(search_upward_files "Cargo.toml")"; new() { test_name="$1"; test_dir="$ROOT_DIR/tests/$test_name"; [ -d "$test_dir" ] && die "$test_dir already exists, refusing to override" cp --recursive "$ROOT_DIR/tests/.template" "$test_dir" sed --in-place "s|template|$test_name|g" "$test_dir/main.rs" editor="${EDITOR:-$VI}" "$editor" "$test_dir/input.tri" update "$test_name" } update() { test_name="$1" test_dir="$ROOT_DIR/tests/$test_name"; if [ -n "$test_name" ]; then cargo run --features build-binary -- \ "$test_dir/input.tri" generate all --no-vendored \ > "$test_dir/expected.md" else fd . "$ROOT_DIR/tests" --type directory --max-depth=1 --exec basename | while read -r dir; do msg2 "Updating $dir.." update "$dir" done fi } for arg in "$@"; do case "$arg" in "--help" | "-h") help; exit 0; ;; esac done case "$1" in "update") shift 1; [ -n "$1" ] && test_name="$1" update "$test_name"; ;; "new") shift 1; test_name="$1"; [ -z "$test_name" ] && die "You must specify a TESTNAME" new "$test_name"; ;; esac # vim: ft=sh