diff --git a/README.md b/README.md index ece11ca4..4e2b59b6 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,26 @@ yaml sample.yaml b.e[1].name ``` will output 'sam' +#### Array Splat +e.g.: given a sample file of +```yaml +b: + e: + - name: fred + value: 3 + - name: sam + value: 4 +``` +then +``` +yaml sample.yaml b.e[*].name +``` +will output: +``` +- fred +- sam +``` + ### Updating yaml Given a sample.yaml file of: ```yaml diff --git a/data_navigator.go b/data_navigator.go index ab71ae86..9806fc62 100644 --- a/data_navigator.go +++ b/data_navigator.go @@ -25,6 +25,9 @@ func readMap(context map[interface{}]interface{}, head string, tail []string) in func recurse(value interface{}, head string, tail []string) interface{} { switch value.(type) { case []interface{}: + if head == "*" { + return readArraySplat(value.([]interface{}), tail) + } index, err := strconv.ParseInt(head, 10, 64) if err != nil { log.Fatalf("Error accessing array: %v", err) @@ -48,3 +51,18 @@ func readArray(array []interface{}, head int64, tail []string) interface{} { } return value } + +func readArraySplat(array []interface{}, tail []string) interface{} { + var newArray = make([]interface{}, len(array)) + for index, value := range array { + newArray[index] = calculateValue(value, tail) + } + return newArray +} + +func calculateValue(value interface{}, tail []string) interface{} { + if len(tail) > 0 { + return recurse(value, tail[0], tail[1:len(tail)]) + } + return value +} diff --git a/data_navigator_test.go b/data_navigator_test.go index 6b398e69..a7f12a38 100644 --- a/data_navigator_test.go +++ b/data_navigator_test.go @@ -8,10 +8,20 @@ import ( ) var rawData = ` +--- a: Easy! b: c: 2 - d: [3, 4] + d: + - 3 + - 4 +e: + - + name: Fred + thing: cat + - + name: Sam + thing: dog ` var parsedData map[interface{}]interface{} @@ -42,6 +52,10 @@ func TestReadMap_with_array_out_of_bounds(t *testing.T) { assertResult(t, nil, readMap(parsedData, "b", []string{"d", "3"})) } +func TestReadMap_with_array_splat(t *testing.T) { + assertResult(t, "[Fred Sam]", fmt.Sprintf("%v", readMap(parsedData, "e", []string{"*", "name"}))) +} + func TestWrite_simple(t *testing.T) { write(parsedData, "b", []string{"c"}, "4") @@ -52,11 +66,12 @@ func TestWrite_simple(t *testing.T) { func assertResult(t *testing.T, expectedValue interface{}, actualValue interface{}) { if expectedValue != actualValue { - t.Error("Expected <", expectedValue, "> but got <", actualValue, ">") + t.Error("Expected <", expectedValue, "> but got <", actualValue, ">", fmt.Sprintf("%T", actualValue)) } } func assertResultWithContext(t *testing.T, expectedValue interface{}, actualValue interface{}, context interface{}) { + if expectedValue != actualValue { t.Error(context) t.Error(": expected <", expectedValue, "> but got <", actualValue, ">")