mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Scribunto
synced 2024-12-02 11:56:13 +00:00
162 lines
4.4 KiB
Lua
162 lines
4.4 KiB
Lua
|
--[[
|
||
|
-- A package library similar to the one that comes with Lua 5.1, but without
|
||
|
-- the local filesystem access. Based on Compat-5.1 which comes with the
|
||
|
-- following license notice:
|
||
|
--
|
||
|
-- Copyright © 2004-2006 The Kepler Project.
|
||
|
--
|
||
|
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||
|
-- this software and associated documentation files (the "Software"), to deal in
|
||
|
-- the Software without restriction, including without limitation the rights to
|
||
|
-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||
|
-- the Software, and to permit persons to whom the Software is furnished to do so,
|
||
|
-- subject to the following conditions:
|
||
|
--
|
||
|
-- The above copyright notice and this permission notice shall be included in all
|
||
|
-- copies or substantial portions of the Software.
|
||
|
--
|
||
|
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||
|
-- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||
|
-- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||
|
-- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||
|
-- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
--]]
|
||
|
|
||
|
|
||
|
local assert, error, getfenv, ipairs, pairs, setfenv, setmetatable, type = assert, error, getfenv, ipairs, pairs, setfenv, setmetatable, type
|
||
|
local find, format, gfind, gsub, sub = string.find, string.format, string.gfind, string.gsub, string.sub
|
||
|
|
||
|
--
|
||
|
-- avoid overwriting the package table if it's already there
|
||
|
--
|
||
|
package = package or {}
|
||
|
local _PACKAGE = package
|
||
|
|
||
|
package.loaded = package.loaded or {}
|
||
|
local _LOADED = package.loaded
|
||
|
|
||
|
--
|
||
|
-- avoid overwriting the package.preload table if it's already there
|
||
|
--
|
||
|
package.preload = package.preload or {}
|
||
|
local _PRELOAD = package.preload
|
||
|
|
||
|
--
|
||
|
-- check whether library is already loaded
|
||
|
--
|
||
|
local function loader_preload (name)
|
||
|
assert (type(name) == "string", format (
|
||
|
"bad argument #1 to `require' (string expected, got %s)", type(name)))
|
||
|
assert (type(_PRELOAD) == "table", "`package.preload' must be a table")
|
||
|
return _PRELOAD[name]
|
||
|
end
|
||
|
|
||
|
-- create `loaders' table
|
||
|
package.loaders = package.loaders or { loader_preload }
|
||
|
local _LOADERS = package.loaders
|
||
|
|
||
|
--
|
||
|
-- iterate over available loaders
|
||
|
--
|
||
|
local function load (name, loaders)
|
||
|
-- iterate over available loaders
|
||
|
assert (type (loaders) == "table", "`package.loaders' must be a table")
|
||
|
for i, loader in ipairs (loaders) do
|
||
|
local f = loader (name)
|
||
|
if f then
|
||
|
return f
|
||
|
end
|
||
|
end
|
||
|
error (format ("module `%s' not found", name))
|
||
|
end
|
||
|
|
||
|
-- sentinel
|
||
|
local sentinel = function () end
|
||
|
|
||
|
--
|
||
|
-- require
|
||
|
--
|
||
|
function _G.require (modname)
|
||
|
assert (type(modname) == "string", format (
|
||
|
"bad argument #1 to `require' (string expected, got %s)", type(name)))
|
||
|
local p = _LOADED[modname]
|
||
|
if p then -- is it there?
|
||
|
if p == sentinel then
|
||
|
error (format ("loop or previous error loading module '%s'", modname))
|
||
|
end
|
||
|
return p -- package is already loaded
|
||
|
end
|
||
|
local init = load (modname, _LOADERS)
|
||
|
_LOADED[modname] = sentinel
|
||
|
local actual_arg = _G.arg
|
||
|
_G.arg = { modname }
|
||
|
local res = init (modname)
|
||
|
if res then
|
||
|
_LOADED[modname] = res
|
||
|
end
|
||
|
_G.arg = actual_arg
|
||
|
if _LOADED[modname] == sentinel then
|
||
|
_LOADED[modname] = true
|
||
|
end
|
||
|
return _LOADED[modname]
|
||
|
end
|
||
|
|
||
|
|
||
|
-- findtable
|
||
|
local function findtable (t, f)
|
||
|
assert (type(f)=="string", "not a valid field name ("..tostring(f)..")")
|
||
|
local ff = f.."."
|
||
|
local ok, e, w = find (ff, '(.-)%.', 1)
|
||
|
while ok do
|
||
|
local nt = rawget (t, w)
|
||
|
if not nt then
|
||
|
nt = {}
|
||
|
t[w] = nt
|
||
|
elseif type(t) ~= "table" then
|
||
|
return sub (f, e+1)
|
||
|
end
|
||
|
t = nt
|
||
|
ok, e, w = find (ff, '(.-)%.', e+1)
|
||
|
end
|
||
|
return t
|
||
|
end
|
||
|
|
||
|
--
|
||
|
-- package.seeall function
|
||
|
--
|
||
|
function _PACKAGE.seeall (module)
|
||
|
local t = type(module)
|
||
|
assert (t == "table", "bad argument #1 to package.seeall (table expected, got "..t..")")
|
||
|
local meta = getmetatable (module)
|
||
|
if not meta then
|
||
|
meta = {}
|
||
|
setmetatable (module, meta)
|
||
|
end
|
||
|
meta.__index = _G
|
||
|
end
|
||
|
|
||
|
|
||
|
--
|
||
|
-- module function
|
||
|
--
|
||
|
function _G.module (modname, ...)
|
||
|
local ns = _LOADED[modname]
|
||
|
if type(ns) ~= "table" then
|
||
|
ns = findtable (_G, modname)
|
||
|
if not ns then
|
||
|
error (string.format ("name conflict for module '%s'", modname))
|
||
|
end
|
||
|
_LOADED[modname] = ns
|
||
|
end
|
||
|
if not ns._NAME then
|
||
|
ns._NAME = modname
|
||
|
ns._M = ns
|
||
|
ns._PACKAGE = gsub (modname, "[^.]*$", "")
|
||
|
end
|
||
|
setfenv (2, ns)
|
||
|
for i, f in ipairs (...) do
|
||
|
f (ns)
|
||
|
end
|
||
|
end
|