Skip to content

Commit 532d68b

Browse files
feat(coll): New coll.Set and coll.Unset functions (#2118)
Signed-off-by: Dave Henderson <dhenderson@gmail.com>
1 parent deeb86f commit 532d68b

5 files changed

Lines changed: 182 additions & 0 deletions

File tree

docs-src/content/functions/coll.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,3 +461,52 @@ funcs:
461461
{{ $keys := coll.Slice "foo" "baz" }}
462462
{{ coll.Omit $keys $data }}'
463463
map[bar:2]
464+
- name: coll.Set
465+
# released: v4.0.0
466+
alias: set
467+
description: |
468+
Sets the given key to the given value in the given map.
469+
470+
The map is modified in place, and the modified map is returned.
471+
pipeline: true
472+
arguments:
473+
- name: key
474+
required: true
475+
description: the key (string) to set
476+
- name: value
477+
required: true
478+
description: the value to set
479+
- name: map
480+
required: true
481+
description: the map to modify
482+
examples:
483+
- |
484+
$ gomplate -i '{{ $data := dict "foo" 1 "bar" 2 }}
485+
{{ coll.Set "baz" 3 $data }}'
486+
map[bar:2 baz:3 foo:1]
487+
- |
488+
$ gomplate -i '{{ dict "foo" 1 | coll.Set "bar" 2 }}'
489+
map[bar:2 foo:1]
490+
- name: coll.Unset
491+
# released: v4.0.0
492+
alias: unset
493+
description: |
494+
Deletes the element with the specified key in the given map. If there is no such element, the map is returned unchanged.
495+
496+
The map is modified in place, and the modified map is returned.
497+
pipeline: true
498+
arguments:
499+
- name: key
500+
required: true
501+
description: the key (string) to unset
502+
- name: map
503+
required: true
504+
description: the map to modify
505+
examples:
506+
- |
507+
$ gomplate -i '{{ $data := dict "foo" 1 "bar" 2 "baz" 3 }}
508+
{{ coll.Unset "bar" $data }}'
509+
map[baz:3 foo:1]
510+
- |
511+
$ gomplate -i '{{ dict "foo" 1 "bar" 2 | coll.Unset "bar" }}'
512+
map[foo:1]

docs/content/functions/coll.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,3 +706,78 @@ $ gomplate -i '{{ $data := dict "foo" 1 "bar" 2 "baz" 3 }}
706706
{{ coll.Omit $keys $data }}'
707707
map[bar:2]
708708
```
709+
710+
## `coll.Set`_(unreleased)_
711+
**Unreleased:** _This function is in development, and not yet available in released builds of gomplate._
712+
713+
**Alias:** `set`
714+
715+
Sets the given key to the given value in the given map.
716+
717+
The map is modified in place, and the modified map is returned.
718+
719+
### Usage
720+
721+
```
722+
coll.Set key value map
723+
```
724+
```
725+
map | coll.Set key value
726+
```
727+
728+
### Arguments
729+
730+
| name | description |
731+
|------|-------------|
732+
| `key` | _(required)_ the key (string) to set |
733+
| `value` | _(required)_ the value to set |
734+
| `map` | _(required)_ the map to modify |
735+
736+
### Examples
737+
738+
```console
739+
$ gomplate -i '{{ $data := dict "foo" 1 "bar" 2 }}
740+
{{ coll.Set "baz" 3 $data }}'
741+
map[bar:2 baz:3 foo:1]
742+
```
743+
```console
744+
$ gomplate -i '{{ dict "foo" 1 | coll.Set "bar" 2 }}'
745+
map[bar:2 foo:1]
746+
```
747+
748+
## `coll.Unset`_(unreleased)_
749+
**Unreleased:** _This function is in development, and not yet available in released builds of gomplate._
750+
751+
**Alias:** `unset`
752+
753+
Deletes the element with the specified key in the given map. If there is no such element, the map is returned unchanged.
754+
755+
The map is modified in place, and the modified map is returned.
756+
757+
### Usage
758+
759+
```
760+
coll.Unset key map
761+
```
762+
```
763+
map | coll.Unset key
764+
```
765+
766+
### Arguments
767+
768+
| name | description |
769+
|------|-------------|
770+
| `key` | _(required)_ the key (string) to unset |
771+
| `map` | _(required)_ the map to modify |
772+
773+
### Examples
774+
775+
```console
776+
$ gomplate -i '{{ $data := dict "foo" 1 "bar" 2 "baz" 3 }}
777+
{{ coll.Unset "bar" $data }}'
778+
map[baz:3 foo:1]
779+
```
780+
```console
781+
$ gomplate -i '{{ dict "foo" 1 "bar" 2 | coll.Unset "bar" }}'
782+
map[foo:1]
783+
```

internal/funcs/coll.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ func CreateCollFuncs(ctx context.Context) map[string]interface{} {
3333
f["jsonpath"] = ns.JSONPath
3434
f["jq"] = ns.JQ
3535
f["flatten"] = ns.Flatten
36+
f["set"] = ns.Set
37+
f["unset"] = ns.Unset
3638
return f
3739
}
3840

@@ -221,3 +223,17 @@ func (CollFuncs) Omit(args ...interface{}) (map[string]interface{}, error) {
221223
}
222224
return coll.Omit(m, keys...), nil
223225
}
226+
227+
// Set -
228+
func (CollFuncs) Set(key string, value interface{}, m map[string]interface{}) (map[string]interface{}, error) {
229+
m[key] = value
230+
231+
return m, nil
232+
}
233+
234+
// Unset -
235+
func (CollFuncs) Unset(key string, m map[string]interface{}) (map[string]interface{}, error) {
236+
delete(m, key)
237+
238+
return m, nil
239+
}

internal/funcs/coll_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,35 @@ func TestGoSlice(t *testing.T) {
216216
assert.Equal(t, reflect.TypeOf([]string{}), out.Type())
217217
assert.EqualValues(t, []string{"bar", "baz"}, out.Interface())
218218
}
219+
220+
func TestCollFuncs_Set(t *testing.T) {
221+
t.Parallel()
222+
223+
c := &CollFuncs{}
224+
225+
m := map[string]interface{}{"foo": "bar"}
226+
out, err := c.Set("foo", "baz", m)
227+
require.NoError(t, err)
228+
assert.EqualValues(t, map[string]interface{}{"foo": "baz"}, out)
229+
230+
// m was modified so foo is now baz
231+
out, err = c.Set("bar", "baz", m)
232+
require.NoError(t, err)
233+
assert.EqualValues(t, map[string]interface{}{"foo": "baz", "bar": "baz"}, out)
234+
}
235+
236+
func TestCollFuncs_Unset(t *testing.T) {
237+
t.Parallel()
238+
239+
c := &CollFuncs{}
240+
241+
m := map[string]interface{}{"foo": "bar"}
242+
out, err := c.Unset("foo", m)
243+
require.NoError(t, err)
244+
assert.Empty(t, out)
245+
246+
// no-op
247+
out, err = c.Unset("bar", m)
248+
require.NoError(t, err)
249+
assert.Empty(t, out)
250+
}

internal/tests/integration/collection_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,13 @@ func TestColl_JQ(t *testing.T) {
105105
inOutTest(t, `{{ coll.JQ ".foo" (dict "foo" 1 "bar" 2 "baz" 3) }}`, "1")
106106
inOutTest(t, `{{ coll.Slice "one" 2 "three" 4.0 | jq ".[2]" }}`, `three`)
107107
}
108+
109+
func TestColl_Set(t *testing.T) {
110+
inOutTest(t, `{{ $dict := dict "foo" 1 }}{{ coll.Set "bar" 2 $dict }}`, "map[bar:2 foo:1]")
111+
inOutTest(t, `{{ dict "foo" 1 | coll.Set "foo" 2 }}`, "map[foo:2]")
112+
}
113+
114+
func TestColl_Unset(t *testing.T) {
115+
inOutTest(t, `{{ $dict := dict "foo" 1 "bar" 2 }}{{ coll.Unset "bar" $dict }}`, "map[foo:1]")
116+
inOutTest(t, `{{ dict "foo" 1 "bar" 2 | coll.Unset "foo" }}`, "map[bar:2]")
117+
}

0 commit comments

Comments
 (0)