Added the keys built-in
This commit is contained in:
parent
34a0c8e3ff
commit
ad746c05aa
|
@ -165,6 +165,29 @@ func indexBuiltin(ctx context.Context, args invocationArgs) (object, error) {
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func keysBuiltin(ctx context.Context, args invocationArgs) (object, error) {
|
||||||
|
if err := args.expectArgn(1); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
val := args.args[0]
|
||||||
|
switch v := val.(type) {
|
||||||
|
case hashable:
|
||||||
|
keys := make(listObject, 0, v.Len())
|
||||||
|
if err := v.Each(func(k string, _ object) error {
|
||||||
|
keys = append(keys, strObject(k))
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return keys, nil
|
||||||
|
default:
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func mapBuiltin(ctx context.Context, args invocationArgs) (object, error) {
|
func mapBuiltin(ctx context.Context, args invocationArgs) (object, error) {
|
||||||
if err := args.expectArgn(2); err != nil {
|
if err := args.expectArgn(2); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -50,6 +50,7 @@ func New(opts ...InstOption) *Inst {
|
||||||
rootEC.addCmd("set", invokableFunc(setBuiltin))
|
rootEC.addCmd("set", invokableFunc(setBuiltin))
|
||||||
rootEC.addCmd("toUpper", invokableFunc(toUpperBuiltin))
|
rootEC.addCmd("toUpper", invokableFunc(toUpperBuiltin))
|
||||||
rootEC.addCmd("len", invokableFunc(lenBuiltin))
|
rootEC.addCmd("len", invokableFunc(lenBuiltin))
|
||||||
|
rootEC.addCmd("keys", invokableFunc(keysBuiltin))
|
||||||
rootEC.addCmd("index", invokableFunc(indexBuiltin))
|
rootEC.addCmd("index", invokableFunc(indexBuiltin))
|
||||||
rootEC.addCmd("call", invokableFunc(callBuiltin))
|
rootEC.addCmd("call", invokableFunc(callBuiltin))
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,10 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Builtins used for test
|
// Builtins used for test
|
||||||
|
@ -642,3 +643,57 @@ func TestBuiltins_Len(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuiltins_Keys(t *testing.T) {
|
||||||
|
type testNested struct {
|
||||||
|
Nested string
|
||||||
|
Type string
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
desc string
|
||||||
|
expr string
|
||||||
|
wantItems []string
|
||||||
|
}{
|
||||||
|
{desc: "keys of map", expr: `keys [alpha: "hello" bravo: "world"]`, wantItems: []string{"alpha", "bravo"}},
|
||||||
|
{desc: "keys of go struct 1", expr: `goStruct | keys`, wantItems: []string{"Alpha", "Beta", "Gamma"}},
|
||||||
|
{desc: "keys of go struct 2", expr: `index (goStruct) Gamma | keys`, wantItems: []string{"Nested", "Type"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.desc, func(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
outW := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
|
inst := New(WithOut(outW), WithTestBuiltin())
|
||||||
|
inst.SetBuiltin("goInt", func(ctx context.Context, args CallArgs) (any, error) {
|
||||||
|
return []int{6, 5, 4}, nil
|
||||||
|
})
|
||||||
|
inst.SetBuiltin("goStruct", func(ctx context.Context, args CallArgs) (any, error) {
|
||||||
|
return struct {
|
||||||
|
Alpha string
|
||||||
|
Beta string
|
||||||
|
Gamma testNested
|
||||||
|
hidden string
|
||||||
|
missing string
|
||||||
|
}{
|
||||||
|
Alpha: "foo",
|
||||||
|
Beta: "bar",
|
||||||
|
Gamma: testNested{
|
||||||
|
Nested: "ads",
|
||||||
|
Type: "asd",
|
||||||
|
},
|
||||||
|
hidden: "hidden",
|
||||||
|
missing: "missing",
|
||||||
|
}, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
res, err := inst.Eval(ctx, tt.expr)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, res, len(tt.wantItems))
|
||||||
|
for _, i := range tt.wantItems {
|
||||||
|
assert.Contains(t, res, i)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue