mirror of
https://github.com/go-task/task.git
synced 2025-01-20 04:59:37 +02:00
feat: support looping over map variables (#1436)
* feat: support looping over map variables * feat: add .KEY variable
This commit is contained in:
parent
658b6012a6
commit
b592648d55
@ -63,8 +63,7 @@ tasks:
|
||||
```
|
||||
|
||||
There are many more templating functions which can be used with the new types of
|
||||
variables. For a full list, see the
|
||||
[slim-sprig][slim-sprig] documentation.
|
||||
variables. For a full list, see the [slim-sprig][slim-sprig] documentation.
|
||||
|
||||
## Looping over variables
|
||||
|
||||
@ -86,8 +85,8 @@ tasks:
|
||||
cmd: echo {{.ITEM}}
|
||||
```
|
||||
|
||||
Because this experiment adds support for array variables, the `for` keyword has
|
||||
been updated to support looping over arrays directly:
|
||||
Because this experiment adds support for "collection-type" variables, the `for`
|
||||
keyword has been updated to support looping over arrays directly:
|
||||
|
||||
```yaml
|
||||
version: 3
|
||||
@ -102,6 +101,30 @@ tasks:
|
||||
cmd: echo {{.ITEM}}
|
||||
```
|
||||
|
||||
This also works for maps. When looping over a map we also make an additional
|
||||
`{{.KEY}}` variable availabe that holds the string value of the map key.
|
||||
Remember that maps are unordered, so the order in which the items are looped
|
||||
over is random:
|
||||
|
||||
```yaml
|
||||
version: 3
|
||||
|
||||
tasks:
|
||||
foo:
|
||||
vars:
|
||||
MAP:
|
||||
KEY_1:
|
||||
SUBKEY: sub_value_1
|
||||
KEY_2:
|
||||
SUBKEY: sub_value_2
|
||||
KEY_3:
|
||||
SUBKEY: sub_value_3
|
||||
cmds:
|
||||
- for:
|
||||
var: MAP
|
||||
cmd: echo {{.KEY}} {{.ITEM.SUBKEY}}
|
||||
```
|
||||
|
||||
String splitting is still supported and remember that for simple cases, you have
|
||||
always been able to loop over an array without using variables at all:
|
||||
|
||||
|
26
testdata/vars/any/Taskfile.yml
vendored
26
testdata/vars/any/Taskfile.yml
vendored
@ -9,6 +9,8 @@ tasks:
|
||||
- task: string-array
|
||||
- task: for-string
|
||||
- task: for-int
|
||||
- task: for-map
|
||||
- task: for-multi-layer-map
|
||||
|
||||
dynamic:
|
||||
vars:
|
||||
@ -78,3 +80,27 @@ tasks:
|
||||
var: LIST
|
||||
cmd: echo {{add .ITEM 100}}
|
||||
|
||||
for-map:
|
||||
vars:
|
||||
MAP:
|
||||
KEY_1: value_1
|
||||
KEY_2: value_2
|
||||
KEY_3: value_3
|
||||
cmds:
|
||||
- for:
|
||||
var: MAP
|
||||
cmd: echo {{.KEY}} {{.ITEM}}
|
||||
|
||||
for-multi-layer-map:
|
||||
vars:
|
||||
MAP:
|
||||
KEY_1:
|
||||
SUBKEY: sub_value_1
|
||||
KEY_2:
|
||||
SUBKEY: sub_value_2
|
||||
KEY_3:
|
||||
SUBKEY: sub_value_3
|
||||
cmds:
|
||||
- for:
|
||||
var: MAP
|
||||
cmd: echo {{.KEY}} {{.ITEM.SUBKEY}}
|
||||
|
12
variables.go
12
variables.go
@ -133,6 +133,7 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
|
||||
continue
|
||||
}
|
||||
if cmd.For != nil {
|
||||
var keys []string
|
||||
var list []any
|
||||
// Get the list from the explicit for list
|
||||
if cmd.For.List != nil && len(cmd.For.List) > 0 {
|
||||
@ -170,9 +171,9 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
|
||||
case []any:
|
||||
list = value
|
||||
case map[string]any:
|
||||
return &taskfile.Task{}, errors.TaskfileInvalidError{
|
||||
URI: origTask.Location.Taskfile,
|
||||
Err: errors.New("sh is not supported with the 'Any Variables' experiment enabled.\nSee https://taskfile.dev/experiments/any-variables for more information."),
|
||||
for k, v := range value {
|
||||
keys = append(keys, k)
|
||||
list = append(list, v)
|
||||
}
|
||||
default:
|
||||
return nil, errors.TaskfileInvalidError{
|
||||
@ -191,10 +192,13 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
|
||||
as = "ITEM"
|
||||
}
|
||||
// Create a new command for each item in the list
|
||||
for _, loopValue := range list {
|
||||
for i, loopValue := range list {
|
||||
extra := map[string]any{
|
||||
as: loopValue,
|
||||
}
|
||||
if len(keys) > 0 {
|
||||
extra["KEY"] = keys[i]
|
||||
}
|
||||
new.Cmds = append(new.Cmds, &taskfile.Cmd{
|
||||
Cmd: r.ReplaceWithExtra(cmd.Cmd, extra),
|
||||
Task: r.ReplaceWithExtra(cmd.Task, extra),
|
||||
|
Loading…
x
Reference in New Issue
Block a user