Files
task/completion/zsh/_task
Valentin Maerten b782d18a45 feat(completion): make the engine the default behind --completion
The engine shipped opt-in behind --new-completion, with the old scripts
still on --completion. That split was never released, so flip it now
rather than carry a third flag through a deprecation later.

--completion serves the engine wrappers; the hand-written scripts move to
completion/legacy/ and stay reachable via --legacy-completion for a
release or two.

.goreleaser.yml needed to follow: it packages the static files from
completion/ into the deb/rpm/apk contents and the Homebrew cask, so
leaving it untouched would have shipped the engine to anyone running
`eval "$(task --completion zsh)"` and the old scripts to everyone
installing from a package. The paths it references are unchanged and now
resolve to the wrappers. Its archive glob is narrowed at the same time,
so the test harness under completion/tests/ stops being shipped in the
release archives.
2026-08-29 10:55:16 +02:00

77 lines
2.1 KiB
Plaintext
Executable File

#compdef task
#
# Thin wrapper around `task __complete`: all suggestion logic lives in the Go engine.
TASK_CMD="${TASK_EXE:-task}"
_task() {
local -a args lines completions describe_opts compadd_opts ctl
local output directive line
# Completion directives, mirroring internal/complete/complete.go.
local -ri NO_SPACE=2 NO_FILE_COMP=4 FILTER_FILE_EXT=8 FILTER_DIRS=16 KEEP_ORDER=32
# `-T` is true when the style is unset, so a flag goes out only when it is off.
zstyle -T ":completion:${curcontext}:" show-aliases || ctl+=(--no-aliases)
zstyle -T ":completion:${curcontext}:" verbose || ctl+=(--no-descriptions)
# (@) preserves the trailing empty word the engine reads as a fresh cursor.
args=("${(@)words[2,CURRENT]}")
(( ${#args} == 0 )) && args=("")
output=$("$TASK_CMD" __complete "${ctl[@]}" "${args[@]}" 2>/dev/null)
if [[ -z "$output" ]]; then
_files
return
fi
lines=("${(f)output}")
directive="${lines[-1]#:}"
lines=("${(@)lines[1,-2]}")
if (( directive & FILTER_FILE_EXT )); then
local -a globs
for line in "${lines[@]}"; do
globs+=("*.${line}")
done
# Inline `--flag=` into IPREFIX so file completion runs on the value. Only
# here: globally it would break `_describe` on inline enums.
compset -P '*='
_files -g "(${(j:|:)globs})"
return
fi
if (( directive & FILTER_DIRS )); then
compset -P '*='
_path_files -/
return
fi
# _describe splits on the first unescaped colon: "docs:serve" → "docs".
local value desc
for line in "${lines[@]}"; do
if [[ "$line" == *$'\t'* ]]; then
value="${line%%$'\t'*}"
desc="${line#*$'\t'}"
completions+=("${value//:/\\:}:$desc")
else
completions+=("${line//:/\\:}")
fi
done
# -S is a compadd option, passed after the array; -V belongs to _describe.
# In the compadd zone it would take the next argument as a group name.
(( directive & NO_SPACE )) && compadd_opts+=(-S '')
(( directive & KEEP_ORDER )) && describe_opts+=(-V)
if (( ${#completions} > 0 )); then
_describe "${describe_opts[@]}" -t tasks 'task' completions "${compadd_opts[@]}"
fi
(( directive & NO_FILE_COMP )) && return
compset -P '*='
_files
}
compdef _task "$TASK_CMD"