Skip to content

Commit a085d62

Browse files
authored
feat(completion): add missing flags and dynamic experimental feature detection (#2532)
1 parent 4ab1958 commit a085d62

File tree

4 files changed

+219
-53
lines changed

4 files changed

+219
-53
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
`env:`, and `requires:` sections. Dynamic variables show their shell command
1111
(e.g., `sh: echo "hello"`) instead of the evaluated value (#2486 ,#2524 by
1212
@vmaerten).
13+
- Improved shell completion scripts (Zsh, Fish, PowerShell) by adding missing
14+
flags and dynamic experimental feature detection (#2532 by @vmaerten).
1315

1416
## v3.45.5 - 2025-11-11
1517

completion/fish/task.fish

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,32 @@
11
set -l GO_TASK_PROGNAME task
22

3+
# Cache variables for experiments (global)
4+
set -g __task_experiments_cache ""
5+
set -g __task_experiments_cache_time 0
6+
7+
# Helper function to get experiments with 1-second cache
8+
function __task_get_experiments
9+
set -l now (date +%s)
10+
set -l ttl 1 # Cache for 1 second only
11+
12+
# Return cached value if still valid
13+
if test (math "$now - $__task_experiments_cache_time") -lt $ttl
14+
printf '%s\n' $__task_experiments_cache
15+
return
16+
end
17+
18+
# Refresh cache
19+
set -g __task_experiments_cache (task --experiments 2>/dev/null)
20+
set -g __task_experiments_cache_time $now
21+
printf '%s\n' $__task_experiments_cache
22+
end
23+
24+
# Helper function to check if an experiment is enabled
25+
function __task_is_experiment_enabled
26+
set -l experiment $argv[1]
27+
__task_get_experiments | string match -qr "^\* $experiment:.*on"
28+
end
29+
330
function __task_get_tasks --description "Prints all available tasks with their description" --inherit-variable GO_TASK_PROGNAME
431
# Check if the global task is requested
532
set -l global_task false
@@ -36,19 +63,49 @@ end
3663
complete -c $GO_TASK_PROGNAME -d 'Runs the specified task(s). Falls back to the "default" task if no task name was specified, or lists all tasks if an unknown task name was
3764
specified.' -xa "(__task_get_tasks)"
3865

39-
complete -c $GO_TASK_PROGNAME -s c -l color -d 'colored output (default true)'
40-
complete -c $GO_TASK_PROGNAME -s d -l dir -d 'sets directory of execution'
41-
complete -c $GO_TASK_PROGNAME -l dry -d 'compiles and prints tasks in the order that they would be run, without executing them'
42-
complete -c $GO_TASK_PROGNAME -s f -l force -d 'forces execution even when the task is up-to-date'
43-
complete -c $GO_TASK_PROGNAME -s h -l help -d 'shows Task usage'
44-
complete -c $GO_TASK_PROGNAME -s i -l init -d 'creates a new Taskfile.yml in the current folder'
45-
complete -c $GO_TASK_PROGNAME -s l -l list -d 'lists tasks with description of current Taskfile'
46-
complete -c $GO_TASK_PROGNAME -s o -l output -d 'sets output style: [interleaved|group|prefixed]' -xa "interleaved group prefixed"
47-
complete -c $GO_TASK_PROGNAME -s p -l parallel -d 'executes tasks provided on command line in parallel'
48-
complete -c $GO_TASK_PROGNAME -s s -l silent -d 'disables echoing'
49-
complete -c $GO_TASK_PROGNAME -l status -d 'exits with non-zero exit code if any of the given tasks is not up-to-date'
50-
complete -c $GO_TASK_PROGNAME -l summary -d 'show summary about a task'
51-
complete -c $GO_TASK_PROGNAME -s t -l taskfile -d 'choose which Taskfile to run. Defaults to "Taskfile.yml"'
52-
complete -c $GO_TASK_PROGNAME -s v -l verbose -d 'enables verbose mode'
53-
complete -c $GO_TASK_PROGNAME -l version -d 'show Task version'
54-
complete -c $GO_TASK_PROGNAME -s w -l watch -d 'enables watch of the given task'
66+
# Standard flags
67+
complete -c $GO_TASK_PROGNAME -s a -l list-all -d 'list all tasks'
68+
complete -c $GO_TASK_PROGNAME -s c -l color -d 'colored output (default true)'
69+
complete -c $GO_TASK_PROGNAME -s C -l concurrency -d 'limit number of concurrent tasks'
70+
complete -c $GO_TASK_PROGNAME -l completion -d 'generate shell completion script' -xa "bash zsh fish powershell"
71+
complete -c $GO_TASK_PROGNAME -s d -l dir -d 'set directory of execution'
72+
complete -c $GO_TASK_PROGNAME -s n -l dry -d 'compile and print tasks without executing'
73+
complete -c $GO_TASK_PROGNAME -s x -l exit-code -d 'pass-through exit code of task command'
74+
complete -c $GO_TASK_PROGNAME -l experiments -d 'list available experiments'
75+
complete -c $GO_TASK_PROGNAME -s f -l force -d 'force execution even when up-to-date'
76+
complete -c $GO_TASK_PROGNAME -s g -l global -d 'run global Taskfile from home directory'
77+
complete -c $GO_TASK_PROGNAME -s h -l help -d 'show help'
78+
complete -c $GO_TASK_PROGNAME -s i -l init -d 'create new Taskfile'
79+
complete -c $GO_TASK_PROGNAME -l insecure -d 'allow insecure Taskfile downloads'
80+
complete -c $GO_TASK_PROGNAME -s I -l interval -d 'interval to watch for changes'
81+
complete -c $GO_TASK_PROGNAME -s j -l json -d 'format task list as JSON'
82+
complete -c $GO_TASK_PROGNAME -s l -l list -d 'list tasks with descriptions'
83+
complete -c $GO_TASK_PROGNAME -l nested -d 'nest namespaces when listing as JSON'
84+
complete -c $GO_TASK_PROGNAME -l no-status -d 'ignore status when listing as JSON'
85+
complete -c $GO_TASK_PROGNAME -s o -l output -d 'set output style' -xa "interleaved group prefixed"
86+
complete -c $GO_TASK_PROGNAME -l output-group-begin -d 'message template before grouped output'
87+
complete -c $GO_TASK_PROGNAME -l output-group-end -d 'message template after grouped output'
88+
complete -c $GO_TASK_PROGNAME -l output-group-error-only -d 'hide output from successful tasks'
89+
complete -c $GO_TASK_PROGNAME -s p -l parallel -d 'execute tasks in parallel'
90+
complete -c $GO_TASK_PROGNAME -s s -l silent -d 'disable echoing'
91+
complete -c $GO_TASK_PROGNAME -l sort -d 'set task sorting order' -xa "default alphanumeric none"
92+
complete -c $GO_TASK_PROGNAME -l status -d 'exit non-zero if tasks not up-to-date'
93+
complete -c $GO_TASK_PROGNAME -l summary -d 'show task summary'
94+
complete -c $GO_TASK_PROGNAME -s t -l taskfile -d 'choose Taskfile to run'
95+
complete -c $GO_TASK_PROGNAME -s v -l verbose -d 'verbose output'
96+
complete -c $GO_TASK_PROGNAME -l version -d 'show version'
97+
complete -c $GO_TASK_PROGNAME -s w -l watch -d 'watch mode, re-run on changes'
98+
complete -c $GO_TASK_PROGNAME -s y -l yes -d 'assume yes to all prompts'
99+
100+
# Experimental flags (dynamically checked at completion time via -n condition)
101+
# GentleForce experiment
102+
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled GENTLE_FORCE" -l force-all -d 'force execution of task and all dependencies'
103+
104+
# RemoteTaskfiles experiment - Options
105+
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l offline -d 'use only local or cached Taskfiles'
106+
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l timeout -d 'timeout for remote Taskfile downloads'
107+
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l expiry -d 'cache expiry duration'
108+
109+
# RemoteTaskfiles experiment - Operations
110+
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l download -d 'download remote Taskfile'
111+
complete -c $GO_TASK_PROGNAME -n "__task_is_experiment_enabled REMOTE_TASKFILES" -l clear-cache -d 'clear remote Taskfile cache'

completion/ps/task.ps1

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,78 @@ Register-ArgumentCompleter -CommandName task -ScriptBlock {
55

66
if ($commandName.StartsWith('-')) {
77
$completions = @(
8-
[CompletionResult]::new('--list-all ', '--list-all ', [CompletionResultType]::ParameterName, 'list all tasks'),
9-
[CompletionResult]::new('--color ', '--color', [CompletionResultType]::ParameterName, '--color'),
10-
[CompletionResult]::new('--concurrency=', '--concurrency=', [CompletionResultType]::ParameterName, 'concurrency'),
11-
[CompletionResult]::new('--interval=', '--interval=', [CompletionResultType]::ParameterName, 'interval'),
12-
[CompletionResult]::new('--output=interleaved ', '--output=interleaved', [CompletionResultType]::ParameterName, '--output='),
13-
[CompletionResult]::new('--output=group ', '--output=group', [CompletionResultType]::ParameterName, '--output='),
14-
[CompletionResult]::new('--output=prefixed ', '--output=prefixed', [CompletionResultType]::ParameterName, '--output='),
15-
[CompletionResult]::new('--dry ', '--dry', [CompletionResultType]::ParameterName, '--dry'),
16-
[CompletionResult]::new('--force ', '--force', [CompletionResultType]::ParameterName, '--force'),
17-
[CompletionResult]::new('--parallel ', '--parallel', [CompletionResultType]::ParameterName, '--parallel'),
18-
[CompletionResult]::new('--silent ', '--silent', [CompletionResultType]::ParameterName, '--silent'),
19-
[CompletionResult]::new('--status ', '--status', [CompletionResultType]::ParameterName, '--status'),
20-
[CompletionResult]::new('--verbose ', '--verbose', [CompletionResultType]::ParameterName, '--verbose'),
21-
[CompletionResult]::new('--watch ', '--watch', [CompletionResultType]::ParameterName, '--watch')
8+
# Standard flags (alphabetical order)
9+
[CompletionResult]::new('-a', '-a', [CompletionResultType]::ParameterName, 'list all tasks'),
10+
[CompletionResult]::new('--list-all', '--list-all', [CompletionResultType]::ParameterName, 'list all tasks'),
11+
[CompletionResult]::new('-c', '-c', [CompletionResultType]::ParameterName, 'colored output'),
12+
[CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'colored output'),
13+
[CompletionResult]::new('-C', '-C', [CompletionResultType]::ParameterName, 'limit concurrent tasks'),
14+
[CompletionResult]::new('--concurrency', '--concurrency', [CompletionResultType]::ParameterName, 'limit concurrent tasks'),
15+
[CompletionResult]::new('--completion', '--completion', [CompletionResultType]::ParameterName, 'generate shell completion'),
16+
[CompletionResult]::new('-d', '-d', [CompletionResultType]::ParameterName, 'set directory'),
17+
[CompletionResult]::new('--dir', '--dir', [CompletionResultType]::ParameterName, 'set directory'),
18+
[CompletionResult]::new('-n', '-n', [CompletionResultType]::ParameterName, 'dry run'),
19+
[CompletionResult]::new('--dry', '--dry', [CompletionResultType]::ParameterName, 'dry run'),
20+
[CompletionResult]::new('-x', '-x', [CompletionResultType]::ParameterName, 'pass-through exit code'),
21+
[CompletionResult]::new('--exit-code', '--exit-code', [CompletionResultType]::ParameterName, 'pass-through exit code'),
22+
[CompletionResult]::new('--experiments', '--experiments', [CompletionResultType]::ParameterName, 'list experiments'),
23+
[CompletionResult]::new('-f', '-f', [CompletionResultType]::ParameterName, 'force execution'),
24+
[CompletionResult]::new('--force', '--force', [CompletionResultType]::ParameterName, 'force execution'),
25+
[CompletionResult]::new('-g', '-g', [CompletionResultType]::ParameterName, 'run global Taskfile'),
26+
[CompletionResult]::new('--global', '--global', [CompletionResultType]::ParameterName, 'run global Taskfile'),
27+
[CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'show help'),
28+
[CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'show help'),
29+
[CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'create new Taskfile'),
30+
[CompletionResult]::new('--init', '--init', [CompletionResultType]::ParameterName, 'create new Taskfile'),
31+
[CompletionResult]::new('--insecure', '--insecure', [CompletionResultType]::ParameterName, 'allow insecure downloads'),
32+
[CompletionResult]::new('-I', '-I', [CompletionResultType]::ParameterName, 'watch interval'),
33+
[CompletionResult]::new('--interval', '--interval', [CompletionResultType]::ParameterName, 'watch interval'),
34+
[CompletionResult]::new('-j', '-j', [CompletionResultType]::ParameterName, 'format as JSON'),
35+
[CompletionResult]::new('--json', '--json', [CompletionResultType]::ParameterName, 'format as JSON'),
36+
[CompletionResult]::new('-l', '-l', [CompletionResultType]::ParameterName, 'list tasks'),
37+
[CompletionResult]::new('--list', '--list', [CompletionResultType]::ParameterName, 'list tasks'),
38+
[CompletionResult]::new('--nested', '--nested', [CompletionResultType]::ParameterName, 'nest namespaces in JSON'),
39+
[CompletionResult]::new('--no-status', '--no-status', [CompletionResultType]::ParameterName, 'ignore status in JSON'),
40+
[CompletionResult]::new('-o', '-o', [CompletionResultType]::ParameterName, 'set output style'),
41+
[CompletionResult]::new('--output', '--output', [CompletionResultType]::ParameterName, 'set output style'),
42+
[CompletionResult]::new('--output-group-begin', '--output-group-begin', [CompletionResultType]::ParameterName, 'template before group'),
43+
[CompletionResult]::new('--output-group-end', '--output-group-end', [CompletionResultType]::ParameterName, 'template after group'),
44+
[CompletionResult]::new('--output-group-error-only', '--output-group-error-only', [CompletionResultType]::ParameterName, 'hide successful output'),
45+
[CompletionResult]::new('-p', '-p', [CompletionResultType]::ParameterName, 'execute in parallel'),
46+
[CompletionResult]::new('--parallel', '--parallel', [CompletionResultType]::ParameterName, 'execute in parallel'),
47+
[CompletionResult]::new('-s', '-s', [CompletionResultType]::ParameterName, 'silent mode'),
48+
[CompletionResult]::new('--silent', '--silent', [CompletionResultType]::ParameterName, 'silent mode'),
49+
[CompletionResult]::new('--sort', '--sort', [CompletionResultType]::ParameterName, 'task sorting order'),
50+
[CompletionResult]::new('--status', '--status', [CompletionResultType]::ParameterName, 'check task status'),
51+
[CompletionResult]::new('--summary', '--summary', [CompletionResultType]::ParameterName, 'show task summary'),
52+
[CompletionResult]::new('-t', '-t', [CompletionResultType]::ParameterName, 'choose Taskfile'),
53+
[CompletionResult]::new('--taskfile', '--taskfile', [CompletionResultType]::ParameterName, 'choose Taskfile'),
54+
[CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'verbose output'),
55+
[CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'verbose output'),
56+
[CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'show version'),
57+
[CompletionResult]::new('-w', '-w', [CompletionResultType]::ParameterName, 'watch mode'),
58+
[CompletionResult]::new('--watch', '--watch', [CompletionResultType]::ParameterName, 'watch mode'),
59+
[CompletionResult]::new('-y', '-y', [CompletionResultType]::ParameterName, 'assume yes'),
60+
[CompletionResult]::new('--yes', '--yes', [CompletionResultType]::ParameterName, 'assume yes')
2261
)
2362

63+
# Experimental flags (dynamically added based on enabled experiments)
64+
$experiments = & task --experiments 2>$null | Out-String
65+
66+
if ($experiments -match '\* GENTLE_FORCE:.*on') {
67+
$completions += [CompletionResult]::new('--force-all', '--force-all', [CompletionResultType]::ParameterName, 'force all dependencies')
68+
}
69+
70+
if ($experiments -match '\* REMOTE_TASKFILES:.*on') {
71+
# Options
72+
$completions += [CompletionResult]::new('--offline', '--offline', [CompletionResultType]::ParameterName, 'use cached Taskfiles')
73+
$completions += [CompletionResult]::new('--timeout', '--timeout', [CompletionResultType]::ParameterName, 'download timeout')
74+
$completions += [CompletionResult]::new('--expiry', '--expiry', [CompletionResultType]::ParameterName, 'cache expiry')
75+
# Operations
76+
$completions += [CompletionResult]::new('--download', '--download', [CompletionResultType]::ParameterName, 'download remote Taskfile')
77+
$completions += [CompletionResult]::new('--clear-cache', '--clear-cache', [CompletionResultType]::ParameterName, 'clear cache')
78+
}
79+
2480
return $completions.Where{ $_.CompletionText.StartsWith($commandName) }
2581
}
2682

0 commit comments

Comments
 (0)