#compdef task # # Thin wrapper around `task __complete`. All suggestion logic lives in the # Go engine — do not add completion logic here. TASK_CMD="${TASK_EXE:-task}" _task() { local -a args lines completions 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 # Map the zsh completion zstyles to engine flags. `-T` is true when the # style is unset (its default) or explicitly true, so a flag is only passed # when the user turned the style off. zstyle -T ":completion:${curcontext}:" show-aliases || ctl+=(--no-aliases) zstyle -T ":completion:${curcontext}:" verbose || ctl+=(--no-descriptions) # (@) preserves a trailing empty string, which the engine relies on to # know the cursor is on a fresh word. 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 _files -g "(${(j:|:)globs})" return fi if (( directive & FILTER_DIRS )); then _path_files -/ return fi # `:` inside the value must be escaped: _describe splits on the first # unescaped colon (e.g. "docs:serve" would otherwise become value "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 (( directive & NO_SPACE )) && opts+=(-S '') (( directive & KEEP_ORDER )) && opts+=(-V) if (( ${#completions} > 0 )); then _describe -t tasks 'task' completions "${opts[@]}" fi (( directive & NO_FILE_COMP )) && return _files } compdef _task "$TASK_CMD"