Files
task/testdata/completion/run.sh

99 lines
2.6 KiB
Bash
Raw Permalink Normal View History

#!/usr/bin/env bash
# Builds the task binary and a fixture Taskfile, then runs every installed shell
# wrapper against them. The engine itself is covered by the Go tests.
set -u
fix(completion): complete task names and required vars together CLI variables are global to the invocation, not scoped to a task: `args.Parse` turns every word holding `=` into a global and every other word into a call, so `task build ENV=dev deploy` and `task build deploy ENV=dev` are the same command. The engine assumed the opposite and, as soon as a word matched a task, served only that task's variables — nothing at all when it had none. `task build <TAB>` and even `task build de<TAB>` went silent, where all five legacy wrappers offered task names at every position. The engine now unions the still-unset requirements of every task named on the line, and falls through to task names once they are all set. The line resolves itself: fill in what blocks execution, then add another task. Keeping the two families exclusive means each keeps a coherent directive, so nothing loses its trailing space. Task words are matched with FindMatchingTasks instead of a hand-built list of names truncated at their first `*`, which is why `task wildcard-foo <TAB>` used to offer task names rather than the variables of `wildcard-*`. Completion also disables fuzzy matching: a suggestion list has no "did you mean". Three fixes ride along. `--sort default` left the sorter nil and cleared the one NewExecutor had set, so completion listed tasks in Taskfile order while `--list` sorted them — and a single templated description silently restored the sort through GetTaskList. The bash wrapper never defined KeepOrder, losing the declaration order of `requires`; it now passes `compopt -o nosort`, which bash 3.2 ignores as it already ignores nospace. And the shell suite unsets TASK_EXE and GO_TASK_PROGNAME: fish, Nushell and PowerShell resolve the binary through them, so an ambient value silently tested something other than the binary just built.
2026-08-20 16:11:49 +02:00
# fish, Nushell and PowerShell resolve the binary through these; an ambient value
# would silently test something other than the binary built below.
unset TASK_EXE GO_TASK_PROGNAME
here=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
root=$(cd "$here/../.." && pwd)
bindir=$(mktemp -d)
fixture=$(mktemp -d)
trap 'rm -rf "$bindir" "$fixture"' EXIT
if ! go build -o "$bindir/task" "$root/cmd/task"; then
echo "failed to build task binary" >&2
exit 1
fi
export TASK_BIN="$bindir/task"
# fish and PowerShell register completion for the command name `task`.
export PATH="$bindir:$PATH"
cat > "$fixture/Taskfile.yml" <<'YML'
version: '3'
tasks:
build:
desc: Build it
deploy:
desc: Deploy it
aliases: [dep]
requires:
vars:
- name: ENV
enum: [dev, prod]
- REGION
docs:serve:
desc: Serve docs
YML
touch "$fixture/extra.yaml" "$fixture/notes.txt"
mkdir -p "$fixture/sub" "$fixture/other"
# Nested path completion must keep the directory prefix.
touch "$fixture/sub/nested.yml"
# Shells must pass a quoted `--dir` value to the engine unquoted, and quote it
# back on insert.
mkdir -p "$fixture/with space"
cat > "$fixture/with space/Taskfile.yml" <<'YML'
version: '3'
tasks:
spaced:
desc: Task from the spaced dir
YML
export TASK_FIXTURE="$fixture"
# Strict mode (CI) turns a missing shell into a failure instead of a skip, so an
# absent pwsh never reads as a pass.
strict=${TASK_COMPLETION_STRICT:-}
fails=0
run() { # LABEL COMMAND...
echo "== $1 =="
"${@:2}" || fails=$((fails + 1))
echo
}
run_if() { # BIN LABEL COMMAND...
if command -v "$1" >/dev/null 2>&1; then run "${@:2}"; else skip "$2"; fi
}
skip() { # LABEL
if [[ -n "$strict" ]]; then
echo "== $1 == (MISSING — required under TASK_COMPLETION_STRICT)"
fails=$((fails + 1))
else
echo "== $1 == (skipped: not installed)"
fi
echo
}
run "bash wrapper" bash "$here/wrapper.bash"
run_if zsh "zsh wrapper" zsh "$here/wrapper.zsh"
run_if fish "fish wrapper" fish "$here/wrapper.fish"
# --no-config-file: the user's own external completer must not interfere.
run_if nu "nu wrapper" nu --no-config-file "$here/wrapper.nu"
pwsh_bin=$(command -v pwsh || command -v pwsh-preview || true)
if [[ -n "$pwsh_bin" ]]; then
run "powershell wrapper" "$pwsh_bin" -NoProfile -File "$here/wrapper.ps1"
else
skip "powershell wrapper"
fi
if ((fails)); then
echo "completion tests: $fails suite(s) failed"
exit 1
fi
echo "completion tests: all suites passed"