1
0
mirror of https://github.com/go-task/task.git synced 2025-08-08 22:36:57 +02:00

feat: support looping over map variables (#1436)

* feat: support looping over map variables

* feat: add .KEY variable
This commit is contained in:
Pete Davison
2023-12-21 09:43:56 -06:00
committed by GitHub
parent 658b6012a6
commit b592648d55
3 changed files with 61 additions and 8 deletions

View File

@@ -63,8 +63,7 @@ tasks:
``` ```
There are many more templating functions which can be used with the new types of There are many more templating functions which can be used with the new types of
variables. For a full list, see the variables. For a full list, see the [slim-sprig][slim-sprig] documentation.
[slim-sprig][slim-sprig] documentation.
## Looping over variables ## Looping over variables
@@ -86,8 +85,8 @@ tasks:
cmd: echo {{.ITEM}} cmd: echo {{.ITEM}}
``` ```
Because this experiment adds support for array variables, the `for` keyword has Because this experiment adds support for "collection-type" variables, the `for`
been updated to support looping over arrays directly: keyword has been updated to support looping over arrays directly:
```yaml ```yaml
version: 3 version: 3
@@ -102,6 +101,30 @@ tasks:
cmd: echo {{.ITEM}} 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 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: always been able to loop over an array without using variables at all:

View File

@@ -9,6 +9,8 @@ tasks:
- task: string-array - task: string-array
- task: for-string - task: for-string
- task: for-int - task: for-int
- task: for-map
- task: for-multi-layer-map
dynamic: dynamic:
vars: vars:
@@ -78,3 +80,27 @@ tasks:
var: LIST var: LIST
cmd: echo {{add .ITEM 100}} 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}}

View File

@@ -133,6 +133,7 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
continue continue
} }
if cmd.For != nil { if cmd.For != nil {
var keys []string
var list []any var list []any
// Get the list from the explicit for list // Get the list from the explicit for list
if cmd.For.List != nil && len(cmd.For.List) > 0 { 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: case []any:
list = value list = value
case map[string]any: case map[string]any:
return &taskfile.Task{}, errors.TaskfileInvalidError{ for k, v := range value {
URI: origTask.Location.Taskfile, keys = append(keys, k)
Err: errors.New("sh is not supported with the 'Any Variables' experiment enabled.\nSee https://taskfile.dev/experiments/any-variables for more information."), list = append(list, v)
} }
default: default:
return nil, errors.TaskfileInvalidError{ return nil, errors.TaskfileInvalidError{
@@ -191,10 +192,13 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
as = "ITEM" as = "ITEM"
} }
// Create a new command for each item in the list // Create a new command for each item in the list
for _, loopValue := range list { for i, loopValue := range list {
extra := map[string]any{ extra := map[string]any{
as: loopValue, as: loopValue,
} }
if len(keys) > 0 {
extra["KEY"] = keys[i]
}
new.Cmds = append(new.Cmds, &taskfile.Cmd{ new.Cmds = append(new.Cmds, &taskfile.Cmd{
Cmd: r.ReplaceWithExtra(cmd.Cmd, extra), Cmd: r.ReplaceWithExtra(cmd.Cmd, extra),
Task: r.ReplaceWithExtra(cmd.Task, extra), Task: r.ReplaceWithExtra(cmd.Task, extra),