Added a log builtin
Some checks failed
Build / build (push) Failing after 1m43s

This commit is contained in:
Leon Mika 2025-01-15 22:22:17 +11:00
parent dcd4d0c5d2
commit d937ee4b54
5 changed files with 105 additions and 3 deletions

View file

@ -20,6 +20,8 @@ func main() {
instRepl := repl.New(
ucl.WithModule(builtins.OS()),
ucl.WithModule(builtins.FS(nil)),
ucl.WithModule(builtins.Log(nil)),
ucl.WithModule(builtins.Strs()),
)
ctx := context.Background()

View file

@ -21,7 +21,10 @@ func invokeUCLCallback(name string, args ...any) {
func initJS(ctx context.Context) {
uclObj := make(map[string]any)
replInst := repl.New(ucl.WithOut(ucl.LineHandler(func(line string) {
replInst := repl.New(
ucl.WithModule(builtins.Log(nil)),
ucl.WithModule(builtins.Strs()),
ucl.WithOut(ucl.LineHandler(func(line string) {
invokeUCLCallback("onOutLine", line)
})))

44
ucl/builtins/log.go Normal file
View file

@ -0,0 +1,44 @@
package builtins
import (
"context"
"log"
"strings"
"ucl.lmika.dev/ucl"
)
type LogMessageHandler func(s string) error
func Log(handler LogMessageHandler) ucl.Module {
if handler == nil {
handler = func(s string) error {
log.Println(s)
return nil
}
}
lh := logHandler{handler: handler}
return ucl.Module{
Name: "log",
Builtins: map[string]ucl.BuiltinHandler{
"puts": lh.logMessage,
},
}
}
type logHandler struct {
handler LogMessageHandler
}
func (lh logHandler) logMessage(ctx context.Context, args ucl.CallArgs) (any, error) {
var sb strings.Builder
var s ucl.Object
for args.NArgs() > 0 {
if err := args.Bind(&s); err == nil {
sb.WriteString(s.String())
}
}
return nil, lh.handler(sb.String())
}

47
ucl/builtins/log_test.go Normal file
View file

@ -0,0 +1,47 @@
package builtins_test
import (
"bytes"
"context"
"github.com/stretchr/testify/assert"
"testing"
"ucl.lmika.dev/ucl"
"ucl.lmika.dev/ucl/builtins"
)
func TestLog_Puts(t *testing.T) {
tests := []struct {
desc string
eval string
want any
wantErr bool
wantLog string
}{
{desc: "log 1", eval: `log:puts "bad stuff here"`, wantLog: "bad stuff here\n"},
{desc: "log 2", eval: `log:puts "bad " 123 " here " [1 2 3]`, wantLog: "bad 123 here [1 2 3]\n"},
{desc: "log 3", eval: `log:puts`, wantLog: "\n"},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
var logMessage bytes.Buffer
inst := ucl.New(
ucl.WithModule(builtins.Log(func(s string) error {
logMessage.WriteString(s)
logMessage.WriteByte('\n')
return nil
})),
)
res, err := inst.Eval(context.Background(), tt.eval)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want, res)
}
assert.Equal(t, tt.wantLog, logMessage.String())
})
}
}

View file

@ -96,8 +96,12 @@ func (u userBuiltin) invoke(ctx context.Context, args invocationArgs) (Object, e
func (ca CallArgs) bindArg(v interface{}, arg Object) error {
switch t := v.(type) {
case *Object:
*t = arg
return nil
case *interface{}:
*t, _ = toGoValue(arg)
return nil
case *Invokable:
i, ok := arg.(invokable)
if !ok {
@ -123,12 +127,14 @@ func (ca CallArgs) bindArg(v interface{}, arg Object) error {
} else {
*t = ""
}
return nil
case *int:
if iArg, ok := arg.(intObject); ok {
*t = int(iArg)
} else {
return errors.New("invalid arg")
}
return nil
}
switch t := arg.(type) {