2024-04-25 01:10:13 +00:00
|
|
|
//go:build js && wasm
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"github.com/alecthomas/participle/v2"
|
|
|
|
"strings"
|
2024-04-27 00:15:04 +00:00
|
|
|
"syscall/js"
|
2024-04-27 01:00:48 +00:00
|
|
|
"ucl.lmika.dev/ucl"
|
2024-04-25 01:10:13 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func invokeUCLCallback(name string, args ...any) {
|
|
|
|
if onLine := js.Global().Get("ucl").Get(name); !onLine.IsNull() {
|
|
|
|
onLine.Invoke(args...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func initJS(ctx context.Context) {
|
2024-04-27 00:15:04 +00:00
|
|
|
uclObj := make(map[string]any)
|
2024-04-25 01:10:13 +00:00
|
|
|
|
2024-04-27 00:11:22 +00:00
|
|
|
inst := ucl.New(ucl.WithOut(&uclOut{
|
2024-04-25 01:10:13 +00:00
|
|
|
lineBuffer: new(bytes.Buffer),
|
|
|
|
writeLine: func(line string) {
|
|
|
|
invokeUCLCallback("onOutLine", line)
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
|
2024-04-27 00:15:04 +00:00
|
|
|
uclObj["eval"] = js.FuncOf(func(this js.Value, args []js.Value) any {
|
2024-04-25 01:10:13 +00:00
|
|
|
if len(args) != 2 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
cmdLine := args[0].String()
|
|
|
|
if strings.TrimSpace(cmdLine) == "" {
|
|
|
|
invokeUCLCallback("onNewCommand")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
wantContinue := args[1].Bool()
|
2024-04-27 00:15:04 +00:00
|
|
|
if err := ucl.EvalAndDisplay(ctx, inst, cmdLine); err != nil {
|
2024-04-25 01:10:13 +00:00
|
|
|
var p participle.Error
|
|
|
|
if errors.As(err, &p) && wantContinue {
|
|
|
|
invokeUCLCallback("onContinue")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
invokeUCLCallback("onError", err.Error())
|
|
|
|
}
|
|
|
|
invokeUCLCallback("onNewCommand")
|
|
|
|
return nil
|
|
|
|
})
|
2024-04-27 00:15:04 +00:00
|
|
|
js.Global().Set("ucl", uclObj)
|
2024-04-25 01:10:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type uclOut struct {
|
|
|
|
lineBuffer *bytes.Buffer
|
|
|
|
writeLine func(line string)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (uo *uclOut) Write(p []byte) (n int, err error) {
|
|
|
|
for _, b := range p {
|
|
|
|
if b == '\n' {
|
|
|
|
uo.writeLine(uo.lineBuffer.String())
|
|
|
|
uo.lineBuffer.Reset()
|
|
|
|
} else {
|
|
|
|
uo.lineBuffer.WriteByte(b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return len(p), nil
|
|
|
|
}
|