diff options
Diffstat (limited to 'lualibs-package.lua')
-rw-r--r-- | lualibs-package.lua | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/lualibs-package.lua b/lualibs-package.lua new file mode 100644 index 0000000..7b82fa5 --- /dev/null +++ b/lualibs-package.lua @@ -0,0 +1,338 @@ +if not modules then modules = { } end modules ['l-package'] = { + version = 1.001, + comment = "companion to luat-lib.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- Code moved from data-lua and changed into a plug-in. + +-- We overload the regular loader. We do so because we operate mostly in +-- tds and use our own loader code. Alternatively we could use a more +-- extensive definition of package.path and package.cpath but even then +-- we're not done. Also, we now have better tracing. +-- +-- -- local mylib = require("libtest") +-- -- local mysql = require("luasql.mysql") + +local type = type +local gsub, format = string.gsub, string.format + +local P, S, Cs, lpegmatch = lpeg.P, lpeg.S, lpeg.Cs, lpeg.match + +local package = package +local searchers = package.searchers or package.loaders + +-- dummies + +local filejoin = file and file.join or function(path,name) return path .. "/" .. name end +local isreadable = file and file.is_readable or function(name) local f = io.open(name) if f then f:close() return true end end +local addsuffix = file and file.addsuffix or function(name,suffix) return name .. "." .. suffix end + +-- + +-- local separator, concatinator, placeholder, pathofexecutable, ignorebefore = string.match(package.config,"(.-)\n(.-)\n(.-)\n(.-)\n(.-)\n") +-- +-- local config = { +-- separator = separator, -- \ or / +-- concatinator = concatinator, -- ; +-- placeholder = placeholder, -- ? becomes name +-- pathofexecutable = pathofexecutable, -- ! becomes executables dir (on windows) +-- ignorebefore = ignorebefore, -- - remove all before this when making lua_open +-- } + +-- + +local function cleanpath(path) -- hm, don't we have a helper for this? + return path +end + +local pattern = Cs((((1-S("\\/"))^0 * (S("\\/")^1/"/"))^0 * (P(".")^1/"/"+P(1))^1) * -1) + +local function lualibfile(name) + return lpegmatch(pattern,name) or name +end + +local helpers = package.helpers or { + cleanpath = cleanpath, + lualibfile = lualibfile, + trace = false, + report = function(...) print(format(...)) end, + builtin = { + ["preload table"] = searchers[1], -- special case, built-in libs + ["path specification"] = searchers[2], + ["cpath specification"] = searchers[3], + ["all in one fallback"] = searchers[4], -- special case, combined libs + }, + methods = { + }, + sequence = { + "already loaded", + "preload table", + "lua extra list", + "lib extra list", + "path specification", + "cpath specification", + "all in one fallback", + "not loaded", + } +} + +package.helpers = helpers + +local methods = helpers.methods +local builtin = helpers.builtin + +-- extra tds/ctx paths + +local extraluapaths = { } +local extralibpaths = { } +local luapaths = nil -- delayed +local libpaths = nil -- delayed + +local function getextraluapaths() + return extraluapaths +end + +local function getextralibpaths() + return extralibpaths +end + +local function getluapaths() + luapaths = luapaths or file.splitpath(package.path, ";") + return luapaths +end + +local function getlibpaths() + libpaths = libpaths or file.splitpath(package.cpath, ";") + return libpaths +end + +package.luapaths = getluapaths +package.libpaths = getlibpaths +package.extraluapaths = getextraluapaths +package.extralibpaths = getextralibpaths + +local hashes = { + lua = { }, + lib = { }, +} + +local function registerpath(tag,what,target,...) + local pathlist = { ... } + local cleanpath = helpers.cleanpath + local trace = helpers.trace + local report = helpers.report + local hash = hashes[what] + -- + local function add(path) + local path = cleanpath(path) + if not hash[path] then + target[#target+1] = path + hash[path] = true + if trace then + report("registered %s path %s: %s",tag,#target,path) + end + else + if trace then + report("duplicate %s path: %s",tag,path) + end + end + end + -- + for p=1,#pathlist do + local path = pathlist[p] + if type(path) == "table" then + for i=1,#path do + add(path[i]) + end + else + add(path) + end + end + return paths +end + +helpers.registerpath = registerpath + +function package.extraluapath(...) + registerpath("extra lua","lua",extraluapaths,...) +end + +function package.extralibpath(...) + registerpath("extra lib","lib",extralibpaths,...) +end + +-- lib loader (used elsewhere) + +local function loadedaslib(resolved,rawname) -- todo: strip all before first - + -- local init = "luaopen_" .. string.match(rawname,".-([^%.]+)$") + local init = "luaopen_"..gsub(rawname,"%.","_") + if helpers.trace then + helpers.report("calling loadlib with '%s' with init '%s'",resolved,init) + end + return package.loadlib(resolved,init) +end + +helpers.loadedaslib = loadedaslib + +-- wrapped and new loaders + +local function loadedbypath(name,rawname,paths,islib,what) + local trace = helpers.trace + local report = helpers.report + if trace then + report("locating '%s' as '%s' on '%s' paths",rawname,name,what) + end + for p=1,#paths do + local path = paths[p] + local resolved = filejoin(path,name) + if trace then -- mode detail + report("checking '%s' using '%s' path '%s'",name,what,path) + end + if isreadable(resolved) then + if trace then + report("'%s' located on '%s'",name,resolved) + end + local result = nil + if islib then + result = loadedaslib(resolved,rawname) + else + result = loadfile(resolved) + end + if result then + result() + end + return true, result + end + end +end + +helpers.loadedbypath = loadedbypath + +-- alternatively we could set the package.searchers + +methods["already loaded"] = function(name) + local result = package.loaded[name] + if result then + return true, result + end +end + +methods["preload table"] = function(name) + local result = builtin["preload table"](name) + if type(result) == "function" then + return true, result + end +end + +methods["lua extra list"] = function(name) + local thename = lualibfile(name) + local luaname = addsuffix(thename,"lua") + local luapaths = getextraluapaths() + local done, result = loadedbypath(luaname,name,luapaths,false,"lua") + if done then + return true, result + end +end + +methods["lib extra list"] = function(name) + local thename = lualibfile(name) + local libname = addsuffix(thename,os.libsuffix) + local libpaths = getextralibpaths() + local done, result = loadedbypath(libname,name,libpaths,true,"lib") + if done then + return true, result + end +end + +local shown = false + +methods["path specification"] = function(name) + if not shown and helpers.trace then + local luapaths = getluapaths() -- triggers list building + if #luapaths > 0 then + helpers.report("using %s built in lua paths",#luapaths) + else + helpers.report("no built in lua paths defined") + end + shown = true + end + local result = builtin["path specification"](name) + if type(result) == "function" then + return true, result() + end +end + +local shown = false + +methods["cpath specification"] = function(name) + if not shown and helpers.trace then + local libpaths = getlibpaths() -- triggers list building + if #libpaths > 0 then + helpers.report("using %s built in lib paths",#libpaths) + else + helpers.report("no built in lib paths defined") + end + shown = true + end + local result = builtin["cpath specification"](name) + if type(result) == "function" then + return true, result() + end +end + +methods["all in one fallback"] = function(name) + local result = builtin["all in one fallback"](name) + if type(result) == "function" then + return true, result() + end +end + +methods["not loaded"] = function(name) + if helpers.trace then + helpers.report("unable to locate '%s'",name) + end +end + +function helpers.loaded(name) + local sequence = helpers.sequence + for i=1,#sequence do + local step = sequence[i] + if helpers.trace then + helpers.report("locating '%s' using method '%s'",name,step) + end + local done, result = methods[step](name) + if done then + if helpers.trace then + helpers.report("'%s' located via method '%s' returns '%s'",name,step,type(result)) + end + if result then + package.loaded[name] = result + end + return result + end + end + return nil -- we must return a value +end + +function helpers.unload(name) + if helpers.trace then + if package.loaded[name] then + helpers.report("unloading '%s', %s",name,"done") + else + helpers.report("unloading '%s', %s",name,"not loaded") + end + end + package.loaded[name] = nil -- does that work? is readable only, maybe we need our own hash +end + +searchers[1] = nil +searchers[2] = nil +searchers[3] = nil +searchers[4] = nil + +helpers.savedrequire = helpers.savedrequire or require + +require = helpers.loaded |