Incorporating Lua with Livtet
One of the goals I have with Livtet is to incorporate a means of extensibility. I didn't want to deeply write support for things like Calibre, Goodreads or Bookwyrm because these services can change their outward facing implementations on a whim, in response to a security change or the like. Having an extension system felt like the best way to work around this. Also I try to imagine this tool replacing my use and need for Calibre, that's still some time off. But I do look to how it allows plugins to manipulate and extend its behavior. In the case of Livtet, at the time of writing, plugins aren't declarable by the user in the interface, you'd have to modify the manifest file with the following:
This is a list of three library lookup definitions and in the case of loading Lua extensions, Livtet knows to do that by looking at the payload value and wrapping that in a contextual extension for that plugin. I chose to share the Lua context across plug-ins to allow for plugins to share logic as opposed to spinning up a new one for each plugin. The way a Lua extensions talks to Livtet is straight-forward: it declares an (currently undocumented) interface to the host and Livtet invokes some code to extract that value from it to complete an operation. For example, if I wanted to get the list of books across my shelves from my Bookwyrm profile, some of the Lua code looks like this:
Livtet provides a per-invocation global method, options, that allows some information that the plugin requires for operation; in this case, the Bookwyrm extension requires the profile URL that it'll work with. The act of calling this from Livtet looks like the following:
Quite a bit is going on here. So a run-down:
We grab a safe reference to the Lua context, Compose the Lua script we'll evaluate for our needs, We determine what kind of value M.library returns and pluck items from it; this mirrors the trait definition. We call it and convert each of the value returned into ones Livtet can work with.
This approach is something that's been simple to replicate. Writing out tests for this currently require hitting actual remote services which slow down the tests just a tad and run the risk, if I ran this on every commit — for example, of being blocked. I don't think it'll happen but I'm known for thinking of "what if". That said, these changes allow me to present these collections locally with little to no effort!
This is shifting my thinking about how I want libraries to show in Livtet. But that's for another post!
Discussion in the ATmosphere