moonscript, busted, penlight packages + debugger speed improvements
This commit is contained in:
8
pl/.package
Normal file
8
pl/.package
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
title = 'Penlight',
|
||||
repository = 'kepler155c/opus-apps/{{OPUS_BRANCH}}/pl',
|
||||
description = [[See: https://github.com/Tieske/Penlight
|
||||
|
||||
Penlight brings together a set of generally useful pure Lua modules, focusing on input data handling (such as reading configuration files), functional programming (such as map, reduce, placeholder expressions, etc), and OS path management. Much of the functionality is inspired by the Python standard libraries.]],
|
||||
license = 'MIT',
|
||||
}
|
||||
188
pl/apis/compat.lua
Normal file
188
pl/apis/compat.lua
Normal file
@@ -0,0 +1,188 @@
|
||||
----------------
|
||||
--- Lua 5.1/5.2/5.3 compatibility.
|
||||
-- Injects `table.pack`, `table.unpack`, and `package.searchpath` in the global
|
||||
-- environment, to make sure they are available for Lua 5.1 and LuaJIT.
|
||||
--
|
||||
-- All other functions are exported as usual in the returned module table.
|
||||
--
|
||||
-- NOTE: everything in this module is also available in `pl.utils`.
|
||||
-- @module pl.compat
|
||||
local compat = {}
|
||||
|
||||
--- boolean flag this is Lua 5.1 (or LuaJIT).
|
||||
-- @field lua51
|
||||
compat.lua51 = _VERSION == 'Lua 5.1'
|
||||
|
||||
--- boolean flag this is LuaJIT.
|
||||
-- @field jit
|
||||
compat.jit = (tostring(assert):match('builtin') ~= nil)
|
||||
|
||||
--- boolean flag this is LuaJIT with 5.2 compatibility compiled in.
|
||||
-- @field jit52
|
||||
if compat.jit then
|
||||
-- 'goto' is a keyword when 52 compatibility is enabled in LuaJit
|
||||
compat.jit52 = not loadstring("local goto = 1")
|
||||
end
|
||||
|
||||
--- the directory separator character for the current platform.
|
||||
-- @field dir_separator
|
||||
compat.dir_separator = _ENV.package.config:sub(1,1)
|
||||
|
||||
--- boolean flag this is a Windows platform.
|
||||
-- @field is_windows
|
||||
compat.is_windows = compat.dir_separator == '\\'
|
||||
|
||||
--- execute a shell command, in a compatible and platform independent way.
|
||||
-- This is a compatibility function that returns the same for Lua 5.1 and
|
||||
-- Lua 5.2+.
|
||||
--
|
||||
-- NOTE: Windows systems can use signed 32bit integer exitcodes. Posix systems
|
||||
-- only use exitcodes 0-255, anything else is undefined.
|
||||
-- @param cmd a shell command
|
||||
-- @return true if successful
|
||||
-- @return actual return code
|
||||
function compat.execute(cmd)
|
||||
local res1,res2,res3 = os.execute(cmd)
|
||||
if res2 == "No error" and res3 == 0 and compat.is_windows then
|
||||
-- os.execute bug in Lua 5.2+ not reporting -1 properly on Windows
|
||||
res3 = -1
|
||||
end
|
||||
if compat.lua51 and not compat.jit52 then
|
||||
if compat.is_windows then
|
||||
return res1==0,res1
|
||||
else
|
||||
res1 = res1 > 255 and res1 / 256 or res1
|
||||
return res1==0,res1
|
||||
end
|
||||
else
|
||||
if compat.is_windows then
|
||||
return res3==0,res3
|
||||
else
|
||||
return not not res1,res3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------
|
||||
-- Load Lua code as a text or binary chunk (in a Lua 5.2 compatible way).
|
||||
-- @param ld code string or loader
|
||||
-- @param[opt] source name of chunk for errors
|
||||
-- @param[opt] mode 'b', 't' or 'bt'
|
||||
-- @param[opt] env environment to load the chunk in
|
||||
-- @function compat.load
|
||||
|
||||
---------------
|
||||
-- Get environment of a function (in a Lua 5.1 compatible way).
|
||||
-- Not 100% compatible, so with Lua 5.2 it may return nil for a function with no
|
||||
-- global references!
|
||||
-- Based on code by [Sergey Rozhenko](http://lua-users.org/lists/lua-l/2010-06/msg00313.html)
|
||||
-- @param f a function or a call stack reference
|
||||
-- @function compat.getfenv
|
||||
|
||||
---------------
|
||||
-- Set environment of a function (in a Lua 5.1 compatible way).
|
||||
-- @param f a function or a call stack reference
|
||||
-- @param env a table that becomes the new environment of `f`
|
||||
-- @function compat.setfenv
|
||||
|
||||
if compat.lua51 then -- define Lua 5.2 style load()
|
||||
if not compat.jit then -- but LuaJIT's load _is_ compatible
|
||||
local lua51_load = load
|
||||
function compat.load(str,src,mode,env)
|
||||
local chunk,err
|
||||
if type(str) == 'string' then
|
||||
if str:byte(1) == 27 and not (mode or 'bt'):find 'b' then
|
||||
return nil,"attempt to load a binary chunk"
|
||||
end
|
||||
chunk,err = loadstring(str,src)
|
||||
else
|
||||
chunk,err = lua51_load(str,src)
|
||||
end
|
||||
if chunk and env then setfenv(chunk,env) end
|
||||
return chunk,err
|
||||
end
|
||||
else
|
||||
compat.load = load
|
||||
end
|
||||
compat.setfenv, compat.getfenv = setfenv, getfenv
|
||||
else
|
||||
compat.load = load
|
||||
-- setfenv/getfenv replacements for Lua 5.2
|
||||
-- by Sergey Rozhenko
|
||||
-- http://lua-users.org/lists/lua-l/2010-06/msg00313.html
|
||||
-- Roberto Ierusalimschy notes that it is possible for getfenv to return nil
|
||||
-- in the case of a function with no globals:
|
||||
-- http://lua-users.org/lists/lua-l/2010-06/msg00315.html
|
||||
function compat.setfenv(f, t)
|
||||
f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func)
|
||||
local name
|
||||
local up = 0
|
||||
repeat
|
||||
up = up + 1
|
||||
name = debug.getupvalue(f, up)
|
||||
until name == '_ENV' or name == nil
|
||||
if name then
|
||||
debug.upvaluejoin(f, up, function() return name end, 1) -- use unique upvalue
|
||||
debug.setupvalue(f, up, t)
|
||||
end
|
||||
if f ~= 0 then return f end
|
||||
end
|
||||
|
||||
function compat.getfenv(f)
|
||||
local f = f or 0
|
||||
f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func)
|
||||
local name, val
|
||||
local up = 0
|
||||
repeat
|
||||
up = up + 1
|
||||
name, val = debug.getupvalue(f, up)
|
||||
until name == '_ENV' or name == nil
|
||||
return val
|
||||
end
|
||||
end
|
||||
|
||||
--- Global exported functions (for Lua 5.1 & LuaJIT)
|
||||
-- @section lua52
|
||||
|
||||
--- pack an argument list into a table.
|
||||
-- @param ... any arguments
|
||||
-- @return a table with field n set to the length
|
||||
-- @function table.pack
|
||||
if not table.pack then
|
||||
function table.pack (...) -- luacheck: ignore
|
||||
return {n=select('#',...); ...}
|
||||
end
|
||||
end
|
||||
|
||||
--- unpack a table and return the elements.
|
||||
--
|
||||
-- NOTE: this version does NOT honor the n field, and hence it is not nil-safe.
|
||||
-- See `utils.unpack` for a version that is nil-safe.
|
||||
-- @param t table to unpack
|
||||
-- @param[opt] i index from which to start unpacking, defaults to 1
|
||||
-- @param[opt] t index of the last element to unpack, defaults to #t
|
||||
-- @return multiple return values from the table
|
||||
-- @function table.unpack
|
||||
-- @see utils.unpack
|
||||
if not table.unpack then
|
||||
table.unpack = unpack -- luacheck: ignore
|
||||
end
|
||||
|
||||
--- return the full path where a Lua module name would be matched.
|
||||
-- @param mod module name, possibly dotted
|
||||
-- @param path a path in the same form as package.path or package.cpath
|
||||
-- @see path.package_path
|
||||
-- @function package.searchpath
|
||||
if not package.searchpath then
|
||||
local sep = package.config:sub(1,1)
|
||||
function package.searchpath (mod,path) -- luacheck: ignore
|
||||
mod = mod:gsub('%.',sep)
|
||||
for m in path:gmatch('[^;]+') do
|
||||
local nm = m:gsub('?',mod)
|
||||
local f = io.open(nm,'r')
|
||||
if f then f:close(); return nm end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return compat
|
||||
445
pl/apis/path.lua
Normal file
445
pl/apis/path.lua
Normal file
@@ -0,0 +1,445 @@
|
||||
--- Path manipulation and file queries.
|
||||
--
|
||||
-- This is modelled after Python's os.path library (10.1); see @{04-paths.md|the Guide}.
|
||||
--
|
||||
-- Dependencies: `pl.utils`, `lfs`
|
||||
-- @module pl.path
|
||||
|
||||
-- imports and locals
|
||||
local _G = _G
|
||||
local sub = string.sub
|
||||
local getenv = os.getenv
|
||||
local tmpnam = os.tmpname
|
||||
local attributes, currentdir, link_attrib
|
||||
local package = package
|
||||
local append, concat, remove = table.insert, table.concat, table.remove
|
||||
local utils = require 'pl.utils'
|
||||
local assert_string,raise = utils.assert_string,utils.raise
|
||||
|
||||
local attrib
|
||||
local path = {}
|
||||
|
||||
local lfs = require('lfs')
|
||||
attributes = lfs.attributes
|
||||
currentdir = lfs.currentdir
|
||||
link_attrib = lfs.symlinkattributes
|
||||
|
||||
|
||||
attrib = attributes
|
||||
path.attrib = attrib
|
||||
path.link_attrib = link_attrib
|
||||
|
||||
--- Lua iterator over the entries of a given directory.
|
||||
-- Behaves like `lfs.dir`
|
||||
path.dir = lfs.dir
|
||||
|
||||
--- Creates a directory.
|
||||
path.mkdir = lfs.mkdir
|
||||
|
||||
--- Removes a directory.
|
||||
path.rmdir = lfs.rmdir
|
||||
|
||||
---- Get the working directory.
|
||||
path.currentdir = currentdir
|
||||
|
||||
--- Changes the working directory.
|
||||
path.chdir = lfs.chdir
|
||||
|
||||
|
||||
--- is this a directory?
|
||||
-- @string P A file path
|
||||
function path.isdir(P)
|
||||
assert_string(1,P)
|
||||
if P:match("\\$") then
|
||||
P = P:sub(1,-2)
|
||||
end
|
||||
return attrib(P,'mode') == 'directory'
|
||||
end
|
||||
|
||||
--- is this a file?.
|
||||
-- @string P A file path
|
||||
function path.isfile(P)
|
||||
assert_string(1,P)
|
||||
return attrib(P,'mode') == 'file'
|
||||
end
|
||||
|
||||
-- is this a symbolic link?
|
||||
-- @string P A file path
|
||||
function path.islink(P)
|
||||
assert_string(1,P)
|
||||
if link_attrib then
|
||||
return link_attrib(P,'mode')=='link'
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- return size of a file.
|
||||
-- @string P A file path
|
||||
function path.getsize(P)
|
||||
assert_string(1,P)
|
||||
return attrib(P,'size')
|
||||
end
|
||||
|
||||
--- does a path exist?.
|
||||
-- @string P A file path
|
||||
-- @return the file path if it exists, nil otherwise
|
||||
function path.exists(P)
|
||||
assert_string(1,P)
|
||||
return attrib(P,'mode') ~= nil and P
|
||||
end
|
||||
|
||||
--- Return the time of last access as the number of seconds since the epoch.
|
||||
-- @string P A file path
|
||||
function path.getatime(P)
|
||||
assert_string(1,P)
|
||||
return attrib(P,'access')
|
||||
end
|
||||
|
||||
--- Return the time of last modification
|
||||
-- @string P A file path
|
||||
function path.getmtime(P)
|
||||
assert_string(1,P)
|
||||
return attrib(P,'modification')
|
||||
end
|
||||
|
||||
---Return the system's ctime.
|
||||
-- @string P A file path
|
||||
function path.getctime(P)
|
||||
assert_string(1,P)
|
||||
return path.attrib(P,'change')
|
||||
end
|
||||
|
||||
|
||||
local function at(s,i)
|
||||
return sub(s,i,i)
|
||||
end
|
||||
|
||||
path.is_windows = utils.is_windows
|
||||
|
||||
local other_sep
|
||||
-- !constant sep is the directory separator for this platform.
|
||||
if path.is_windows then
|
||||
path.sep = '\\'; other_sep = '/'
|
||||
path.dirsep = ';'
|
||||
else
|
||||
path.sep = '/'
|
||||
path.dirsep = ':'
|
||||
end
|
||||
local sep = path.sep
|
||||
|
||||
--- are we running Windows?
|
||||
-- @class field
|
||||
-- @name path.is_windows
|
||||
|
||||
--- path separator for this platform.
|
||||
-- @class field
|
||||
-- @name path.sep
|
||||
|
||||
--- separator for PATH for this platform
|
||||
-- @class field
|
||||
-- @name path.dirsep
|
||||
|
||||
--- given a path, return the directory part and a file part.
|
||||
-- if there's no directory part, the first value will be empty
|
||||
-- @string P A file path
|
||||
function path.splitpath(P)
|
||||
assert_string(1,P)
|
||||
local i = #P
|
||||
local ch = at(P,i)
|
||||
while i > 0 and ch ~= sep and ch ~= other_sep do
|
||||
i = i - 1
|
||||
ch = at(P,i)
|
||||
end
|
||||
if i == 0 then
|
||||
return '',P
|
||||
else
|
||||
return sub(P,1,i-1), sub(P,i+1)
|
||||
end
|
||||
end
|
||||
|
||||
--- return an absolute path.
|
||||
-- @string P A file path
|
||||
-- @string[opt] pwd optional start path to use (default is current dir)
|
||||
function path.abspath(P,pwd)
|
||||
assert_string(1,P)
|
||||
if pwd then assert_string(2,pwd) end
|
||||
local use_pwd = pwd ~= nil
|
||||
if not use_pwd and not currentdir then return P end
|
||||
P = P:gsub('[\\/]$','')
|
||||
pwd = pwd or currentdir()
|
||||
if not path.isabs(P) then
|
||||
P = path.join(pwd,P)
|
||||
elseif path.is_windows and not use_pwd and at(P,2) ~= ':' and at(P,2) ~= '\\' then
|
||||
P = pwd:sub(1,2)..P -- attach current drive to path like '\\fred.txt'
|
||||
end
|
||||
return path.normpath(P)
|
||||
end
|
||||
|
||||
--- given a path, return the root part and the extension part.
|
||||
-- if there's no extension part, the second value will be empty
|
||||
-- @string P A file path
|
||||
-- @treturn string root part
|
||||
-- @treturn string extension part (maybe empty)
|
||||
function path.splitext(P)
|
||||
assert_string(1,P)
|
||||
local i = #P
|
||||
local ch = at(P,i)
|
||||
while i > 0 and ch ~= '.' do
|
||||
if ch == sep or ch == other_sep then
|
||||
return P,''
|
||||
end
|
||||
i = i - 1
|
||||
ch = at(P,i)
|
||||
end
|
||||
if i == 0 then
|
||||
return P,''
|
||||
else
|
||||
return sub(P,1,i-1),sub(P,i)
|
||||
end
|
||||
end
|
||||
|
||||
--- return the directory part of a path
|
||||
-- @string P A file path
|
||||
function path.dirname(P)
|
||||
assert_string(1,P)
|
||||
local p1 = path.splitpath(P)
|
||||
return p1
|
||||
end
|
||||
|
||||
--- return the file part of a path
|
||||
-- @string P A file path
|
||||
function path.basename(P)
|
||||
assert_string(1,P)
|
||||
local _,p2 = path.splitpath(P)
|
||||
return p2
|
||||
end
|
||||
|
||||
--- get the extension part of a path.
|
||||
-- @string P A file path
|
||||
function path.extension(P)
|
||||
assert_string(1,P)
|
||||
local _,p2 = path.splitext(P)
|
||||
return p2
|
||||
end
|
||||
|
||||
--- is this an absolute path?.
|
||||
-- @string P A file path
|
||||
function path.isabs(P)
|
||||
assert_string(1,P)
|
||||
if path.is_windows then
|
||||
return at(P,1) == '/' or at(P,1)=='\\' or at(P,2)==':'
|
||||
else
|
||||
return at(P,1) == '/'
|
||||
end
|
||||
end
|
||||
|
||||
--- return the path resulting from combining the individual paths.
|
||||
-- if the second (or later) path is absolute, we return the last absolute path (joined with any non-absolute paths following).
|
||||
-- empty elements (except the last) will be ignored.
|
||||
-- @string p1 A file path
|
||||
-- @string p2 A file path
|
||||
-- @string ... more file paths
|
||||
function path.join(p1,p2,...)
|
||||
assert_string(1,p1)
|
||||
assert_string(2,p2)
|
||||
if select('#',...) > 0 then
|
||||
local p = path.join(p1,p2)
|
||||
local args = {...}
|
||||
for i = 1,#args do
|
||||
assert_string(i,args[i])
|
||||
p = path.join(p,args[i])
|
||||
end
|
||||
return p
|
||||
end
|
||||
if path.isabs(p2) then return p2 end
|
||||
local endc = at(p1,#p1)
|
||||
if endc ~= path.sep and endc ~= other_sep and endc ~= "" then
|
||||
p1 = p1..path.sep
|
||||
end
|
||||
return p1..p2
|
||||
end
|
||||
|
||||
--- normalize the case of a pathname. On Unix, this returns the path unchanged;
|
||||
-- for Windows, it converts the path to lowercase, and it also converts forward slashes
|
||||
-- to backward slashes.
|
||||
-- @string P A file path
|
||||
function path.normcase(P)
|
||||
assert_string(1,P)
|
||||
if path.is_windows then
|
||||
return (P:lower():gsub('/','\\'))
|
||||
else
|
||||
return P
|
||||
end
|
||||
end
|
||||
|
||||
--- normalize a path name.
|
||||
-- `A//B`, `A/./B`, and `A/foo/../B` all become `A/B`.
|
||||
-- @string P a file path
|
||||
function path.normpath(P)
|
||||
assert_string(1,P)
|
||||
-- Split path into anchor and relative path.
|
||||
local anchor = ''
|
||||
if path.is_windows then
|
||||
if P:match '^\\\\' then -- UNC
|
||||
anchor = '\\\\'
|
||||
P = P:sub(3)
|
||||
elseif at(P, 1) == '/' or at(P, 1) == '\\' then
|
||||
anchor = '\\'
|
||||
P = P:sub(2)
|
||||
elseif at(P, 2) == ':' then
|
||||
anchor = P:sub(1, 2)
|
||||
P = P:sub(3)
|
||||
if at(P, 1) == '/' or at(P, 1) == '\\' then
|
||||
anchor = anchor..'\\'
|
||||
P = P:sub(2)
|
||||
end
|
||||
end
|
||||
P = P:gsub('/','\\')
|
||||
else
|
||||
-- According to POSIX, in path start '//' and '/' are distinct,
|
||||
-- but '///+' is equivalent to '/'.
|
||||
if P:match '^//' and at(P, 3) ~= '/' then
|
||||
anchor = '//'
|
||||
P = P:sub(3)
|
||||
elseif at(P, 1) == '/' then
|
||||
anchor = '/'
|
||||
P = P:match '^/*(.*)$'
|
||||
end
|
||||
end
|
||||
local parts = {}
|
||||
for part in P:gmatch('[^'..sep..']+') do
|
||||
if part == '..' then
|
||||
if #parts ~= 0 and parts[#parts] ~= '..' then
|
||||
remove(parts)
|
||||
else
|
||||
append(parts, part)
|
||||
end
|
||||
elseif part ~= '.' then
|
||||
append(parts, part)
|
||||
end
|
||||
end
|
||||
P = anchor..concat(parts, sep)
|
||||
if P == '' then P = '.' end
|
||||
return P
|
||||
end
|
||||
|
||||
--- relative path from current directory or optional start point
|
||||
-- @string P a path
|
||||
-- @string[opt] start optional start point (default current directory)
|
||||
function path.relpath (P,start)
|
||||
assert_string(1,P)
|
||||
if start then assert_string(2,start) end
|
||||
local split,min,append = utils.split, math.min, table.insert
|
||||
P = path.abspath(P,start)
|
||||
start = start or currentdir()
|
||||
local compare
|
||||
if path.is_windows then
|
||||
P = P:gsub("/","\\")
|
||||
start = start:gsub("/","\\")
|
||||
compare = function(v) return v:lower() end
|
||||
else
|
||||
compare = function(v) return v end
|
||||
end
|
||||
local startl, Pl = split(start,sep), split(P,sep)
|
||||
local n = min(#startl,#Pl)
|
||||
if path.is_windows and n > 0 and at(Pl[1],2) == ':' and Pl[1] ~= startl[1] then
|
||||
return P
|
||||
end
|
||||
local k = n+1 -- default value if this loop doesn't bail out!
|
||||
for i = 1,n do
|
||||
if compare(startl[i]) ~= compare(Pl[i]) then
|
||||
k = i
|
||||
break
|
||||
end
|
||||
end
|
||||
local rell = {}
|
||||
for i = 1, #startl-k+1 do rell[i] = '..' end
|
||||
if k <= #Pl then
|
||||
for i = k,#Pl do append(rell,Pl[i]) end
|
||||
end
|
||||
return table.concat(rell,sep)
|
||||
end
|
||||
|
||||
|
||||
--- Replace a starting '~' with the user's home directory.
|
||||
-- In windows, if HOME isn't set, then USERPROFILE is used in preference to
|
||||
-- HOMEDRIVE HOMEPATH. This is guaranteed to be writeable on all versions of Windows.
|
||||
-- @string P A file path
|
||||
function path.expanduser(P)
|
||||
assert_string(1,P)
|
||||
if at(P,1) == '~' then
|
||||
local home = getenv('HOME')
|
||||
if not home then -- has to be Windows
|
||||
home = getenv 'USERPROFILE' or (getenv 'HOMEDRIVE' .. getenv 'HOMEPATH')
|
||||
end
|
||||
return home..sub(P,2)
|
||||
else
|
||||
return P
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---Return a suitable full path to a new temporary file name.
|
||||
-- unlike os.tmpname(), it always gives you a writeable path (uses TEMP environment variable on Windows)
|
||||
function path.tmpname ()
|
||||
local res = tmpnam()
|
||||
-- On Windows if Lua is compiled using MSVC14 os.tmpname
|
||||
-- already returns an absolute path within TEMP env variable directory,
|
||||
-- no need to prepend it.
|
||||
if path.is_windows and not res:find(':') then
|
||||
res = getenv('TEMP')..res
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
--- return the largest common prefix path of two paths.
|
||||
-- @string path1 a file path
|
||||
-- @string path2 a file path
|
||||
function path.common_prefix (path1,path2)
|
||||
assert_string(1,path1)
|
||||
assert_string(2,path2)
|
||||
-- get them in order!
|
||||
if #path1 > #path2 then path2,path1 = path1,path2 end
|
||||
local compare
|
||||
if path.is_windows then
|
||||
path1 = path1:gsub("/", "\\")
|
||||
path2 = path2:gsub("/", "\\")
|
||||
compare = function(v) return v:lower() end
|
||||
else
|
||||
compare = function(v) return v end
|
||||
end
|
||||
for i = 1,#path1 do
|
||||
if compare(at(path1,i)) ~= compare(at(path2,i)) then
|
||||
local cp = path1:sub(1,i-1)
|
||||
if at(path1,i-1) ~= sep then
|
||||
cp = path.dirname(cp)
|
||||
end
|
||||
return cp
|
||||
end
|
||||
end
|
||||
if at(path2,#path1+1) ~= sep then path1 = path.dirname(path1) end
|
||||
return path1
|
||||
--return ''
|
||||
end
|
||||
|
||||
--- return the full path where a particular Lua module would be found.
|
||||
-- Both package.path and package.cpath is searched, so the result may
|
||||
-- either be a Lua file or a shared library.
|
||||
-- @string mod name of the module
|
||||
-- @return on success: path of module, lua or binary
|
||||
-- @return on error: nil,error string
|
||||
function path.package_path(mod)
|
||||
assert_string(1,mod)
|
||||
local res
|
||||
mod = mod:gsub('%.',sep)
|
||||
res = package.searchpath(mod,package.path)
|
||||
if res then return res,true end
|
||||
res = package.searchpath(mod,package.cpath)
|
||||
if res then return res,false end
|
||||
return raise 'cannot find module on path'
|
||||
end
|
||||
|
||||
|
||||
---- finis -----
|
||||
return path
|
||||
1
pl/etc/fstab
Normal file
1
pl/etc/fstab
Normal file
@@ -0,0 +1 @@
|
||||
packages/pl/apis gitfs Tieske/Penlight/master/lua/pl
|
||||
19
pl/init/6.penlight.lua
Normal file
19
pl/init/6.penlight.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
--[[
|
||||
local getfenv = _G.getfenv
|
||||
|
||||
-- penlight requires a global package to determine path separator
|
||||
-- some funky things in penlight regarding global access
|
||||
_G.package = {
|
||||
config = '/\n:\n?\n!\n-',
|
||||
}
|
||||
|
||||
_G.require = function(module)
|
||||
for i = 2, 3 do
|
||||
local env = getfenv(i)
|
||||
if env ~= _G then
|
||||
return env.require(module)
|
||||
end
|
||||
end
|
||||
error('invalid environment for require')
|
||||
end
|
||||
]]
|
||||
Reference in New Issue
Block a user