mirror of
https://github.com/go-task/task.git
synced 2026-09-01 11:39:28 +02:00
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.
95 lines
2.3 KiB
Bash
95 lines
2.3 KiB
Bash
# vim: set tabstop=2 shiftwidth=2 expandtab:
|
|
#
|
|
# Thin wrapper around `task __complete`: all suggestion logic lives in the Go engine.
|
|
|
|
TASK_CMD="${TASK_EXE:-task}"
|
|
|
|
# `=` stays inside the current word (see `_init_completion -n =:`), so an inline
|
|
# `--flag=` prefix must be stripped before _filedir and re-applied after.
|
|
_task_filedir() {
|
|
local fpfx="" savecur="$cur"
|
|
if [[ "$cur" == -*=* ]]; then
|
|
fpfx="${cur%%=*}="
|
|
cur="${cur#*=}"
|
|
fi
|
|
_filedir ${1:+"$1"}
|
|
cur="$savecur"
|
|
if [[ -n "$fpfx" ]]; then
|
|
COMPREPLY=( ${COMPREPLY[@]+"${COMPREPLY[@]/#/$fpfx}"} )
|
|
fi
|
|
}
|
|
|
|
_task() {
|
|
local cur prev words cword
|
|
|
|
# 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
|
|
|
|
# `=` and `:` out of the word breaks: `--output=`, `docs:serve` stay one token.
|
|
_init_completion -n =: || return
|
|
|
|
local -a args=( "${words[@]:1:cword}" )
|
|
if (( ${#args[@]} == 0 )); then
|
|
args=( "" )
|
|
fi
|
|
|
|
local output
|
|
output=$("$TASK_CMD" __complete "${args[@]}" 2>/dev/null)
|
|
if [[ -z "$output" ]]; then
|
|
_task_filedir
|
|
return
|
|
fi
|
|
|
|
local -a lines=()
|
|
local line
|
|
while IFS= read -r line; do
|
|
lines+=( "$line" )
|
|
done <<< "$output"
|
|
|
|
local last_idx=$(( ${#lines[@]} - 1 ))
|
|
local directive="${lines[$last_idx]#:}"
|
|
unset 'lines[$last_idx]'
|
|
|
|
if (( directive & FILTER_FILE_EXT )); then
|
|
local exts=""
|
|
# ${arr[@]+…} guards an empty array under `set -u` in bash 3.2 (macOS).
|
|
for line in ${lines[@]+"${lines[@]}"}; do
|
|
exts+="${exts:+|}$line"
|
|
done
|
|
_task_filedir "@($exts)"
|
|
return
|
|
fi
|
|
|
|
if (( directive & FILTER_DIRS )); then
|
|
_task_filedir -d
|
|
return
|
|
fi
|
|
|
|
# Not `compgen -W`: it splits the word list on IFS, mangling values with spaces.
|
|
local value
|
|
COMPREPLY=()
|
|
for line in ${lines[@]+"${lines[@]}"}; do
|
|
value="${line%%$'\t'*}"
|
|
if [[ -z "$cur" || "$value" == "$cur"* ]]; then
|
|
COMPREPLY+=( "$value" )
|
|
fi
|
|
done
|
|
|
|
if (( directive & NO_SPACE )); then
|
|
compopt -o nospace 2>/dev/null
|
|
fi
|
|
|
|
# nosort needs bash 4.4; the 3.2 shipped by macOS ignores it and stays sorted.
|
|
if (( directive & KEEP_ORDER )); then
|
|
compopt -o nosort 2>/dev/null
|
|
fi
|
|
|
|
__ltrim_colon_completions "$cur"
|
|
|
|
if (( ${#COMPREPLY[@]} == 0 )) && ! (( directive & NO_FILE_COMP )); then
|
|
_task_filedir
|
|
fi
|
|
}
|
|
|
|
complete -F _task "$TASK_CMD"
|