1
0
mirror of https://github.com/go-task/task.git synced 2025-06-23 00:38:19 +02:00

feat: allow variable references in a matrix (#2069)

This commit is contained in:
Pete Davison
2025-02-23 18:13:56 +00:00
committed by GitHub
parent a31f2cf4a8
commit d6234af49a
5 changed files with 185 additions and 39 deletions

View File

@ -10,15 +10,25 @@ import (
"github.com/go-task/task/v3/internal/deepcopy"
)
type Matrix struct {
om *orderedmap.OrderedMap[string, []any]
}
type MatrixElement orderedmap.Element[string, []any]
type (
// Matrix is an ordered map of variable names to arrays of values.
Matrix struct {
om *orderedmap.OrderedMap[string, *MatrixRow]
}
// A MatrixElement is a key-value pair that is used for initializing a
// Matrix structure.
MatrixElement orderedmap.Element[string, *MatrixRow]
// A MatrixRow list of values for a matrix key or a reference to another
// variable.
MatrixRow struct {
Ref string
Value []any
}
)
func NewMatrix(els ...*MatrixElement) *Matrix {
matrix := &Matrix{
om: orderedmap.NewOrderedMap[string, []any](),
om: orderedmap.NewOrderedMap[string, *MatrixRow](),
}
for _, el := range els {
matrix.Set(el.Key, el.Value)
@ -33,27 +43,27 @@ func (matrix *Matrix) Len() int {
return matrix.om.Len()
}
func (matrix *Matrix) Get(key string) ([]any, bool) {
func (matrix *Matrix) Get(key string) (*MatrixRow, bool) {
if matrix == nil || matrix.om == nil {
return nil, false
}
return matrix.om.Get(key)
}
func (matrix *Matrix) Set(key string, value []any) bool {
func (matrix *Matrix) Set(key string, value *MatrixRow) bool {
if matrix == nil {
matrix = NewMatrix()
}
if matrix.om == nil {
matrix.om = orderedmap.NewOrderedMap[string, []any]()
matrix.om = orderedmap.NewOrderedMap[string, *MatrixRow]()
}
return matrix.om.Set(key, value)
}
// All returns an iterator that loops over all task key-value pairs.
func (matrix *Matrix) All() iter.Seq2[string, []any] {
func (matrix *Matrix) All() iter.Seq2[string, *MatrixRow] {
if matrix == nil || matrix.om == nil {
return func(yield func(string, []any) bool) {}
return func(yield func(string, *MatrixRow) bool) {}
}
return matrix.om.AllFromFront()
}
@ -67,9 +77,9 @@ func (matrix *Matrix) Keys() iter.Seq[string] {
}
// Values returns an iterator that loops over all task values.
func (matrix *Matrix) Values() iter.Seq[[]any] {
func (matrix *Matrix) Values() iter.Seq[*MatrixRow] {
if matrix == nil || matrix.om == nil {
return func(yield func([]any) bool) {}
return func(yield func(*MatrixRow) bool) {}
}
return matrix.om.Values()
}
@ -93,14 +103,36 @@ func (matrix *Matrix) UnmarshalYAML(node *yaml.Node) error {
keyNode := node.Content[i]
valueNode := node.Content[i+1]
// Decode the value node into a Matrix struct
var v []any
if err := valueNode.Decode(&v); err != nil {
return errors.NewTaskfileDecodeError(err, node)
}
switch valueNode.Kind {
case yaml.SequenceNode:
// Decode the value node into a Matrix struct
var v []any
if err := valueNode.Decode(&v); err != nil {
return errors.NewTaskfileDecodeError(err, node)
}
// Add the task to the ordered map
matrix.Set(keyNode.Value, v)
// Add the row to the ordered map
matrix.Set(keyNode.Value, &MatrixRow{
Value: v,
})
case yaml.MappingNode:
// Decode the value node into a Matrix struct
var refStruct struct {
Ref string
}
if err := valueNode.Decode(&refStruct); err != nil {
return errors.NewTaskfileDecodeError(err, node)
}
// Add the reference to the ordered map
matrix.Set(keyNode.Value, &MatrixRow{
Ref: refStruct.Ref,
})
default:
return errors.NewTaskfileDecodeError(nil, node).WithMessage("matrix values must be an array or a reference")
}
}
return nil
}