228 lines
No EOL
5.3 KiB
Lua
228 lines
No EOL
5.3 KiB
Lua
require "functools"
|
|
require "itertools"
|
|
require "operators"
|
|
|
|
-- Return the elements in t1 not in t2
|
|
function difference(i1, i2)
|
|
local t2 = collect(i2)
|
|
function filt(x)
|
|
return not any(map(partial(op_eq, x), t2))
|
|
end
|
|
return filter(filt, i1)
|
|
end
|
|
|
|
function string:lstrip()
|
|
local idx = self:find("[^ ]")
|
|
if idx then
|
|
return self:sub(idx)
|
|
else
|
|
return self
|
|
end
|
|
end
|
|
|
|
-- Returns a string representing a "friendly" representation of x
|
|
local _rec = {}
|
|
function show(x, indent)
|
|
indent = indent or ""
|
|
if x == nil then
|
|
return indent .. "nil"
|
|
end
|
|
-- safeguard against recursion
|
|
if _rec[x] then
|
|
return indent .. tostring(x)
|
|
end
|
|
_rec[x] = true
|
|
if type(x) == "table" then
|
|
local newindent = indent .. " "
|
|
local res = indent .. "{\n"
|
|
for k, v in pairs(x) do
|
|
local key = show(k, newindent)
|
|
local value = show(v, newindent .. " ")
|
|
res = res .. key .. " = " .. value:lstrip() .. ",\n"
|
|
end
|
|
res = res .. indent .. "}"
|
|
_rec[x] = nil
|
|
return res
|
|
elseif type(x) == "string" then
|
|
_rec[x] = nil
|
|
return indent .. string.format("%q", x)
|
|
else
|
|
_rec[x] = nil
|
|
return indent .. tostring(x)
|
|
end
|
|
end
|
|
|
|
-- Modify (merge) the content of t with the other tables.
|
|
function updatetable(t, t2, ...)
|
|
t = t or {}
|
|
if t2 ~= nil then
|
|
for k,v in pairs(t2) do
|
|
t[k] = v
|
|
end
|
|
end
|
|
if ... then
|
|
updatetable(t, ...)
|
|
end
|
|
return t
|
|
end
|
|
|
|
-- Modify (add) the content of t with the other tables.
|
|
function updatetable_add(t, t2, ...)
|
|
t = t or {}
|
|
if t2 ~= nil then
|
|
for k,v in pairs(t2) do
|
|
if type(t[k]) == "table" then
|
|
if type(v) == "table" then
|
|
updatetable_add(t[k], v)
|
|
else
|
|
iif(not contains(t[k], v), table.insert(t[k], v))
|
|
end
|
|
elseif type(v) == "table" then
|
|
if contains(v, t[k]) or t[k] == nil then
|
|
t[k] = v
|
|
else
|
|
local temp = copytable(v) -- to avoid modifying v
|
|
table.insert(temp, t[k])
|
|
t[k] = temp
|
|
end
|
|
elseif type(k) == "number" then
|
|
iif(not contains(t, v), table.insert(t, v))
|
|
else
|
|
t[k] = iif(t[k] and t[k] ~= v, { t[k], v }, v )
|
|
end
|
|
end
|
|
end
|
|
if ... then
|
|
updatetable(t, ...)
|
|
end
|
|
return t
|
|
end
|
|
|
|
-- Merge the content of all tables together.
|
|
function mergetables(...)
|
|
return updatetable({}, ...)
|
|
end
|
|
|
|
-- Return a copy of table t.
|
|
function copytable(t)
|
|
return mergetables(t)
|
|
end
|
|
|
|
-- Join all the path components together in a single path.
|
|
function joinpath(p, ...)
|
|
if ... then
|
|
return path.join(p, joinpath(...))
|
|
else
|
|
return p
|
|
end
|
|
end
|
|
|
|
-- Like joinpath but append a "/" at the end.
|
|
function joindir(...)
|
|
return joinpath(joinpath(...), "")
|
|
end
|
|
|
|
-- Print a debug message and return the arguments.
|
|
function logit(...)
|
|
print("debug:", unpack(arg))
|
|
return unpack(arg)
|
|
end
|
|
|
|
-- format the arguments as CSV
|
|
function sargs(...)
|
|
local r = ""
|
|
for a in iter(arg) do
|
|
r = r .. "," .. show(a)
|
|
end
|
|
return r:sub(2)
|
|
end
|
|
|
|
-- Print a pretty debug message and return the arguments
|
|
function showit(...)
|
|
logit("\n" .. table.concat(collect(map(show,{unpack(arg)})), "\n"))
|
|
return unpack(arg)
|
|
end
|
|
|
|
function cwdrelative(f)
|
|
local rel = partial(joinpath,top)
|
|
if type(f) == "string" then
|
|
return rel(f)
|
|
else
|
|
return collect(map(rel, iter(f)))
|
|
end
|
|
end
|
|
|
|
function toprelative(f)
|
|
local rel = partial(path.getrelative,path.getdirectory(top))
|
|
if type(f) == "string" then
|
|
return rel(f)
|
|
else
|
|
return collect(map(rel,iter(f)))
|
|
end
|
|
end
|
|
|
|
function matchdirs(pattern)
|
|
return toprelative(os.matchdirs(cwdrelative(pattern)))
|
|
end
|
|
|
|
function matchfiles(pattern)
|
|
return toprelative(os.matchfiles(cwdrelative(pattern)))
|
|
end
|
|
|
|
function enumerate_members(o)
|
|
assert(type(o) == "table")
|
|
local function next()
|
|
for k in iterkeys(o) do
|
|
coroutine.yield(k)
|
|
end
|
|
t = getmetatable(o)
|
|
if type(t) == "table" then
|
|
for k in enumerate_members(t) do
|
|
coroutine.yield(k)
|
|
end
|
|
end
|
|
end
|
|
return coroutine.wrap(next)
|
|
end
|
|
|
|
-- wrap a global function to log its arguments.
|
|
function logf(name)
|
|
local silent = _G[name]
|
|
_G[name] = function (...)
|
|
logit(name .. "(" .. sargs(unpack(arg)) .. ")")
|
|
return silent(unpack(arg))
|
|
end
|
|
end
|
|
|
|
function reportf(name, level)
|
|
level = level or 1
|
|
local unsafe = _G[name]
|
|
_G[name] = function (...)
|
|
res = {pcall(unsafe, unpack(arg))}
|
|
if not res[1] then
|
|
error(string.format("Invalid call: %s(%s)", name, sargs(unpack(arg))), level + 1)
|
|
end
|
|
return unpack(res,2)
|
|
end
|
|
end
|
|
|
|
-- print table
|
|
function printTable(tab, indent, circularRef)
|
|
circularRef = circularRef or {}
|
|
indent = indent or ""
|
|
indent = indent .. " "
|
|
|
|
local size = 0
|
|
for k, v in pairs(tab) do
|
|
size = size + 1
|
|
print(string.format("%s- %s = \'%s\' (%s)", indent, tostring(k), tostring(v), type(v)))
|
|
if type(v) == "table" and circularRef[v] == nil then
|
|
circularRef[v] = true
|
|
printTable(v, indent, circularRef)
|
|
end
|
|
end
|
|
|
|
if size == 0 then
|
|
print(string.format("%s- (empty)", indent))
|
|
end
|
|
end |