I made up some code which could be used instead of the old os.loadAPI part. It can't be inserted exactly there, but that's the general idea. The package api should also not be protected like the others, as it contains variables (like package.path) which are meant to be changeable.
this version will also search in a local directory ("/apis").
Please don't reply things like "If you want it, just change it on your cc installation". My request is a global standard for api loading.
-- An example for how to include package lib support
-- This would be inserted into bios.lua instead of os.loadAPI/os.unloadAPI
-- constants
package = {}
package.config = [[/
:
?
]]
package.path = "./?:.?./lua:/apis/?:/apis/?.lua:/rom/apis/?:/rom:/apis/?.lua"
if turtle then
package.path = package.path .. ":/rom/apis/turtle/?:/rom:/apis/turtle/?.lua"
end
-- loaded/preload can't be overridden. their localness also improves the speed.
local loaded = {}
local preload = {}
package.loaded = loaded
package.preload = preload
-- Init loaded native apis
for k,v in pairs( _G ) do
if type(k) == "string" and type(v) == "table" and k ~= "_G" then
loaded[k] = v
end
end
-- define the searcher order
package.searchers = {
-- search preload
function(modname)
return preload[modname]
end,
-- search path
function(modname)
local file = package.searchpath(modname, path)
if not file then
return nil
end
-- load the lua file
local func, err = loadfile(file)
if func then
-- successfully loaded
return func, fs.getName(file)
else
error(err)
end
end
}
local function getconf(line)
for opt in string.gmatch(package.config, "[^\n]" do
if line == 1 then
return opt
end
line = line - 1
end
end
function package.searchpath(name, path, sep, rep)
-- replace directory pattern
sep = sep or "."
rep = rep or getconf(1)
local nameWithRep = string.gsub(name, "%" .. sep, rep)
local qmpattern = "%" .. getconf(3)
-- save the attempts for the error message
local attempts = {}
for pPath in string.gmatch(path, "[^" .. getconf(2) .. "]+") do
-- inject module name
pPath = shell.resolve(string.gsub(pPath, qmpattern, nameWithRep))
if fs.exists( sPath ) and not fs.isDir( sPath ) then
return sPath
end
-- add to missed attempts
table.insert(attempts, pPath)
end
return nil, table.concat(attempts, ", ")
end
function require(modname)
if type(modname) ~= "string" then
error("Invalid arg; string expected")
end
-- check for already loaded libraries
local lib = loaded[modname]
if lib then
return lib
end
-- find a loader
local loader, source
for _,s in ipairs(package.searchers)
loader, source = s(modname)
if loader then
break
end
end
if not loader then
error("Module not available: " .. modname)
end
-- load the library
lib = loader(modname, source) or true -- if the loader returns nil, use true instead
-- save for later use
loaded[modname] = lib
return lib
end
-- some apis need to be loaded early
term = require "term"
rednet = require "rednet"
textutils = require "textutils"
if turtle then
require "turtle"
end