Started working on a REPL helper
This commit is contained in:
parent
9b3b8287fa
commit
8c5cb299c2
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"github.com/chzyer/readline"
|
||||
"log"
|
||||
"ucl.lmika.dev/repl"
|
||||
"ucl.lmika.dev/ucl"
|
||||
"ucl.lmika.dev/ucl/builtins"
|
||||
)
|
||||
|
@ -15,7 +16,7 @@ func main() {
|
|||
}
|
||||
defer rl.Close()
|
||||
|
||||
inst := ucl.New(
|
||||
instRepl := repl.New(
|
||||
ucl.WithModule(builtins.OS()),
|
||||
ucl.WithModule(builtins.FS(nil)),
|
||||
)
|
||||
|
|
6
repl/docs.go
Normal file
6
repl/docs.go
Normal file
|
@ -0,0 +1,6 @@
|
|||
package repl
|
||||
|
||||
type Doc struct {
|
||||
Brief string
|
||||
Detailed string
|
||||
}
|
37
repl/evaldisplay.go
Normal file
37
repl/evaldisplay.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package repl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"ucl.lmika.dev/ucl"
|
||||
)
|
||||
|
||||
func (r *REPL) EvalAndDisplay(ctx context.Context, expr string) error {
|
||||
res, err := r.inst.Eval(ctx, expr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return displayResult(ctx, r.inst, res)
|
||||
}
|
||||
|
||||
func displayResult(ctx context.Context, inst *ucl.Inst, res any) (err error) {
|
||||
switch v := res.(type) {
|
||||
case nil:
|
||||
if _, err = fmt.Fprintln(os.Stdout, "(nil)"); err != nil {
|
||||
return err
|
||||
}
|
||||
case listable:
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
if err = displayResult(ctx, inst, v.Index(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
default:
|
||||
if _, err = fmt.Fprintln(os.Stdout, v.String()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
64
repl/repl.go
Normal file
64
repl/repl.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package repl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/lmika/gopkgs/fp/maps"
|
||||
"sort"
|
||||
"ucl.lmika.dev/ucl"
|
||||
)
|
||||
|
||||
type CommandOpt interface {
|
||||
config(cmdName string, r *REPL)
|
||||
}
|
||||
|
||||
type REPL struct {
|
||||
inst *ucl.Inst
|
||||
|
||||
commandDocs map[string]Doc
|
||||
}
|
||||
|
||||
func New(opts ...ucl.InstOption) *REPL {
|
||||
inst := ucl.New(opts...)
|
||||
|
||||
r := &REPL{
|
||||
inst: inst,
|
||||
commandDocs: make(map[string]Doc),
|
||||
}
|
||||
inst.SetBuiltin("help", r.helpBuiltin)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *REPL) Inst() *ucl.Inst {
|
||||
return r.inst
|
||||
}
|
||||
|
||||
func (r *REPL) SetCommand(name string, fn ucl.BuiltinHandler, opts ...CommandOpt) {
|
||||
r.commandDocs[name] = Doc{}
|
||||
for _, opt := range opts {
|
||||
opt.config(name, r)
|
||||
}
|
||||
|
||||
r.inst.SetBuiltin(name, fn)
|
||||
}
|
||||
|
||||
func (r *REPL) helpBuiltin(ctx context.Context, args ucl.CallArgs) (any, error) {
|
||||
switch {
|
||||
case args.NArgs() == 0:
|
||||
// TEMP
|
||||
names := maps.Keys(r.commandDocs)
|
||||
sort.Strings(names)
|
||||
|
||||
for _, name := range names {
|
||||
cdoc := r.commandDocs[name]
|
||||
if cdoc.Brief != "" {
|
||||
fmt.Println("%v\t%v", name, r.commandDocs[name])
|
||||
} else {
|
||||
fmt.Println("%v", name)
|
||||
}
|
||||
}
|
||||
// END TEMP
|
||||
}
|
||||
return nil, nil
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package ucl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func EvalAndDisplay(ctx context.Context, inst *Inst, expr string) error {
|
||||
res, err := inst.eval(ctx, expr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return displayResult(ctx, inst, res)
|
||||
}
|
||||
|
||||
func displayResult(ctx context.Context, inst *Inst, res Object) (err error) {
|
||||
switch v := res.(type) {
|
||||
case nil:
|
||||
if _, err = fmt.Fprintln(inst.out, "(nil)"); err != nil {
|
||||
return err
|
||||
}
|
||||
case Listable:
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
if err = displayResult(ctx, inst, v.Index(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
default:
|
||||
if _, err = fmt.Fprintln(inst.out, v.String()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -47,7 +47,7 @@ func New(opts ...InstOption) *Inst {
|
|||
rootEC.root = rootEC
|
||||
|
||||
rootEC.addCmd("echo", invokableFunc(echoBuiltin))
|
||||
rootEC.addCmd("set", invokableFunc(setBuiltin))
|
||||
rootEC.addCmd("var", invokableFunc(setBuiltin))
|
||||
rootEC.addCmd("toUpper", invokableFunc(toUpperBuiltin))
|
||||
rootEC.addCmd("len", invokableFunc(lenBuiltin))
|
||||
rootEC.addCmd("keys", invokableFunc(keysBuiltin))
|
||||
|
|
Loading…
Reference in a new issue