mirror of
https://github.com/go-task/task.git
synced 2026-09-02 12:16:04 +02:00
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.
This commit is contained in:
@@ -1,60 +1,94 @@
|
||||
# vim: set tabstop=2 shiftwidth=2 expandtab:
|
||||
#
|
||||
# Thin wrapper around `task __complete`: all suggestion logic lives in the Go engine.
|
||||
|
||||
_GO_TASK_COMPLETION_LIST_OPTION='--list-all'
|
||||
TASK_CMD="${TASK_EXE:-task}"
|
||||
|
||||
function _task()
|
||||
{
|
||||
local cur prev words cword
|
||||
_init_completion -n : || return
|
||||
# `=` 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
|
||||
}
|
||||
|
||||
# Check for `--` within command-line and quit or strip suffix.
|
||||
local i
|
||||
for i in "${!words[@]}"; do
|
||||
if [ "${words[$i]}" == "--" ]; then
|
||||
# Do not complete words following `--` passed to CLI_ARGS.
|
||||
[ $cword -gt $i ] && return
|
||||
# Remove the words following `--` to not put --list in CLI_ARGS.
|
||||
words=( "${words[@]:0:$i}" )
|
||||
break
|
||||
_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
|
||||
|
||||
# Handle special arguments of options.
|
||||
case "$prev" in
|
||||
-d|--dir|--remote-cache-dir)
|
||||
_filedir -d
|
||||
return $?
|
||||
;;
|
||||
--cacert|--cert|--cert-key)
|
||||
_filedir
|
||||
return $?
|
||||
;;
|
||||
-t|--taskfile)
|
||||
_filedir yaml || return $?
|
||||
_filedir yml
|
||||
return $?
|
||||
;;
|
||||
-o|--output)
|
||||
COMPREPLY=( $( compgen -W "interleaved group prefixed" -- $cur ) )
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
if (( directive & NO_SPACE )); then
|
||||
compopt -o nospace 2>/dev/null
|
||||
fi
|
||||
|
||||
# Handle normal options.
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W "$(_parse_help $1)" -- $cur ) )
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
# 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
|
||||
|
||||
# Prepare task name completions.
|
||||
local tasks=( $( "${words[@]}" --silent $_GO_TASK_COMPLETION_LIST_OPTION 2> /dev/null ) )
|
||||
COMPREPLY=( $( compgen -W "${tasks[*]}" -- "$cur" ) )
|
||||
|
||||
# Post-process because task names might contain colons.
|
||||
__ltrim_colon_completions "$cur"
|
||||
|
||||
if (( ${#COMPREPLY[@]} == 0 )) && ! (( directive & NO_FILE_COMP )); then
|
||||
_task_filedir
|
||||
fi
|
||||
}
|
||||
|
||||
complete -F _task "$TASK_CMD"
|
||||
|
||||
Reference in New Issue
Block a user