Skip to content

Plugin-as-a-Library #145

Open
Open
@ThistleSifter

Description

@ThistleSifter

I was toying with the idea of writing plugins in such a way so that they can be called by other plugins, aka plugin-as-a-library (not the best name, I know). At the moment this is just an idea and I haven't tried it out, but combined with the state management offered by finenv.RetainLuaState, this could open up some interesting opportunities for interactions between plugins.

I came across a method for checking if a script is included as a library or whether it is the main script.
Using it in a plugin means the following is possible:

src/my_plugin.lua

-- True if this script is included as a library, false if it's the main script
local is_library = pcall(debug.getlocal, 4, 1)

...
-- plugin defining code
...

-- At the end of the file
if is_library then
    -- As library
    return dialog
else
    -- As main script
    dialog:ExecuteModal(nil)
end

If exposing the whole dialog object is not desirable (and I imagine it wouldn't be), we could have a factory for creating wrapping tables:

-- function finalemix.create_wrapper(object, exposed_methods)

if is_library then
    return finalemix.create_wrapper(dialog, {'ExecuteModal', 'MyCustomFunction', 'MyOtherCustomFunction'})
end

And if control over preserving/refeshing state is needed, the plugin could return a create function, which then returns a dialog or a wrapper as desired. Then the calling plugin would be in control of when the plugin-as-a-library is retained or garbage collected.

Possible usage:

src/consuming_plugin.lua

-- my_plugin returns a create function when run as a library
local my_plugin = require('my_plugin')

...
-- plugin defining code
...

-- create a button that invokes my_plugin
-- to save some lines, named controls are taken from the dialog mixin I'm currently working on
dialog:CreateButton(10, 10, 'my_plugin_ctrl')

dialog:RegisterHandleControlEvent(dialog:GetControl('my_plugin_ctrl'), function(ctrl)
    if not dialog.my_plugin then
        dialog.my_plugin = my_plugin()
    end

    dialog.my_plugin.ExecuteModal(dialog)
    -- Additional tasks or testing the return value can be done here as well
end)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions