diff --git a/CHANGELOG.md b/CHANGELOG.md index c07d540..58a0cd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased ### Added - Forward/Right arrow key will fill in hint text (#327) +- Values returned by bait hooks will be passed to the `throw` caller ## [2.3.4] - 2024-12-28 ### Fixed diff --git a/golibs/bait/bait.go b/golibs/bait/bait.go index 1f85c76..9a38d02 100644 --- a/golibs/bait/bait.go +++ b/golibs/bait/bait.go @@ -47,7 +47,7 @@ type Recoverer func(event string, handler *Listener, err interface{}) type Listener struct{ typ listenerType once bool - caller func(...interface{}) + caller func(...interface{}) rt.Value luaCaller *rt.Closure } @@ -73,10 +73,11 @@ func New(rtm *rt.Runtime) *Bait { } // Emit throws an event. -func (b *Bait) Emit(event string, args ...interface{}) { +func (b *Bait) Emit(event string, args ...interface{}) []rt.Value { + var returns []rt.Value handles := b.handlers[event] if handles == nil { - return + return nil } for idx, handle := range handles { @@ -97,28 +98,37 @@ func (b *Bait) Emit(event string, args ...interface{}) { } luaArgs = append(luaArgs, luarg) } - _, err := rt.Call1(b.rtm.MainThread(), funcVal, luaArgs...) + luaRet, err := rt.Call1(b.rtm.MainThread(), funcVal, luaArgs...) if err != nil { if event != "error" { b.Emit("error", event, handle.luaCaller, err.Error()) - return + return nil } // if there is an error in an error event handler, panic instead // (calls the go recoverer function) panic(err) } + + if luaRet != rt.NilValue { + returns = append(returns, luaRet) + } } else { - handle.caller(args...) + ret := handle.caller(args...) + if ret != rt.NilValue { + returns = append(returns, ret) + } } if handle.once { b.removeListener(event, idx) } } + + return returns } // On adds a Go function handler for an event. -func (b *Bait) On(event string, handler func(...interface{})) *Listener { +func (b *Bait) On(event string, handler func(...interface{}) rt.Value) *Listener { listener := &Listener{ typ: goListener, caller: handler, @@ -130,7 +140,7 @@ func (b *Bait) On(event string, handler func(...interface{})) *Listener { // OnLua adds a Lua function handler for an event. func (b *Bait) OnLua(event string, handler *rt.Closure) *Listener { - listener :=&Listener{ + listener := &Listener{ typ: luaListener, luaCaller: handler, } @@ -162,7 +172,7 @@ func (b *Bait) OffLua(event string, handler *rt.Closure) { } // Once adds a Go function listener for an event that only runs once. -func (b *Bait) Once(event string, handler func(...interface{})) *Listener { +func (b *Bait) Once(event string, handler func(...interface{}) rt.Value) *Listener { listener := &Listener{ typ: goListener, once: true, @@ -226,27 +236,6 @@ func (b *Bait) loaderFunc(rtm *rt.Runtime) (rt.Value, func()) { return rt.TableValue(mod), nil } -func handleHook(t *rt.Thread, c *rt.GoCont, name string, catcher *rt.Closure, args ...interface{}) { - funcVal := rt.FunctionValue(catcher) - var luaArgs []rt.Value - for _, arg := range args { - var luarg rt.Value - switch arg.(type) { - case rt.Value: luarg = arg.(rt.Value) - default: luarg = rt.AsValue(arg) - } - luaArgs = append(luaArgs, luarg) - } - _, err := rt.Call1(t, funcVal, luaArgs...) - if err != nil { - e := rt.NewError(rt.StringValue(err.Error())) - e = e.AddContext(c.Next(), 1) - // panicking here won't actually cause hilbish to panic and instead will - // print the error and remove the hook (look at emission recover from above) - panic(e) - } -} - // catch(name, cb) // Catches an event. This function can be used to act on events. // #param name string The name of the hook. @@ -370,7 +359,7 @@ func (b *Bait) bthrow(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { for i, v := range c.Etc() { ifaceSlice[i] = v } - b.Emit(name, ifaceSlice...) + ret := b.Emit(name, ifaceSlice...) - return c.Next(), nil + return c.PushingNext(t.Runtime, ret...), nil } diff --git a/lua.go b/lua.go index 859a39d..9ae030a 100644 --- a/lua.go +++ b/lua.go @@ -46,10 +46,11 @@ func luaInit() { lib.LoadLibs(l, hooks.Loader) // Add Ctrl-C handler - hooks.On("signal.sigint", func(...interface{}) { + hooks.On("signal.sigint", func(...interface{}) rt.Value { if !interactive { os.Exit(0) } + return rt.NilValue }) lr.rl.RawInputCallback = func(r []rune) {