Skip to content

Commit

Permalink
feat: coll.Pick now supports slice of strings as input (#2069)
Browse files Browse the repository at this point in the history
Signed-off-by: Dave Henderson <[email protected]>
  • Loading branch information
hairyhenderson authored May 12, 2024
1 parent 916ebe6 commit ab982b5
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 4 deletions.
18 changes: 14 additions & 4 deletions docs-src/content/functions/coll.yml
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ funcs:
description: |
Given a map, returns a new map with any entries that have the given keys.
All keys are converted to strings.
The keys can either be separate arguments, or a slice (since v4.0.0).
This is the inverse of [`coll.Omit`](#coll-omit).
Expand All @@ -419,7 +419,7 @@ funcs:
arguments:
- name: keys...
required: true
description: the keys to match
description: the keys (strings) to match
- name: map
required: true
description: the map to pick from
Expand All @@ -428,12 +428,17 @@ funcs:
$ gomplate -i '{{ $data := dict "foo" 1 "bar" 2 "baz" 3 }}
{{ coll.Pick "foo" "baz" $data }}'
map[baz:3 foo:1]
- |
$ gomplate -i '{{ $data := dict "foo" 1 "bar" 2 "baz" 3 }}
{{ $keys := coll.Slice "foo" "baz" }}
{{ coll.Pick $keys $data }}'
map[baz:3 foo:1]
- name: coll.Omit
released: v3.7.0
description: |
Given a map, returns a new map without any entries that have the given keys.
All keys are converted to strings.
The keys can either be separate arguments, or a slice (since v4.0.0).
This is the inverse of [`coll.Pick`](#coll-pick).
Expand All @@ -442,7 +447,7 @@ funcs:
arguments:
- name: keys...
required: true
description: the keys to match
description: the keys (strings) to match
- name: map
required: true
description: the map to omit from
Expand All @@ -451,3 +456,8 @@ funcs:
$ gomplate -i '{{ $data := dict "foo" 1 "bar" 2 "baz" 3 }}
{{ coll.Omit "foo" "baz" $data }}'
map[bar:2]
- |
$ gomplate -i '{{ $data := dict "foo" 1 "bar" 2 "baz" 3 }}
{{ $keys := coll.Slice "foo" "baz" }}
{{ coll.Omit $keys $data }}'
map[bar:2]
13 changes: 13 additions & 0 deletions internal/funcs/coll.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,19 @@ func pickOmitArgs(args ...interface{}) (map[string]interface{}, []string, error)
return nil, nil, fmt.Errorf("wrong map type: must be map[string]interface{}, got %T", args[len(args)-1])
}

// special-case - if there's only one key and it's a slice, expand it
if len(args) == 2 {
if reflect.TypeOf(args[0]).Kind() == reflect.Slice {
sl := reflect.ValueOf(args[0])
expandedArgs := make([]interface{}, sl.Len()+1)
for i := 0; i < sl.Len(); i++ {
expandedArgs[i] = sl.Index(i).Interface()
}
expandedArgs[len(expandedArgs)-1] = m
args = expandedArgs
}
}

keys := make([]string, len(args)-1)
for i, v := range args[0 : len(args)-1] {
k, ok := v.(string)
Expand Down
39 changes: 39 additions & 0 deletions internal/funcs/coll_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,19 @@ func TestPick(t *testing.T) {
out, err = c.Pick("foo", "bar", "", in)
require.NoError(t, err)
assert.EqualValues(t, in, out)

t.Run("supports slice key", func(t *testing.T) {
t.Parallel()

in := map[string]interface{}{
"foo": "bar",
"bar": true,
"": "baz",
}
out, err := c.Pick([]string{"foo", "bar"}, in)
require.NoError(t, err)
assert.EqualValues(t, map[string]interface{}{"foo": "bar", "bar": true}, out)
})
}

func TestOmit(t *testing.T) {
Expand Down Expand Up @@ -143,6 +156,32 @@ func TestOmit(t *testing.T) {
out, err = c.Omit("foo", "bar", "", in)
require.NoError(t, err)
assert.EqualValues(t, map[string]interface{}{}, out)

t.Run("supports slice of strings", func(t *testing.T) {
t.Parallel()

in := map[string]interface{}{
"foo": "bar",
"bar": true,
"": "baz",
}
out, err := c.Omit([]string{"foo", "bar"}, in)
require.NoError(t, err)
assert.EqualValues(t, map[string]interface{}{"": "baz"}, out)
})

t.Run("supports slice of interface{}", func(t *testing.T) {
t.Parallel()

in := map[string]interface{}{
"foo": "bar",
"bar": true,
"": "baz",
}
out, err := c.Omit([]interface{}{"foo", "bar"}, in)
require.NoError(t, err)
assert.EqualValues(t, map[string]interface{}{"": "baz"}, out)
})
}

func TestGoSlice(t *testing.T) {
Expand Down
2 changes: 2 additions & 0 deletions internal/tests/integration/collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,12 @@ func TestColl_Flatten(t *testing.T) {

func TestColl_Pick(t *testing.T) {
inOutTest(t, `{{ $data := dict "foo" 1 "bar" 2 "baz" 3 }}{{ coll.Pick "foo" "baz" $data }}`, "map[baz:3 foo:1]")
inOutTest(t, `{{ $data := dict "foo" 1 "bar" 2 "baz" 3 }}{{ coll.Pick (coll.Slice "foo" "baz") $data }}`, "map[baz:3 foo:1]")
}

func TestColl_Omit(t *testing.T) {
inOutTest(t, `{{ $data := dict "foo" 1 "bar" 2 "baz" 3 }}{{ coll.Omit "foo" "baz" $data }}`, "map[bar:2]")
inOutTest(t, `{{ $data := dict "foo" 1 "bar" 2 "baz" 3 }}{{ coll.Omit (coll.Slice "foo" "baz") $data }}`, "map[bar:2]")
}

func TestColl_JQ(t *testing.T) {
Expand Down

0 comments on commit ab982b5

Please sign in to comment.