Hilbish/golibs/bait/bait.go

132 lines
3.2 KiB
Go
Raw Normal View History

2021-03-26 05:12:55 +00:00
package bait
import (
"fmt"
"hilbish/util"
2022-03-28 21:48:12 +00:00
rt "github.com/arnodel/golua/runtime"
"github.com/arnodel/golua/lib/packagelib"
"github.com/chuckpreslar/emission"
2021-03-26 05:12:55 +00:00
)
2021-03-30 23:47:02 +00:00
type Bait struct{
Em *emission.Emitter
2022-03-28 21:48:12 +00:00
Loader packagelib.Loader
2021-03-30 23:47:02 +00:00
}
2021-03-26 05:12:55 +00:00
func New() Bait {
emitter := emission.NewEmitter()
emitter.RecoverWith(func(hookname, hookfunc interface{}, err error) {
emitter.Off(hookname, hookfunc)
fmt.Println(err)
})
2022-03-28 21:48:12 +00:00
b := Bait{
Em: emitter,
2021-03-30 23:47:02 +00:00
}
2022-03-28 21:48:12 +00:00
b.Loader = packagelib.Loader{
Load: b.LoaderFunc,
Name: "bait",
}
return b
2021-03-26 05:12:55 +00:00
}
2022-03-28 21:48:12 +00:00
func (b *Bait) LoaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
exports := map[string]util.LuaExport{
"catch": util.LuaExport{b.bcatch, 2, false},
"catchOnce": util.LuaExport{b.bcatchOnce, 2, false},
"throw": util.LuaExport{b.bthrow, 1, true},
}
mod := rt.NewTable()
util.SetExports(rtm, mod, exports)
2021-11-22 23:58:30 +00:00
2022-03-28 21:48:12 +00:00
/*
2021-11-22 23:58:30 +00:00
util.Document(L, mod,
`Bait is the event emitter for Hilbish. Why name it bait?
Because it throws hooks that you can catch (emits events
that you can listen to) and because why not, fun naming
is fun. This is what you will use if you want to listen
in on hooks to know when certain things have happened,
like when you've changed directory, a command has
failed, etc. To find all available hooks, see doc hooks.`)
2022-03-28 21:48:12 +00:00
*/
2021-11-22 23:58:30 +00:00
2022-03-28 21:48:12 +00:00
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)
}
2021-03-26 05:12:55 +00:00
}
// throw(name, ...args)
// Throws a hook with `name` with the provided `args`
// --- @param name string
// --- @vararg any
2022-03-28 21:48:12 +00:00
func (b *Bait) bthrow(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
name, err := c.StringArg(0)
if err != nil {
return nil, err
}
ifaceSlice := make([]interface{}, len(c.Etc()))
for i, v := range c.Etc() {
ifaceSlice[i] = v
}
b.Em.Emit(name, ifaceSlice...)
return c.Next(), nil
2021-03-30 23:47:02 +00:00
}
// catch(name, cb)
// Catches a hook with `name`. Runs the `cb` when it is thrown
// --- @param name string
// --- @param cb function
2022-03-28 21:48:12 +00:00
func (b *Bait) bcatch(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
name, catcher, err := util.HandleStrCallback(t, c)
2022-03-28 21:48:12 +00:00
if err != nil {
return nil, err
}
b.Em.On(name, func(args ...interface{}) {
handleHook(t, c, name, catcher, args...)
})
return c.Next(), nil
2021-03-30 23:47:02 +00:00
}
2021-12-04 21:59:19 +00:00
// catchOnce(name, cb)
// Same as catch, but only runs the `cb` once and then removes the hook
// --- @param name string
// --- @param cb function
2022-03-28 21:48:12 +00:00
func (b *Bait) bcatchOnce(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
name, catcher, err := util.HandleStrCallback(t, c)
2022-03-28 21:48:12 +00:00
if err != nil {
return nil, err
}
b.Em.Once(name, func(args ...interface{}) {
handleHook(t, c, name, catcher, args...)
})
return c.Next(), nil
2021-12-04 21:59:19 +00:00
}