delve/pkg/terminal/starlark.go
Alessandro Arzilli ed35dce7a3 terminal: adds embedded scripting language (#1466)
If the argument of 'source' ends in '.star' it will be interpreted as a
starlark script.
If the argument of 'source' is '-' an interactive starlark repl will be
started.

For documentation on how the starlark execution environment works see
Documentation/cli/starlark.md.

The starlark API is autogenerated from the JSON-RPC API by
script/gen-starlark-bindings.go.
In general for each JSON-RPC API a single global starlark function is
created.
When one of those functions is called (through a starlark script) the
arguments are converted to go structs using reflection. See
unmarshalStarlarkValue in pkg/terminal/starbind/conv.go.
If there are no type conversion errors the JSON-RPC call is executed.
The return value of the JSON-RPC call is converted back into a starlark
value by interfaceToStarlarkValue (same file):

* primitive types (such as integers, floats or strings) are converted
  by creating the corresponding starlark value.
* compound types (such as structs and slices) are converted by wrapping
  their reflect.Value object into a type that implements the relevant
  starlark interfaces.
* api.Variables are treated specially so that their Value field can be
  of the proper type instead of always being a string.

Implements #1415, #1443
2019-07-02 10:55:27 -07:00

60 lines
1.2 KiB
Go

package terminal
import (
"github.com/go-delve/delve/pkg/terminal/starbind"
"github.com/go-delve/delve/service"
"github.com/go-delve/delve/service/api"
)
type starlarkContext struct {
term *Term
}
var _ starbind.Context = starlarkContext{}
func (ctx starlarkContext) Client() service.Client {
return ctx.term.client
}
func (ctx starlarkContext) RegisterCommand(name, helpMsg string, fn func(args string) error) {
cmdfn := func(t *Term, ctx callContext, args string) error {
return fn(args)
}
found := false
for i := range ctx.term.cmds.cmds {
cmd := &ctx.term.cmds.cmds[i]
for _, alias := range cmd.aliases {
if alias == name {
cmd.cmdFn = cmdfn
cmd.helpMsg = helpMsg
found = true
break
}
}
if found {
break
}
}
if !found {
newcmd := command{
aliases: []string{name},
helpMsg: helpMsg,
cmdFn: cmdfn,
}
ctx.term.cmds.cmds = append(ctx.term.cmds.cmds, newcmd)
}
}
func (ctx starlarkContext) CallCommand(cmdstr string) error {
return ctx.term.cmds.Call(cmdstr, ctx.term)
}
func (ctx starlarkContext) Scope() api.EvalScope {
return api.EvalScope{-1, ctx.term.cmds.frame, 0}
}
func (ctx starlarkContext) LoadConfig() api.LoadConfig {
return ctx.term.loadConfig()
}