local map = function(lst,fn)
local new = {} for k,v in pairs(lst) do
local nv, nk = fn(v,k)
new[nk or k] = nv
end
return new
end
local chomp = function(str)
while string.sub(str,#str) == '\n' do
str = string.sub(str,1,#str - 1)
end
return str
end
local exec = function(args, val)
local cmd = table.concat(map(args, function(a)
return string.format('%q', a)
end), ' ')
if val then return os.execute(cmd) else
local fd = io.popen(cmd,'r')
local t = fd:read('*a')
return chomp(t), fd:close()
end
end
local function copy(a)
local new = {}
for k,v in pairs(a) do new[k] = v end
return new
end
local function cat(a,b)
a = copy(a)
local ofs = #a
for k,v in pairs(b) do
if type(k) == 'number' then
a[k+ofs] = v
else a[k] = v end
end
return a
end
local function search(tbl,pred,lst,path)
lst = lst or {} path = path or {}
if type(pred) ~= 'function' then
local val = pred
pred = function(a,k)
if type(a) == 'table' and a ~= val then return end
return a == val
end
end
for k,v in pairs(tbl) do
local res = pred(v,k)
local np = cat(path, {tbl})
if res == true then
table.insert(lst, {
key = k;
value = v;
parent = tbl;
path = np;
})
elseif res == nil then
search(v,pred,lst,np)
end
end
return lst
end
local function dump(v,pfx,cyc,ismeta)
pfx = pfx or ''
cyc = cyc or {}
local np = pfx .. ' '
if type(v) == 'table' then
if cyc[v] then return '<...>' else cyc[v] = true end
end
if type(v) == 'string' then
return string.format('%q', v)
elseif type(v) == 'table' then
local str = ''
for k,v in pairs(v) do
local tkey, tval = dump(k,np,cyc), dump(v,np,cyc)
str = str .. string.format('%s[%s] = %s\n', np, tkey,tval)
end
local meta = ''
if getmetatable(v) then
meta = dump(getmetatable(v),pfx,cyc,true) .. '::'
end
if ismeta then
return string.format('%s<|\n%s%s|>',meta,str,pfx)
else
return meta..'{\n' .. str .. pfx .. '}\n'
end
else
return string.format('%s', v)
end
end
local ping = function(path)
local f = io.open(path)
if f then f:close() return true end
return false
end
local tobool = function(s)
if s == true then return true
elseif s == false then return false end
s = ({
yes = true, ['true'] = true, on = true, ['1'] = true;
no = false, ['false'] = false, off = false, ['0'] = false;
})[string.lower(s)]
if not s then return false end
return true
end
if ping '/dev/urandom' then
local r = io.open('/dev/urandom')
local ent = r:read(8) r:close()
local seed = 1 for i = 1, 8 do
seed = seed * string.byte(string.sub(ent,i,i))
end
math.randomseed(seed)
else math.randomseed(os.time()) end
return {
dump = dump;
exec = exec, ping = ping;
map = map, copy = copy, cat = cat, search = search;
chomp = chomp, tobool = tobool;
find = function(lst,pred)
for k,v in pairs(lst) do
local test = pred(v,k)
if test then return test end
end
return nil
end;
rndstr = function(len)
local s = ''
for i=1,len do
local ofs = math.random(0,10 + 26)
if ofs >= 10 then ofs = 0x60 + (ofs - 10)
else ofs = 0x30 + ofs end
s = s .. string.char(ofs)
end
return s
end;
append = function(a,b)
for _, v in pairs(b) do a[#a+1] = v end
end;
has = function(haystack,pred)
if type(pred) ~= 'function' then
local val = pred
pred = function(a) return a == val end
end
for k,v in pairs(haystack) do
if pred(v,k) then return k,v end
end
end;
keys = function(ary)
local kt = {}
for k,v in pairs(ary) do kt[#kt+1] = k end
return kt
end;
ingest = function(f)
local h = io.open(f, 'r')
if h == nil then return nil end
local txt = h:read('*a') h:close()
return chomp(txt)
end;
parseargs = function(a)
local raw = false
local opts, args = {}, {}
for i,v in ipairs(a) do
if v == '--' then
raw = true
else
if (not raw) and string.sub(v,1,2) == '--' then -- longopt
opts[#opts+1] = string.sub(v,3)
elseif (not raw) and string.sub(v,1,1) == '-' then -- shortopts
for c in string.gmatch(string.sub(v,2), '.') do
opts[#opts+1] = c
end
else args[#args+1]=v end
end
end
return opts, args
end;
}