Module:Sandbox/KickahaOta/Loader

From Path of Exile Wiki
Revision as of 02:31, 20 December 2021 by KickahaOta (talk | contribs) (Test lazy loader)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
Module documentation[create] [purge]
local loader = {}

-- caller_module_name: The name of the module calling us, without the 'Module:' prefix. Set by loader.init.
loader.caller_module_name = nil

-- base_util: Module:Util. Optionally set by loader.init. Loaded by us if needed otherwise.
loader.base_util = nil

-- registered_modules: Association table:
--    Key: the name of the main version of the module, without the Module: prefix.
--        Example: 'Item2'.
--    Value: Association table:
--        'handle': object; the loaded copy of the module, or nil if it has not yet been loaded.
--        'use_loaddata': string or boolean:
--           'yes' or true: load module using dwLoadData
--           'no' or false: load module using require
--        'use_sandbox': string:
--           'yes': always load the sandbox version of the module
--           'maybe' : use util.maybe_sandbox to decide
--           'no': always load the main version of the module
loader.registered_modules = {}

-- init: Must be called before any other loader function.
-- Arguments:
--   module_name: The name of the calling module, without the 'Module:' prefix.
--       Example: 'Item2'.
--   util: A copy of Module:Util, if you've already loaded it. Can be nil.
function loader.init(module_name, util)
    loader.caller_module_name = module_name or error('No module name supplied')
    loader.base_util = util
end

-- is_inited: Returns true if init has previously been called.
function loader.is_inited()
    return (loader.caller_module_name ~= nil)
end

-- verify_init: Throws an error if init has not previously been called.
function loader.verify_init()
    local test = loader.isinited() or error('Loader has not been initialized')
end

-- Wrapper around Util:maybe_sandbox
function loader.maybe_sandbox()
    loader.verify_init()
    loader.base_util = loader.base_util or require('Module:Util')
    return base_util.misc.maybe_sandbox(loader.caller_module_name)
end

-- Registers a module to be loaded later
-- Arguments:
--    name: the name of the main version of the module, without the Module: prefix.
--        Example: 'Item2'.
--    args: Association table:
--        'use_loaddata': string or boolean:
--           'yes' or true: load module using dwLoadData
--           'no', false, or omitted: load module using require
--        'use_sandbox': string or boolean:
--           'yes' or true: always load the sandbox version of the module
--           'maybe' : use util.maybe_sandbox to decide
--           'no', false, or omitted: always load the main version of the module
function loader.register(name, args)
    if (name == nil) or (name == '') then 
        error('no name supplied')
    end

    args = args or {}
    args.use_loaddata = args.use_loaddata or false
    args.use_sandbox = args.use_sandbox or false
    if loader.registered_modules[name] ~= nil then
        error(string.format('Module %s already registered', name))
    end
    local new_module = {
        handle = nil,
        use_loaddata = args.use_loaddata,
        use_sandbox = args.use_sandbox
    }
    loader.registered_modules[name] = new_module
end

local function yesmaybeno(arg, nomaybe)
    local arg_str = string.lower(tostring(arg))
    if arg == true or arg_str == 'yes' then
        return true
    elseif arg_str == 'maybe' and not nomaybe then
        return loader.maybe_sandbox()
    elseif arg == false or arg == nil or arg_str == 'no' then
        return false
    else
        error(string.format('Unrecognized value %s', tostring(arg)))
    end
end

local function yesno(arg)
    return yesmaybeno(arg, true)
end

-- Retrieves a module that was registered earlier, loading it if needed.
-- Arguments:
--    name: the name of the main version of the module, without the Module: prefix.
--        Example: 'Item2'.
function loader.get(name)
    if (name == nil) or (name == '') then 
        error('no name supplied')
    end
    local info = loader.registered_modules[name]
    if info == nil then
        error(string.format('Module %s is not registered', name))
    end
    if info['handle'] ~= nil then
        return info['handle']
    end

    local use_sandbox = yesmaybeno(info['use_sandbox'])
    local module_id = 'Module:' .. name
    if use_sandbox then
        module_id = module_id .. '/sandbox'
    end

    local use_loaddata = yesno(info['use_loaddata'])
    if use_loaddata then
        loader.registered_modules[name]['handle'] = mw.loadData(module_id)
    else
        loader.registered_modules[name]['handle'] = require(module_id)
    end
    return loader.registered_modules[name]['handle']        
end

return loader