mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-12 17:27:50 +08:00
eval: BuiltinFn -> GoFn.
This commit is contained in:
parent
c8e767b2fd
commit
a0c53d4c40
|
@ -8,14 +8,14 @@ import (
|
|||
)
|
||||
|
||||
func TestRawFilterCandidates(t *testing.T) {
|
||||
passAll := eval.NewBuiltinFn("test:passAll",
|
||||
passAll := eval.NewGoFn("test:passAll",
|
||||
func(fm *eval.Frame, pattern string, inputs eval.Inputs) {
|
||||
out := fm.OutputChan()
|
||||
inputs(func(v interface{}) {
|
||||
out <- vals.Bool(true)
|
||||
})
|
||||
})
|
||||
blockAll := eval.NewBuiltinFn("test:blockAll",
|
||||
blockAll := eval.NewGoFn("test:blockAll",
|
||||
func(fm *eval.Frame, pattern string, inputs eval.Inputs) {
|
||||
out := fm.OutputChan()
|
||||
inputs(func(v interface{}) {
|
||||
|
@ -43,7 +43,7 @@ func TestRawFilterCandidates(t *testing.T) {
|
|||
|
||||
func TestComplexCandidate(t *testing.T) {
|
||||
setup := func(ev *eval.Evaler) {
|
||||
ev.Builtin.AddNs("edit", eval.NewNs().AddBuiltinFn(
|
||||
ev.Builtin.AddNs("edit", eval.NewNs().AddGoFn(
|
||||
"edit:", "complex-candidate", makeComplexCandidate))
|
||||
}
|
||||
That := eval.That
|
||||
|
|
|
@ -51,7 +51,7 @@ func Init(ed eddefs.Editor, ns eval.Ns) {
|
|||
"binding": vars.FromPtr(&c.binding),
|
||||
"matcher": vars.FromPtr(&c.matcher),
|
||||
"arg-completer": vars.FromPtr(&c.argCompleter),
|
||||
}.AddBuiltinFns("edit:completion:", map[string]interface{}{
|
||||
}.AddGoFns("edit:completion:", map[string]interface{}{
|
||||
"start": func() { c.start(ed, false) },
|
||||
"smart-start": func() { c.start(ed, true) },
|
||||
"up": func() { c.prev(false) },
|
||||
|
@ -77,7 +77,7 @@ func Init(ed eddefs.Editor, ns eval.Ns) {
|
|||
ns.AddFn("match-subseq", matchSubseq)
|
||||
|
||||
// Other functions.
|
||||
ns.AddBuiltinFns("edit:", map[string]interface{}{
|
||||
ns.AddGoFns("edit:", map[string]interface{}{
|
||||
"complete-getopt": complGetopt,
|
||||
"complex-candidate": makeComplexCandidate,
|
||||
})
|
||||
|
|
|
@ -17,11 +17,11 @@ var (
|
|||
)
|
||||
|
||||
var (
|
||||
matchPrefix = eval.NewBuiltinFn(
|
||||
matchPrefix = eval.NewGoFn(
|
||||
"edit:match-prefix", wrapMatcher(strings.HasPrefix))
|
||||
matchSubstr = eval.NewBuiltinFn(
|
||||
matchSubstr = eval.NewGoFn(
|
||||
"edit:match-substr", wrapMatcher(strings.Contains))
|
||||
matchSubseq = eval.NewBuiltinFn(
|
||||
matchSubseq = eval.NewGoFn(
|
||||
"edit:match-subseq", wrapMatcher(util.HasSubseq))
|
||||
)
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ func makeNs(ed *editor) eval.Ns {
|
|||
"wordify": wordifyBuiltin,
|
||||
"-dump-buf": ed.dumpBuf,
|
||||
}
|
||||
ns.AddBuiltinFns("edit:", fns)
|
||||
ns.AddGoFns("edit:", fns)
|
||||
|
||||
return ns
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ func init() {
|
|||
}
|
||||
|
||||
func initCoreFns(ed *editor, ns eval.Ns) {
|
||||
ns.AddBuiltinFns("edit:", map[string]interface{}{
|
||||
ns.AddGoFns("edit:", map[string]interface{}{
|
||||
"kill-line-left": ed.applyKill(moveDotSOL),
|
||||
"kill-line-right": ed.applyKill(moveDotEOL),
|
||||
"kill-word-left": ed.applyKill(moveDotLeftWord),
|
||||
|
@ -80,7 +80,7 @@ func initInsert(ed *editor, ns eval.Ns) {
|
|||
insertNs := eval.Ns{
|
||||
"binding": vars.FromPtr(&insert.binding),
|
||||
}
|
||||
insertNs.AddBuiltinFns("edit:insert:", map[string]interface{}{
|
||||
insertNs.AddGoFns("edit:insert:", map[string]interface{}{
|
||||
"start": ed.SetModeInsert,
|
||||
"default": ed.insertDefault,
|
||||
})
|
||||
|
@ -115,7 +115,7 @@ func initCommand(ed *editor, ns eval.Ns) {
|
|||
commandNs := eval.Ns{
|
||||
"binding": vars.FromPtr(&command.binding),
|
||||
}
|
||||
commandNs.AddBuiltinFns("edit:command:", map[string]interface{}{
|
||||
commandNs.AddGoFns("edit:command:", map[string]interface{}{
|
||||
"start": ed.commandStart,
|
||||
"default": ed.commandDefault,
|
||||
})
|
||||
|
|
|
@ -38,7 +38,7 @@ func initListing(ed *editor, ns eval.Ns) {
|
|||
subns := eval.Ns{
|
||||
"binding": vars.FromPtr(&l.commonBinding),
|
||||
}
|
||||
subns.AddBuiltinFns("edit:listing:", map[string]interface{}{
|
||||
subns.AddGoFns("edit:listing:", map[string]interface{}{
|
||||
"up": func() { l.up(false) },
|
||||
"up-cycle": func() { l.up(true) },
|
||||
"page-up": func() { l.pageUp() },
|
||||
|
|
|
@ -28,7 +28,7 @@ func initNarrow(ed *editor, ns eval.Ns) {
|
|||
subns := eval.Ns{
|
||||
"binding": vars.FromPtr(&n.binding),
|
||||
}
|
||||
subns.AddBuiltinFns("edit:narrow:", map[string]interface{}{
|
||||
subns.AddGoFns("edit:narrow:", map[string]interface{}{
|
||||
"up": func() { n.up(false) },
|
||||
"up-cycle": func() { n.up(true) },
|
||||
"page-up": func() { n.pageUp() },
|
||||
|
@ -52,7 +52,7 @@ func initNarrow(ed *editor, ns eval.Ns) {
|
|||
"default": func() { n.defaultBinding(ed) },
|
||||
})
|
||||
ns.AddNs("narrow", subns)
|
||||
ns.AddBuiltinFn("edit:", "-narrow-read", n.NarrowRead)
|
||||
ns.AddGoFn("edit:", "-narrow-read", n.NarrowRead)
|
||||
}
|
||||
|
||||
type narrowState struct {
|
||||
|
|
|
@ -48,7 +48,7 @@ func initNavigation(ed *editor, ns eval.Ns) {
|
|||
subns := eval.Ns{
|
||||
"binding": vars.FromPtr(&n.binding),
|
||||
}
|
||||
subns.AddBuiltinFns("edit:navigation:", map[string]interface{}{
|
||||
subns.AddGoFns("edit:navigation:", map[string]interface{}{
|
||||
"start": func() { n.start(ed) },
|
||||
"up": n.prev,
|
||||
"down": n.next,
|
||||
|
|
|
@ -50,7 +50,7 @@ func Init(ed eddefs.Editor, ns eval.Ns) {
|
|||
"binding": vars.FromPtr(&hist.binding),
|
||||
"list": vars.NewReadOnly(List{&hist.mutex, ed.Daemon()}),
|
||||
}
|
||||
historyNs.AddBuiltinFns("edit:history:", map[string]interface{}{
|
||||
historyNs.AddGoFns("edit:history:", map[string]interface{}{
|
||||
"start": hist.start,
|
||||
"up": hist.up,
|
||||
"down": hist.down,
|
||||
|
@ -63,7 +63,7 @@ func Init(ed eddefs.Editor, ns eval.Ns) {
|
|||
histlistNs := eval.Ns{
|
||||
"binding": vars.FromPtr(&histlistBinding),
|
||||
}
|
||||
histlistNs.AddBuiltinFns("edit:histlist:", map[string]interface{}{
|
||||
histlistNs.AddGoFns("edit:histlist:", map[string]interface{}{
|
||||
"start": func() {
|
||||
hl.start(ed, hist.fuser, histlistBinding)
|
||||
},
|
||||
|
@ -74,7 +74,7 @@ func Init(ed eddefs.Editor, ns eval.Ns) {
|
|||
ns.AddNs("history", historyNs)
|
||||
ns.AddNs("histlist", histlistNs)
|
||||
// TODO(xiaq): Rename and put in edit:history
|
||||
ns.AddBuiltinFn("edit:", "command-history", hist.commandHistory)
|
||||
ns.AddGoFn("edit:", "command-history", hist.commandHistory)
|
||||
}
|
||||
|
||||
func (h *hist) Teardown() {
|
||||
|
|
|
@ -32,7 +32,7 @@ func Init(ed eddefs.Editor, ns eval.Ns) {
|
|||
subns := eval.Ns{
|
||||
"binding": vars.FromPtr(&binding),
|
||||
}
|
||||
subns.AddBuiltinFns("edit:lastcmd:", map[string]interface{}{
|
||||
subns.AddGoFns("edit:lastcmd:", map[string]interface{}{
|
||||
"start": func() { lc.start(ed, binding) },
|
||||
"accept-line": func() { lc.acceptLine(ed) },
|
||||
})
|
||||
|
|
|
@ -37,7 +37,7 @@ type mode struct {
|
|||
matcher eval.Callable
|
||||
}
|
||||
|
||||
var matchDirPatternBuiltin = eval.NewBuiltinFn("edit:location:match-dir-pattern", matchDirPattern)
|
||||
var matchDirPatternBuiltin = eval.NewGoFn("edit:location:match-dir-pattern", matchDirPattern)
|
||||
|
||||
// Init initializes the location mode for an Editor.
|
||||
func Init(ed eddefs.Editor, ns eval.Ns) {
|
||||
|
@ -51,7 +51,7 @@ func Init(ed eddefs.Editor, ns eval.Ns) {
|
|||
"pinned": vars.FromPtr(&m.pinned),
|
||||
"matcher": vars.FromPtr(&m.matcher),
|
||||
"workspaces": vars.FromPtr(&m.workspaces),
|
||||
}.AddBuiltinFn("edit:location:", "start", m.start).
|
||||
}.AddGoFn("edit:location:", "start", m.start).
|
||||
AddFn("match-dir-pattern", matchDirPatternBuiltin))
|
||||
|
||||
ed.Evaler().AddAfterChdir(func(string) {
|
||||
|
|
|
@ -59,7 +59,7 @@ var (
|
|||
"/home",
|
||||
nil,
|
||||
eval.NewEvaler(),
|
||||
eval.NewBuiltinFn("edit:location:test:match-prefix", matchPrefix))
|
||||
eval.NewGoFn("edit:location:test:match-prefix", matchPrefix))
|
||||
|
||||
locationWithPrefixMatcherTests = []eddefs.ListingProviderFilterTest{
|
||||
{"", []eddefs.ListingShown{
|
||||
|
|
|
@ -24,7 +24,7 @@ func init() {
|
|||
out <- &ui.Styled{"> ", ui.Styles{}}
|
||||
}
|
||||
}
|
||||
defaultPrompt = eval.NewBuiltinFn("default prompt", prompt)
|
||||
defaultPrompt = eval.NewGoFn("default prompt", prompt)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -42,7 +42,7 @@ func init() {
|
|||
out := fm.OutputChan()
|
||||
out <- &ui.Styled{rpromptStr, ui.Styles{"inverse"}}
|
||||
}
|
||||
defaultRPrompt = eval.NewBuiltinFn("default rprompt", rprompt)
|
||||
defaultRPrompt = eval.NewGoFn("default rprompt", rprompt)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -53,5 +53,5 @@ func init() {
|
|||
out <- &ui.Styled{s.Text, ui.Styles{"inverse"}}
|
||||
})
|
||||
}
|
||||
defaultStaleTransform = eval.NewBuiltinFn("default stale transform", staleTransform)
|
||||
defaultStaleTransform = eval.NewGoFn("default stale transform", staleTransform)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package eval
|
||||
|
||||
// Builtin functions.
|
||||
// Misc builtin functions.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -51,7 +51,7 @@ func kindOf(fm *Frame, args ...interface{}) {
|
|||
|
||||
func constantly(args ...interface{}) Callable {
|
||||
// XXX Repr of this fn is not right
|
||||
return NewBuiltinFn(
|
||||
return NewGoFn(
|
||||
"created by constantly",
|
||||
func(fm *Frame) {
|
||||
out := fm.ports[1].Chan
|
||||
|
|
|
@ -21,5 +21,5 @@ var builtinNs = Ns{
|
|||
}
|
||||
|
||||
func addBuiltinFns(fns map[string]interface{}) {
|
||||
builtinNs.AddBuiltinFns("", fns)
|
||||
builtinNs.AddGoFns("", fns)
|
||||
}
|
||||
|
|
|
@ -194,7 +194,7 @@ func (op fnOp) invoke(fm *Frame) error {
|
|||
// Initialize the function variable with the builtin nop function. This step
|
||||
// allows the definition of recursive functions; the actual function will
|
||||
// never be called.
|
||||
fm.local[op.varName] = vars.FromInit(NewBuiltinFn("<shouldn't be called>", nop))
|
||||
fm.local[op.varName] = vars.FromInit(NewGoFn("<shouldn't be called>", nop))
|
||||
values, err := op.lambdaOp.invoke(fm)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -41,7 +41,7 @@ func Ns(daemon *daemon.Client, spawner *daemonp.Daemon) eval.Ns {
|
|||
return eval.Ns{
|
||||
"pid": vars.FromGet(getPidVar),
|
||||
"sock": vars.NewReadOnly(string(daemon.SockPath())),
|
||||
}.AddBuiltinFns("daemon:", map[string]interface{}{
|
||||
}.AddGoFns("daemon:", map[string]interface{}{
|
||||
"pid": getPid,
|
||||
"spawn": spawn,
|
||||
})
|
||||
|
|
|
@ -11,18 +11,17 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
// ErrArgs is thrown when a builtin function gets erroneous arguments.
|
||||
// ErrArgs is thrown when a Go function gets erroneous arguments.
|
||||
//
|
||||
// TODO(xiaq): Replace this single error type with multiple types that carry
|
||||
// richer error information.
|
||||
ErrArgs = errors.New("args error")
|
||||
// ErrNoOptAccepted is thrown when a builtin function that does not accept
|
||||
// any options gets passed options.
|
||||
// ErrNoOptAccepted is thrown when a Go function that does not accept any
|
||||
// options gets passed options.
|
||||
ErrNoOptAccepted = errors.New("function does not accept any options")
|
||||
)
|
||||
|
||||
// BuiltinFn uses reflection to wrap arbitrary Go functions into Elvish
|
||||
// functions.
|
||||
// GoFn uses reflection to wrap arbitrary Go functions into Elvish functions.
|
||||
//
|
||||
// Parameters are passed following these rules:
|
||||
//
|
||||
|
@ -49,9 +48,7 @@ var (
|
|||
// converted using goToElv. If the last return value has type error and is not
|
||||
// nil, it is turned into an exception and no ouputting happens. If the last
|
||||
// return value is a nil error, it is ignored.
|
||||
//
|
||||
// TODO(xiaq): Rename this to NativeFn.
|
||||
type BuiltinFn struct {
|
||||
type GoFn struct {
|
||||
name string
|
||||
impl interface{}
|
||||
|
||||
|
@ -71,7 +68,7 @@ type BuiltinFn struct {
|
|||
variadicArg reflect.Type
|
||||
}
|
||||
|
||||
var _ Callable = &BuiltinFn{}
|
||||
var _ Callable = &GoFn{}
|
||||
|
||||
// An interface to be implemented by pointers to structs that should hold
|
||||
// scanned options.
|
||||
|
@ -79,9 +76,9 @@ type optionsPtr interface {
|
|||
SetDefaultOptions()
|
||||
}
|
||||
|
||||
// Inputs is the type that the last parameter of a builtin function can take.
|
||||
// When that is the case, it is a callback to get inputs. See the doc of
|
||||
// BuiltinFn for details.
|
||||
// Inputs is the type that the last parameter of a Go-native function can take.
|
||||
// When that is the case, it is a callback to get inputs. See the doc of GoFn
|
||||
// for details.
|
||||
type Inputs func(func(interface{}))
|
||||
|
||||
var (
|
||||
|
@ -91,10 +88,10 @@ var (
|
|||
inputsType = reflect.TypeOf(Inputs(nil))
|
||||
)
|
||||
|
||||
// NewBuiltinFn creates a new ReflectBuiltinFn instance.
|
||||
func NewBuiltinFn(name string, impl interface{}) *BuiltinFn {
|
||||
// NewGoFn creates a new GoFn instance.
|
||||
func NewGoFn(name string, impl interface{}) *GoFn {
|
||||
implType := reflect.TypeOf(impl)
|
||||
b := &BuiltinFn{name: name, impl: impl}
|
||||
b := &GoFn{name: name, impl: impl}
|
||||
|
||||
i := 0
|
||||
if i < implType.NumIn() && implType.In(i) == frameType {
|
||||
|
@ -129,22 +126,22 @@ func NewBuiltinFn(name string, impl interface{}) *BuiltinFn {
|
|||
}
|
||||
|
||||
// Kind returns "fn".
|
||||
func (*BuiltinFn) Kind() string {
|
||||
func (*GoFn) Kind() string {
|
||||
return "fn"
|
||||
}
|
||||
|
||||
// Equal compares identity.
|
||||
func (b *BuiltinFn) Equal(rhs interface{}) bool {
|
||||
func (b *GoFn) Equal(rhs interface{}) bool {
|
||||
return b == rhs
|
||||
}
|
||||
|
||||
// Hash hashes the address.
|
||||
func (b *BuiltinFn) Hash() uint32 {
|
||||
func (b *GoFn) Hash() uint32 {
|
||||
return hash.Pointer(unsafe.Pointer(b))
|
||||
}
|
||||
|
||||
// Repr returns an opaque representation "<builtin $name>".
|
||||
func (b *BuiltinFn) Repr(int) string {
|
||||
func (b *GoFn) Repr(int) string {
|
||||
return "<builtin " + b.name + ">"
|
||||
}
|
||||
|
||||
|
@ -155,7 +152,7 @@ var errorType = reflect.TypeOf((*error)(nil)).Elem()
|
|||
var errNoOptions = errors.New("function does not accept any options")
|
||||
|
||||
// Call calls the implementation using reflection.
|
||||
func (b *BuiltinFn) Call(f *Frame, args []interface{}, opts map[string]interface{}) error {
|
||||
func (b *GoFn) Call(f *Frame, args []interface{}, opts map[string]interface{}) error {
|
||||
if b.variadicArg != nil {
|
||||
if len(args) < len(b.normalArgs) {
|
||||
return fmt.Errorf("want %d or more arguments, got %d",
|
|
@ -14,7 +14,7 @@ type testOptions struct {
|
|||
|
||||
func (o *testOptions) SetDefaultOptions() { o.Bar = "default" }
|
||||
|
||||
func TestReflectBuiltinFnCall(t *testing.T) {
|
||||
func TestGoFnCall(t *testing.T) {
|
||||
theFrame := new(Frame)
|
||||
theOptions := map[string]interface{}{}
|
||||
|
||||
|
@ -33,7 +33,7 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
}
|
||||
|
||||
// *Frame parameter gets the Frame.
|
||||
f = NewBuiltinFn("f", func(f *Frame) {
|
||||
f = NewGoFn("f", func(f *Frame) {
|
||||
if f != theFrame {
|
||||
t.Errorf("*Frame parameter doesn't get current frame")
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
callGood(theFrame, nil, theOptions)
|
||||
|
||||
// RawOptions parameter gets options.
|
||||
f = NewBuiltinFn("f", func(opts RawOptions) {
|
||||
f = NewGoFn("f", func(opts RawOptions) {
|
||||
if opts["foo"] != "bar" {
|
||||
t.Errorf("RawOptions parameter doesn't get options")
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
callGood(theFrame, nil, RawOptions{"foo": "bar"})
|
||||
|
||||
// ScanOptions parameters gets scanned options.
|
||||
f = NewBuiltinFn("f", func(opts testOptions) {
|
||||
f = NewGoFn("f", func(opts testOptions) {
|
||||
if opts.Foo != "bar" {
|
||||
t.Errorf("ScanOptions parameter doesn't get options")
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
callGood(theFrame, nil, RawOptions{"foo": "bar"})
|
||||
|
||||
// Combination of Frame and RawOptions.
|
||||
f = NewBuiltinFn("f", func(f *Frame, opts RawOptions) {
|
||||
f = NewGoFn("f", func(f *Frame, opts RawOptions) {
|
||||
if f != theFrame {
|
||||
t.Errorf("*Frame parameter doesn't get current frame")
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
callGood(theFrame, nil, RawOptions{"foo": "bar"})
|
||||
|
||||
// Argument passing.
|
||||
f = NewBuiltinFn("f", func(x, y string) {
|
||||
f = NewGoFn("f", func(x, y string) {
|
||||
if x != "lorem" {
|
||||
t.Errorf("Argument x not passed")
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
callGood(theFrame, []interface{}{"lorem", "ipsum"}, theOptions)
|
||||
|
||||
// Variadic arguments.
|
||||
f = NewBuiltinFn("f", func(x ...string) {
|
||||
f = NewGoFn("f", func(x ...string) {
|
||||
if len(x) != 2 || x[0] != "lorem" || x[1] != "ipsum" {
|
||||
t.Errorf("Variadic argument not passed")
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
callGood(theFrame, []interface{}{"lorem", "ipsum"}, theOptions)
|
||||
|
||||
// Conversion into int and float64.
|
||||
f = NewBuiltinFn("f", func(i int, f float64) {
|
||||
f = NewGoFn("f", func(i int, f float64) {
|
||||
if i != 314 {
|
||||
t.Errorf("Integer argument i not passed")
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
callGood(theFrame, []interface{}{"314", "1.25"}, theOptions)
|
||||
|
||||
// Conversion of supplied inputs.
|
||||
f = NewBuiltinFn("f", func(i Inputs) {
|
||||
f = NewGoFn("f", func(i Inputs) {
|
||||
var values []interface{}
|
||||
i(func(x interface{}) {
|
||||
values = append(values, x)
|
||||
|
@ -119,7 +119,7 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
ch <- "bar"
|
||||
close(ch)
|
||||
inFrame.ports[0] = &Port{Chan: ch}
|
||||
f = NewBuiltinFn("f", func(i Inputs) {
|
||||
f = NewGoFn("f", func(i Inputs) {
|
||||
var values []interface{}
|
||||
i(func(x interface{}) {
|
||||
values = append(values, x)
|
||||
|
@ -134,7 +134,7 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
outFrame := &Frame{ports: make([]*Port, 3)}
|
||||
ch = make(chan interface{}, 10)
|
||||
outFrame.ports[1] = &Port{Chan: ch}
|
||||
f = NewBuiltinFn("f", func() string { return "ret" })
|
||||
f = NewGoFn("f", func() string { return "ret" })
|
||||
callGood(outFrame, nil, theOptions)
|
||||
select {
|
||||
case ret := <-ch:
|
||||
|
@ -146,7 +146,7 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
}
|
||||
|
||||
// Conversion of return values.
|
||||
f = NewBuiltinFn("f", func() int { return 314 })
|
||||
f = NewGoFn("f", func() int { return 314 })
|
||||
callGood(outFrame, nil, theOptions)
|
||||
select {
|
||||
case ret := <-ch:
|
||||
|
@ -159,7 +159,7 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
|
||||
// Passing of error return value.
|
||||
theError := errors.New("the error")
|
||||
f = NewBuiltinFn("f", func() (string, error) {
|
||||
f = NewGoFn("f", func() (string, error) {
|
||||
return "x", theError
|
||||
})
|
||||
if f.Call(outFrame, nil, theOptions) != theError {
|
||||
|
@ -172,41 +172,41 @@ func TestReflectBuiltinFnCall(t *testing.T) {
|
|||
}
|
||||
|
||||
// Too many arguments.
|
||||
f = NewBuiltinFn("f", func() {
|
||||
f = NewGoFn("f", func() {
|
||||
t.Errorf("Function called when there are too many arguments")
|
||||
})
|
||||
callBad(theFrame, []interface{}{"x"}, theOptions)
|
||||
|
||||
// Too few arguments.
|
||||
f = NewBuiltinFn("f", func(x string) {
|
||||
f = NewGoFn("f", func(x string) {
|
||||
t.Errorf("Function called when there are too few arguments")
|
||||
})
|
||||
callBad(theFrame, nil, theOptions)
|
||||
f = NewBuiltinFn("f", func(x string, y ...string) {
|
||||
f = NewGoFn("f", func(x string, y ...string) {
|
||||
t.Errorf("Function called when there are too few arguments")
|
||||
})
|
||||
callBad(theFrame, nil, theOptions)
|
||||
|
||||
// Options when the function does not accept options.
|
||||
f = NewBuiltinFn("f", func() {
|
||||
f = NewGoFn("f", func() {
|
||||
t.Errorf("Function called when there are extra options")
|
||||
})
|
||||
callBad(theFrame, nil, RawOptions{"foo": "bar"})
|
||||
|
||||
// Wrong argument type.
|
||||
f = NewBuiltinFn("f", func(x string) {
|
||||
f = NewGoFn("f", func(x string) {
|
||||
t.Errorf("Function called when arguments have wrong type")
|
||||
})
|
||||
callBad(theFrame, []interface{}{1}, theOptions)
|
||||
|
||||
// Wrong argument type: cannot convert to int.
|
||||
f = NewBuiltinFn("f", func(x int) {
|
||||
f = NewGoFn("f", func(x int) {
|
||||
t.Errorf("Function called when arguments have wrong type")
|
||||
})
|
||||
callBad(theFrame, []interface{}{"x"}, theOptions)
|
||||
|
||||
// Wrong argument type: cannot convert to float64.
|
||||
f = NewBuiltinFn("f", func(x float64) {
|
||||
f = NewGoFn("f", func(x float64) {
|
||||
t.Errorf("Function called when arguments have wrong type")
|
||||
})
|
||||
callBad(theFrame, []interface{}{"x"}, theOptions)
|
14
eval/ns.go
14
eval/ns.go
|
@ -92,17 +92,15 @@ func (ns Ns) AddNs(name string, v Ns) Ns {
|
|||
return ns.Add(name+NsSuffix, vars.FromPtr(&v))
|
||||
}
|
||||
|
||||
// AddBuiltinFn adds a builtin function to a namespace. It returns the namespace
|
||||
// itself.
|
||||
func (ns Ns) AddBuiltinFn(nsName, name string, impl interface{}) Ns {
|
||||
return ns.AddFn(name, NewBuiltinFn(nsName+name, impl))
|
||||
// AddGoFn adds a Go function to a namespace. It returns the namespace itself.
|
||||
func (ns Ns) AddGoFn(nsName, name string, impl interface{}) Ns {
|
||||
return ns.AddFn(name, NewGoFn(nsName+name, impl))
|
||||
}
|
||||
|
||||
// AddBuiltinFns adds builtin functions to a namespace. It returns the namespace
|
||||
// itself.
|
||||
func (ns Ns) AddBuiltinFns(nsName string, fns map[string]interface{}) Ns {
|
||||
// AddGoFns adds Go functions to a namespace. It returns the namespace itself.
|
||||
func (ns Ns) AddGoFns(nsName string, fns map[string]interface{}) Ns {
|
||||
for name, impl := range fns {
|
||||
ns.AddBuiltinFn(nsName, name, impl)
|
||||
ns.AddGoFn(nsName, name, impl)
|
||||
}
|
||||
return ns
|
||||
}
|
||||
|
|
|
@ -9,8 +9,9 @@ import (
|
|||
"github.com/elves/elvish/util"
|
||||
)
|
||||
|
||||
// RawOptions is the type of an argument a builtin function can take to declare
|
||||
// that it wants to parse options itself. See the doc of BuiltinFn for details.
|
||||
// RawOptions is the type of an argument a Go-native function can take to
|
||||
// declare that it wants to parse options itself. See the doc of GoFn for
|
||||
// details.
|
||||
type RawOptions map[string]interface{}
|
||||
|
||||
// Takes a raw option map and a pointer to a struct, and populate the struct
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
// Ns is the namespace for the re: module.
|
||||
var Ns = eval.NewNs().AddBuiltinFns("re:", fns)
|
||||
var Ns = eval.NewNs().AddGoFns("re:", fns)
|
||||
|
||||
var fns = map[string]interface{}{
|
||||
"quote": regexp.QuoteMeta,
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
func Ns(s storedefs.Store) eval.Ns {
|
||||
return eval.NewNs().AddBuiltinFns("store:", map[string]interface{}{
|
||||
return eval.NewNs().AddGoFns("store:", map[string]interface{}{
|
||||
"del-dir": s.DelDir,
|
||||
"del-cmd": s.DelCmd,
|
||||
})
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/elves/elvish/eval"
|
||||
)
|
||||
|
||||
var Ns = eval.NewNs().AddBuiltinFns("str:", fns)
|
||||
var Ns = eval.NewNs().AddGoFns("str:", fns)
|
||||
|
||||
var fns = map[string]interface{}{
|
||||
"compare": strings.Compare,
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
func TestKeyHandlerFromBinding_CallsBinding(t *testing.T) {
|
||||
called := 0
|
||||
binding := buildBinding(
|
||||
"a", eval.NewBuiltinFn("[test]", func() { called++ }))
|
||||
"a", eval.NewGoFn("[test]", func() { called++ }))
|
||||
handler := keyHandlerFromBindings(&fakeEditor{}, eval.NewEvaler(), &binding)
|
||||
|
||||
action := handler(ui.Key{Rune: 'a'})
|
||||
|
@ -31,7 +31,7 @@ func TestKeyHandlerFromBinding_SetsBindingKey(t *testing.T) {
|
|||
ed := &fakeEditor{}
|
||||
var gotKey ui.Key
|
||||
binding := buildBinding(
|
||||
"a", eval.NewBuiltinFn("[test]", func() { gotKey = ed.State().BindingKey() }))
|
||||
"a", eval.NewGoFn("[test]", func() { gotKey = ed.State().BindingKey() }))
|
||||
handler := keyHandlerFromBindings(ed, eval.NewEvaler(), &binding)
|
||||
|
||||
key := ui.Key{Rune: 'a'}
|
||||
|
@ -65,10 +65,10 @@ func TestIndexLayeredBindings(t *testing.T) {
|
|||
// 3. Key
|
||||
called := 0
|
||||
binding1 := buildBinding(
|
||||
"a", eval.NewBuiltinFn("[a1]", func() { called = 1 }))
|
||||
"a", eval.NewGoFn("[a1]", func() { called = 1 }))
|
||||
binding2 := buildBinding(
|
||||
"a", eval.NewBuiltinFn("[a2]", func() { called = 2 }),
|
||||
"b", eval.NewBuiltinFn("[b2]", func() { called = 2 }))
|
||||
"a", eval.NewGoFn("[a2]", func() { called = 2 }),
|
||||
"b", eval.NewGoFn("[b2]", func() { called = 2 }))
|
||||
|
||||
handler := keyHandlerFromBindings(&fakeEditor{}, eval.NewEvaler(),
|
||||
&binding1, &binding2)
|
||||
|
@ -88,7 +88,7 @@ func TestIndexLayeredBindings(t *testing.T) {
|
|||
|
||||
// Use lower layer default when upper layer does not have default
|
||||
b, _ := binding2.Assoc(
|
||||
ui.Default, eval.NewBuiltinFn("[d2]", func() { called = 2 }))
|
||||
ui.Default, eval.NewGoFn("[d2]", func() { called = 2 }))
|
||||
binding2 = b.(BindingMap)
|
||||
|
||||
called = 0
|
||||
|
@ -99,7 +99,7 @@ func TestIndexLayeredBindings(t *testing.T) {
|
|||
|
||||
// Prefer upper layer default
|
||||
b, _ = binding1.Assoc(
|
||||
ui.Default, eval.NewBuiltinFn("[d1]", func() { called = 1 }))
|
||||
ui.Default, eval.NewGoFn("[d1]", func() { called = 1 }))
|
||||
binding1 = b.(BindingMap)
|
||||
|
||||
called = 0
|
||||
|
@ -110,7 +110,7 @@ func TestIndexLayeredBindings(t *testing.T) {
|
|||
|
||||
// Exact matches in all layers are tried before falling back to default
|
||||
b, _ = binding2.Assoc(
|
||||
"c", eval.NewBuiltinFn("[c2]", func() { called = 2 }))
|
||||
"c", eval.NewGoFn("[c2]", func() { called = 2 }))
|
||||
binding2 = b.(BindingMap)
|
||||
|
||||
called = 0
|
||||
|
@ -137,7 +137,7 @@ func TestCallBinding_CallsFunction(t *testing.T) {
|
|||
nt := &fakeNotifier{}
|
||||
|
||||
called := 0
|
||||
callBinding(nt, ev, eval.NewBuiltinFn("test binding", func() {
|
||||
callBinding(nt, ev, eval.NewGoFn("test binding", func() {
|
||||
called++
|
||||
}))
|
||||
if called != 1 {
|
||||
|
@ -149,7 +149,7 @@ func TestCallBinding_CapturesAction(t *testing.T) {
|
|||
ev := eval.NewEvaler()
|
||||
nt := &fakeNotifier{}
|
||||
|
||||
action := callBinding(nt, ev, eval.NewBuiltinFn("test", func() error {
|
||||
action := callBinding(nt, ev, eval.NewGoFn("test", func() error {
|
||||
return editutil.ActionError(types.CommitCode)
|
||||
}))
|
||||
if action != types.CommitCode {
|
||||
|
@ -161,7 +161,7 @@ func TestCallBinding_NotifyOnValueOutput(t *testing.T) {
|
|||
ev := eval.NewEvaler()
|
||||
nt := &fakeNotifier{}
|
||||
|
||||
callBinding(nt, ev, eval.NewBuiltinFn("test binding", func(fm *eval.Frame) {
|
||||
callBinding(nt, ev, eval.NewGoFn("test binding", func(fm *eval.Frame) {
|
||||
fm.OutputChan() <- "VALUE"
|
||||
}))
|
||||
wantNotes := []string{"[value out] VALUE"}
|
||||
|
@ -174,7 +174,7 @@ func TestCallBinding_NotifyOnByteOutput(t *testing.T) {
|
|||
ev := eval.NewEvaler()
|
||||
nt := &fakeNotifier{}
|
||||
|
||||
callBinding(nt, ev, eval.NewBuiltinFn("test binding", func(fm *eval.Frame) {
|
||||
callBinding(nt, ev, eval.NewGoFn("test binding", func(fm *eval.Frame) {
|
||||
fm.OutputFile().WriteString("BYTES")
|
||||
}))
|
||||
wantNotes := []string{"[bytes out] BYTES"}
|
||||
|
@ -187,7 +187,7 @@ func TestCallBinding_StripsNewlinesFromByteOutput(t *testing.T) {
|
|||
ev := eval.NewEvaler()
|
||||
nt := &fakeNotifier{}
|
||||
|
||||
callBinding(nt, ev, eval.NewBuiltinFn("test binding", func(fm *eval.Frame) {
|
||||
callBinding(nt, ev, eval.NewGoFn("test binding", func(fm *eval.Frame) {
|
||||
fm.OutputFile().WriteString("line 1\nline 2\n")
|
||||
}))
|
||||
wantNotes := []string{"[bytes out] line 1", "[bytes out] line 2"}
|
||||
|
@ -200,7 +200,7 @@ func TestCallBinding_NotifyOnError(t *testing.T) {
|
|||
ev := eval.NewEvaler()
|
||||
nt := &fakeNotifier{}
|
||||
|
||||
callBinding(nt, ev, eval.NewBuiltinFn("test binding", func() error {
|
||||
callBinding(nt, ev, eval.NewGoFn("test binding", func() error {
|
||||
return errors.New("ERROR")
|
||||
}))
|
||||
wantNotes := []string{"[binding error] ERROR"}
|
||||
|
|
|
@ -32,14 +32,14 @@ func NewEditor(in, out *os.File, ev *eval.Evaler, st storedefs.Store) *Editor {
|
|||
ns := eval.NewNs().
|
||||
Add("max-height",
|
||||
vars.FromPtrWithMutex(&ed.Config.Raw.MaxHeight, &ed.Config.Mutex)).
|
||||
AddBuiltinFns("<edit>", map[string]interface{}{
|
||||
AddGoFns("<edit>", map[string]interface{}{
|
||||
"binding-map": makeBindingMap,
|
||||
"exit-binding": exitBinding,
|
||||
"commit-code": commitCode,
|
||||
"commit-eof": commitEOF,
|
||||
"reset-mode": makeResetMode(ed.State()),
|
||||
}).
|
||||
AddBuiltinFns("<edit>", bufferBuiltins(ed.State()))
|
||||
AddGoFns("<edit>", bufferBuiltins(ed.State()))
|
||||
|
||||
// Hooks
|
||||
ns["before-readline"], ed.BeforeReadline = initBeforeReadline(ev)
|
||||
|
|
|
@ -46,7 +46,7 @@ func TestMakeHasCommand(t *testing.T) {
|
|||
hasCommand := makeHasCommand(ev)
|
||||
|
||||
// Set up global functions and modules in the evaler.
|
||||
goodFn := eval.NewBuiltinFn("good", func() {})
|
||||
goodFn := eval.NewGoFn("good", func() {})
|
||||
ev.Global.AddFn("good", goodFn)
|
||||
aNs := eval.Ns{}.AddFn("good", goodFn)
|
||||
bNs := eval.Ns{}.AddFn("good", goodFn)
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
func TestInitBeforeReadline(t *testing.T) {
|
||||
variable, cb := initBeforeReadline(eval.NewEvaler())
|
||||
called := 0
|
||||
variable.Set(vals.EmptyList.Cons(eval.NewBuiltinFn("[test]", func() {
|
||||
variable.Set(vals.EmptyList.Cons(eval.NewGoFn("[test]", func() {
|
||||
called++
|
||||
})))
|
||||
cb()
|
||||
|
@ -24,7 +24,7 @@ func TestInitAfterReadline(t *testing.T) {
|
|||
variable, cb := initAfterReadline(eval.NewEvaler())
|
||||
called := 0
|
||||
calledWith := ""
|
||||
variable.Set(vals.EmptyList.Cons(eval.NewBuiltinFn("[test]", func(s string) {
|
||||
variable.Set(vals.EmptyList.Cons(eval.NewGoFn("[test]", func(s string) {
|
||||
called++
|
||||
calledWith = s
|
||||
})))
|
||||
|
|
|
@ -29,7 +29,7 @@ func initInsert(ed editor, ev *eval.Evaler) (*insert.Mode, eval.Ns) {
|
|||
"abbr": vars.FromPtr(&abbr),
|
||||
"quote-paste": vars.FromPtrWithMutex(
|
||||
&m.Config.Raw.QuotePaste, &m.Config.Mutex),
|
||||
}.AddBuiltinFns("<edit:insert>:", map[string]interface{}{
|
||||
}.AddGoFns("<edit:insert>:", map[string]interface{}{
|
||||
"start": func() { st.SetMode(m) },
|
||||
"default-handler": func() error {
|
||||
action := editutil.BasicHandler(tty.KeyEvent(st.BindingKey()), st)
|
||||
|
|
|
@ -36,7 +36,7 @@ func TestInitInsert_Binding(t *testing.T) {
|
|||
m, ns := initInsert(&fakeEditor{}, eval.NewEvaler())
|
||||
called := 0
|
||||
binding, err := EmptyBindingMap.Assoc("a",
|
||||
eval.NewBuiltinFn("test binding", func() { called++ }))
|
||||
eval.NewGoFn("test binding", func() { called++ }))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ func initLastcmd(ed editor, ev *eval.Evaler, st storedefs.Store, lsMode *listing
|
|||
KeyHandler: keyHandlerFromBindings(ed, ev, &binding, lsBinding),
|
||||
}
|
||||
ns := eval.Ns{}.
|
||||
AddBuiltinFn("<edit:lastcmd>:", "start", func() {
|
||||
AddGoFn("<edit:lastcmd>:", "start", func() {
|
||||
startLastcmd(ed, st, &mode)
|
||||
})
|
||||
return ns
|
||||
|
|
|
@ -11,7 +11,7 @@ func initListing(ed editor) (*listing.Mode, *BindingMap, eval.Ns) {
|
|||
binding := EmptyBindingMap
|
||||
ns := eval.Ns{
|
||||
"binding": vars.FromPtr(&binding),
|
||||
}.AddBuiltinFns("<edit:listing>:", map[string]interface{}{
|
||||
}.AddGoFns("<edit:listing>:", map[string]interface{}{
|
||||
"up": func() { mode.MutateStates((*listing.State).Up) },
|
||||
"down": func() { mode.MutateStates((*listing.State).Down) },
|
||||
"up-cycle": func() { mode.MutateStates((*listing.State).UpCycle) },
|
||||
|
|
|
@ -49,7 +49,7 @@ func getDefaultPrompt(isRoot bool) eval.Callable {
|
|||
if isRoot {
|
||||
p = styled.Transform(styled.Unstyled("# "), "red")
|
||||
}
|
||||
return eval.NewBuiltinFn("default prompt", func(fm *eval.Frame) {
|
||||
return eval.NewGoFn("default prompt", func(fm *eval.Frame) {
|
||||
out := fm.OutputChan()
|
||||
out <- string(util.Getwd())
|
||||
out <- p
|
||||
|
@ -58,7 +58,7 @@ func getDefaultPrompt(isRoot bool) eval.Callable {
|
|||
|
||||
func getDefaultRPrompt(username, hostname string) eval.Callable {
|
||||
rp := styled.Transform(styled.Unstyled(username+"@"+hostname), "inverse")
|
||||
return eval.NewBuiltinFn("default rprompt", func(fm *eval.Frame) {
|
||||
return eval.NewGoFn("default rprompt", func(fm *eval.Frame) {
|
||||
fm.OutputChan() <- rp
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user