Compare commits

..

2 Commits

Author SHA1 Message Date
TorchedSammy cc6e5d01dd docs: [ci] generate new docs 2022-10-11 21:43:22 +00:00
TorchedSammy 068a5b5149
feat(bait): add error hook and hooks function (closes #205)
an `error` hook is now thrown when an event in lua
throws an error (errors from go side should not happen)
it includes the event name, handler, and error message

a hooks function has also been added. it returns a table
of handlers for a specific event.
2022-10-11 17:41:13 -04:00
6 changed files with 55 additions and 3 deletions

View File

@ -2,6 +2,8 @@ catch(name, cb) > Catches a hook with `name`. Runs the `cb` when it is thrown
catchOnce(name, cb) > Same as catch, but only runs the `cb` once and then removes the hook catchOnce(name, cb) > Same as catch, but only runs the `cb` once and then removes the hook
hooks(name) -> {cb, cb...} > Returns a table with hooks on the event with `name`.
release(name, catcher) > Removes the `catcher` for the event with `name` release(name, catcher) > Removes the `catcher` for the event with `name`
For this to work, `catcher` has to be the same function used to catch For this to work, `catcher` has to be the same function used to catch
an event, like one saved to a variable. an event, like one saved to a variable.

View File

@ -6,3 +6,8 @@ Here is the format for a doc for a hook:
`<args>` just means the arguments of the hook. If a hook doc has the format `<args>` just means the arguments of the hook. If a hook doc has the format
of `arg...`, it means the hook can take/recieve any number of `arg`. of `arg...`, it means the hook can take/recieve any number of `arg`.
+ error -> eventName, handler, err > Emitted when there is an error in
an event handler. The `eventName` is the name of the event the handler
is for, the `handler` is the callback function, and `err` is the error
message.

View File

@ -12,6 +12,9 @@ function bait.catch(name, cb) end
--- @param cb function --- @param cb function
function bait.catchOnce(name, cb) end function bait.catchOnce(name, cb) end
--- Returns a table with hooks on the event with `name`.
function bait.hooks() end
--- Removes the `catcher` for the event with `name` --- Removes the `catcher` for the event with `name`
--- For this to work, `catcher` has to be the same function used to catch --- For this to work, `catcher` has to be the same function used to catch
--- an event, like one saved to a variable. --- an event, like one saved to a variable.

View File

@ -1,6 +1,8 @@
package bait package bait
import ( import (
"errors"
"hilbish/util" "hilbish/util"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
@ -72,8 +74,12 @@ func (b *Bait) Emit(event string, args ...interface{}) {
} }
_, err := rt.Call1(b.rtm.MainThread(), funcVal, luaArgs...) _, err := rt.Call1(b.rtm.MainThread(), funcVal, luaArgs...)
if err != nil { if err != nil {
// panicking here won't actually cause hilbish to panic and instead will if event != "error" {
// print the error and remove the hook. reference the recoverer function in lua.go b.Emit("error", event, handle.luaCaller, err.Error())
return
}
// if there is an error in an error event handler, panic instead
// (calls the go recoverer function)
panic(err) panic(err)
} }
} else { } else {
@ -187,6 +193,7 @@ func (b *Bait) loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
"catchOnce": util.LuaExport{b.bcatchOnce, 2, false}, "catchOnce": util.LuaExport{b.bcatchOnce, 2, false},
"throw": util.LuaExport{b.bthrow, 1, true}, "throw": util.LuaExport{b.bthrow, 1, true},
"release": util.LuaExport{b.brelease, 2, false}, "release": util.LuaExport{b.brelease, 2, false},
"hooks": util.LuaExport{b.bhooks, 1, false},
} }
mod := rt.NewTable() mod := rt.NewTable()
util.SetExports(rtm, mod, exports) util.SetExports(rtm, mod, exports)
@ -289,3 +296,33 @@ func (b *Bait) brelease(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil return c.Next(), nil
} }
// hooks(name) -> {cb, cb...}
// Returns a table with hooks on the event with `name`.
func (b *Bait) bhooks(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
evName, err := c.StringArg(0)
if err != nil {
return nil, err
}
noHooks := errors.New("no hooks for event " + evName)
handlers := b.handlers[evName]
if handlers == nil {
return nil, noHooks
}
luaHandlers := rt.NewTable()
for _, handler := range handlers {
if handler.typ != luaListener { continue }
luaHandlers.Set(rt.IntValue(luaHandlers.Len() + 1), rt.FunctionValue(handler.luaCaller))
}
if luaHandlers.Len() == 0 {
return nil, noHooks
}
return c.PushingNext1(t.Runtime, rt.TableValue(luaHandlers)), nil
}

2
lua.go
View File

@ -49,7 +49,7 @@ func luaInit() {
hooks = bait.New(l) hooks = bait.New(l)
hooks.SetRecoverer(func(event string, handler *bait.Listener, err interface{}) { hooks.SetRecoverer(func(event string, handler *bait.Listener, err interface{}) {
fmt.Println("Error in", event, "event:", err) fmt.Println("Error in `error` hook handler:", err)
hooks.Off(event, handler) hooks.Off(event, handler)
}) })

View File

@ -1,5 +1,6 @@
-- Prelude initializes everything else for our shell -- Prelude initializes everything else for our shell
local _ = require 'succulent' -- Function additions local _ = require 'succulent' -- Function additions
local bait = require 'bait'
local fs = require 'fs' local fs = require 'fs'
package.path = package.path .. ';' .. hilbish.dataDir .. '/?/init.lua' package.path = package.path .. ';' .. hilbish.dataDir .. '/?/init.lua'
@ -64,3 +65,7 @@ do
package.path = package.path .. ';' .. startSearchPath package.path = package.path .. ';' .. startSearchPath
end end
bait.catch('error', function(event, handler, err)
bait.release(event, handler)
end)