Posted 01 June 2018 - 12:50 AM
libloader
Decided to write a small library that adds support for lua require. I see now after writing this utility that it has been done before by Oddstr13 thought this one is a bit different. Instead of being based on 5.1 docs I based it on 5.3 docs, the only difference afaik being that 5.3 renamed package.loaders to package.searchers.
One thing this library supports which Oddstr13 didn't is the possibility of loading libraries from the program's working directory by using "./" in the package.path string
Basic usage
if it doesn't find anything there it will look in /lib and /bin
By default it will not find non lua files when looking in <workdir> due to the possibility of accidentally loading
a non library like a config file.
package.path is set to "./?.lua;./lib/?.lua;./lib/?;./bin/?.lua;./bin/?;/lib/?.lua;/lib/?;/bin/?.lua;/bin/?"
but it can be changed by calling setPath
Lua 5.3 doc: http://www.lua.org/m...al.html#Modules
Pastebin: https://pastebin.com/tt8eQALP
Moonscript source:
Transpiled lua:
Decided to write a small library that adds support for lua require. I see now after writing this utility that it has been done before by Oddstr13 thought this one is a bit different. Instead of being based on 5.1 docs I based it on 5.3 docs, the only difference afaik being that 5.3 renamed package.loaders to package.searchers.
One thing this library supports which Oddstr13 didn't is the possibility of loading libraries from the program's working directory by using "./" in the package.path string
Basic usage
local _libloader = dofile("path/to/libloader")
local mylibrary = require("mylibrary")
mylibrary.doSomething()
By default libloader is set up to look for libraries in the program's working directory (including <workdir>/lib and <workdir>/bin)if it doesn't find anything there it will look in /lib and /bin
By default it will not find non lua files when looking in <workdir> due to the possibility of accidentally loading
a non library like a config file.
package.path is set to "./?.lua;./lib/?.lua;./lib/?;./bin/?.lua;./bin/?;/lib/?.lua;/lib/?;/bin/?.lua;/bin/?"
but it can be changed by calling setPath
local _libloader = dofile("path/to/libloader")
_libloader.setPath("./?.lua")
local mylibrary = require("mylibrary")
mylibrary.doSomething()
Lua 5.3 doc: http://www.lua.org/m...al.html#Modules
Pastebin: https://pastebin.com/tt8eQALP
Moonscript source:
Spoiler
preload = {}
loaded = {}
searchers = {}
searchpath = (name, path, sep=".", rep="/") ->
err = "Could not find #{name}\n"
currDir = shell.getRunningProgram()
path = path\gsub("%./", "#{currDir}/")
name = name\gsub("[#{sep}]", rep)
path = path\gsub("[?]", name)
for test in path\gmatch("[^;]+")
if fs.exists(test) and not fs.isDir(test)
return test
else
err ..= " #{test}\n"
return nil, err
preloadSearcher = (name) ->
if package.preload[name]
return package.preload[name]
return nil, "Could not find #{name} in package.preload"
simplePathSearcher = (name) ->
path = searchpath(name, package.path)
return dofile, path
table.insert(searchers, preloadSearcher)
table.insert(searchers, simplePathSearcher)
export require = (name) ->
errors = {}
if not loaded[name]
loader = nil
arg = nil
for _, searcher in ipairs(searchers)
loader, arg = searcher(name)
if loader != nil
break
else
table.insert(errors, arg)
if loader != nil
status, res = xpcall(
() ->
loader(arg),
(err) ->
return "An error occured while loading #{name} #{tostring(err)}"
)
if(not status)
error(res)
loaded[name] = res or {}
else
errStr = "Failed to load module #{name}\n"
for _, err in ipairs(errors)
errStr ..= "#{err}\n"
error(errStr)
return loaded[name]
export package = {
:preload,
:searchers,
:loaded,
path: "./?.lua;./lib/?.lua;./lib/?;./bin/?.lua;./bin/?;/lib/?.lua;/lib/?;/bin/?.lua;/bin/?",
:searchpath
}
return {
setPath: (path) ->
package.path = path
}
Transpiled lua:
Spoiler
local preload = { }
local loaded = { }
local searchers = { }
local searchpath
searchpath = function(name, path, sep, rep)
if sep == nil then
sep = "."
end
if rep == nil then
rep = "/"
end
local err = "Could not find " .. tostring(name) .. "\n"
local currDir = shell.getRunningProgram()
path = path:gsub("%./", tostring(currDir) .. "/")
name = name:gsub("[" .. tostring(sep) .. "]", rep)
path = path:gsub("[?]", name)
for test in path:gmatch("[^;]+") do
if fs.exists(test) and not fs.isDir(test) then
return test
else
err = err .. " " .. tostring(test) .. "\n"
end
end
return nil, err
end
local preloadSearcher
preloadSearcher = function(name)
if package.preload[name] then
return package.preload[name]
end
return nil, "Could not find " .. tostring(name) .. " in package.preload"
end
local simplePathSearcher
simplePathSearcher = function(name)
local path = searchpath(name, package.path)
return dofile, path
end
table.insert(searchers, preloadSearcher)
table.insert(searchers, simplePathSearcher)
require = function(name)
local errors = { }
if not loaded[name] then
local loader = nil
local arg = nil
for _, searcher in ipairs(searchers) do
loader, arg = searcher(name)
if loader ~= nil then
break
else
table.insert(errors, arg)
end
end
if loader ~= nil then
local status, res = xpcall(function()
return loader(arg)
end, function(err)
return "An error occured while loading " .. tostring(name) .. " " .. tostring(tostring(err))
end)
if (not status) then
error(res)
end
loaded[name] = res or { }
else
local errStr = "Failed to load module " .. tostring(name) .. "\n"
for _, err in ipairs(errors) do
errStr = errStr .. tostring(err) .. "\n"
end
error(errStr)
end
end
return loaded[name]
end
package = {
preload = preload,
searchers = searchers,
loaded = loaded,
path = "./?.lua;./lib/?.lua;./lib/?;./bin/?.lua;./bin/?;/lib/?.lua;/lib/?;/bin/?.lua;/bin/?",
searchpath = searchpath
}
return {
setPath = function(path)
package.path = path
end
}
Edited on 01 June 2018 - 11:44 AM