Lua - Custom Module Loader
Lua custom module loading mechanism provides a greater control over how Lua finds and loads a module. require function is flexible and allows us to extend its behavior by using custom module loader.
By default, a module is loaded from a predefined set of path/pattern or from current directory. Using custom loader we can insert our own custom logic in between this process, to load a module from a custom location, handle different file type or even use network based module files.
package.loaders table
Lua maintains a global table package.loaders. This table maintains the entries of functions which Lua calls in order when a module is loaded using require import. Each function is a loader which takes module name, searches and loads the module.
Default Loader Functions
Following are the default loader functions used by Lua package.loaders table.
A loader function to search preloaded modules in path defined by package.preload
A loader function to search lua files in path defined by package.path
A loader function to search C libraries in path defined by package.cpath
A loader function to act as a fallback loader to return an error message as no relevant module found.
Creating a Custom Loader
In order to implement a custom loader, we can define a function which follows input and output format of package.loaders table.
Example - Loading a Module from Custom Directory
In this example, we'll be loading a module from custom_modules folder present in current directory.
Let's define a module file stringutils.lua in custom_modules directory in current folder as described below −
./custom_modules/stringutils.lua
local utils = {}
-- function to reverse a string
function utils.reverse(s)
return s:reverse()
end
-- function to get string in uppercase
function utils.uppercase(s)
return s:upper()
end
-- function to get string in lowercase
function utils.lowercase(s)
return s:lower()
end
-- function to check a substring
function utils.contains(s, sub)
return s:find(sub, 1, true) ~= nil
end
return utils
Now, in order to access module from custom_module directory, say, moduletutorial.lua, you need to use the following code segment.
moduletutorial.lua
-- we're adding custom loader in the beginning of package.loaders table.
table.insert(package.loaders, 2, function(module_name)
local filename = "./custom_modules/" .. module_name .. ".lua"
local f, err = loadfile(filename) -- load the module
if f then
-- Execute the loaded module
return f
else
-- return nil with error message
return nil, "Couldn't load module '" .. module_name .. "' from '" .. filename .. "': " .. err
end
end)
-- using require on 'custom_modules' directory
local custom_module = require("stringutils")
print(custom_module.uppercase("tutorialspoint"))
Output
IWhen we run the above program, we will get the following output−
TUTORIALSPOINT
Explanation
stringutils.lua
We've created an empty table utils as a module defined few functions on strings and returned the table as a module.
This file is created in custom_modules directory under current directory.
moduletutorial.lua
table.insert(package.loaders, 2, function(module_name) − adds a custom loader function in the beginning of package.loader table.
local filename = "./custom_modules/" .. module_name .. ".lua" − is used to get the Lua file name using the module name.
local f, err = loadfile(filename) − load the module.
If module is found, it is returned otherwise nil is returned with an error message.
local custom_module = require("stringutils") loads the module from custom_modules directory and then a function is called to print a result.