mirror of https://github.com/natnat-mc/moonbuild
parent
a5b4024eb6
commit
3ed6844a9f
@ -0,0 +1,7 @@ |
||||
tasks: |
||||
build: => |
||||
sh "moon bin/moonbuild.moon compile-lua" |
||||
release: => |
||||
error "no version provided" unless @v |
||||
tasks.build! |
||||
sh "rockbuild -m -t #{@v} upload" |
@ -1,30 +1,14 @@ |
||||
SOURCES_MOON = wildcard '*.moon' |
||||
exclude SOURCES_MOON, 'Build.moon' |
||||
SOURCES_MOON = flatten {'bin/moonbuild.moon', wildcard 'moonbuild/**.moon'} |
||||
OUT_LUA = patsubst SOURCES_MOON, '%.moon', '%.lua' |
||||
BINARY = 'moonbuild' |
||||
MAIN = "#{BINARY}.moon" |
||||
MAIN_LUA = patsubst MAIN, '%.moon', '%.lua' |
||||
OUT_C = patsubst MAIN, '%.moon', '%.lua.c' |
||||
PREFIX = env 'PREFIX', '/usr/local' |
||||
INSTALL_LOC = "#{PREFIX}/bin" |
||||
|
||||
public target 'install', from: BINARY, out: INSTALL_LOC, fn: => |
||||
-install @infile, @outfile |
||||
|
||||
public target 'clean', fn: => |
||||
-rm '-f', OUT_LUA |
||||
-rm '-f', OUT_C |
||||
|
||||
public target 'mrproper', deps: 'clean', fn: => |
||||
-rm '-f', BINARY |
||||
|
||||
public target 'info', fn: => |
||||
#echo "Moonscript sources:", SOURCES_MOON |
||||
#echo "Compiled lua:", OUT_LUA |
||||
#echo "Binary:", BINARY |
||||
|
||||
default target BINARY, out: {BINARY, OUT_C}, from: OUT_LUA, fn: => |
||||
-luastatic MAIN_LUA, OUT_LUA, (findclib 'lua5.3', 'all') |
||||
default target 'compile-lua', from: OUT_LUA |
||||
|
||||
target '%.lua', in: '%.moon', out: '%.lua', fn: => |
||||
-moonc @infile |
||||
|
@ -0,0 +1,428 @@ |
||||
local argparse = require('argparse') |
||||
require('moonscript') |
||||
local loadfile |
||||
loadfile = require('moonscript.base').loadfile |
||||
local truncate_traceback, rewrite_traceback |
||||
do |
||||
local _obj_0 = require('moonscript.errors') |
||||
truncate_traceback, rewrite_traceback = _obj_0.truncate_traceback, _obj_0.rewrite_traceback |
||||
end |
||||
local trim |
||||
trim = require('moonscript.util').trim |
||||
local util = require('moonbuild.util') |
||||
local exists, mtime, run, min, max, first, flatten, match, patsubst, sortedpairs |
||||
exists, mtime, run, min, max, first, flatten, match, patsubst, sortedpairs = util.exists, util.mtime, util.run, util.min, util.max, util.first, util.flatten, util.match, util.patsubst, util.sortedpairs |
||||
local insert, concat |
||||
do |
||||
local _obj_0 = table |
||||
insert, concat = _obj_0.insert, _obj_0.concat |
||||
end |
||||
local parser = argparse('moonbuild') |
||||
parser:argument('targets', "Targets to run"):args('*') |
||||
parser:flag('-a --noskip', "Always run targets") |
||||
parser:flag('-l --list', "List available targets") |
||||
parser:flag('-d --deps', "List targets and their dependancies") |
||||
local args = parser:parse() |
||||
local loadwithscope |
||||
loadwithscope = function(file, scope) |
||||
local fn, err = loadfile(file) |
||||
if not (fn) then |
||||
error(err or "failed to load code") |
||||
end |
||||
local dumped |
||||
dumped, err = string.dump(fn) |
||||
if not (dumped) then |
||||
error(err or "failed to dump function") |
||||
end |
||||
return load(dumped, file, 'b', scope) |
||||
end |
||||
local pcall |
||||
pcall = function(fn, ...) |
||||
local rewrite |
||||
rewrite = function(err) |
||||
local trace = debug.traceback('', 2) |
||||
local trunc = truncate_traceback(trim(trace)) |
||||
return rewrite_traceback(trunc, err) |
||||
end |
||||
return xpcall(fn, rewrite, ...) |
||||
end |
||||
local Command |
||||
do |
||||
local _class_0 |
||||
local _base_0 = { |
||||
__unm = function(self) |
||||
return self:run({ |
||||
error = true, |
||||
print = true |
||||
}) |
||||
end, |
||||
__len = function(self) |
||||
return self:run({ |
||||
error = true |
||||
}) |
||||
end, |
||||
__tostring = function(self) |
||||
return self.cmd |
||||
end, |
||||
run = function(self, params) |
||||
return run(self.cmd, self.args, params) |
||||
end |
||||
} |
||||
_base_0.__index = _base_0 |
||||
_class_0 = setmetatable({ |
||||
__init = function(self, cmd, ...) |
||||
self.cmd = cmd |
||||
self.args = { |
||||
... |
||||
} |
||||
end, |
||||
__base = _base_0, |
||||
__name = "Command" |
||||
}, { |
||||
__index = _base_0, |
||||
__call = function(cls, ...) |
||||
local _self_0 = setmetatable({}, _base_0) |
||||
cls.__init(_self_0, ...) |
||||
return _self_0 |
||||
end |
||||
}) |
||||
_base_0.__class = _class_0 |
||||
local self = _class_0 |
||||
self.run = function(self, ...) |
||||
return -self(...) |
||||
end |
||||
Command = _class_0 |
||||
end |
||||
local BuildObject |
||||
do |
||||
local _class_0 |
||||
local all, skip |
||||
local _base_0 = { |
||||
__tostring = function(self) |
||||
return "Target " .. tostring(self.name) .. " (" .. tostring(concat(self.deps, ', ')) .. ")" |
||||
end, |
||||
build = function(self, name, upper) |
||||
if upper == nil then |
||||
upper = { } |
||||
end |
||||
if skip[name] then |
||||
return |
||||
end |
||||
if upper[self] then |
||||
error("Cycle detected on " .. tostring(self.name)) |
||||
end |
||||
upper = setmetatable({ |
||||
[self] = true |
||||
}, { |
||||
__index = upper |
||||
}) |
||||
if self.name ~= name then |
||||
local _list_0 = self.deps |
||||
for _index_0 = 1, #_list_0 do |
||||
local dep = _list_0[_index_0] |
||||
self.__class:build((patsubst(name, self.name, dep)), upper) |
||||
end |
||||
else |
||||
local _list_0 = self.deps |
||||
for _index_0 = 1, #_list_0 do |
||||
local dep = _list_0[_index_0] |
||||
self.__class:build(dep, upper) |
||||
end |
||||
end |
||||
if not (self:shouldbuild(name)) then |
||||
return |
||||
end |
||||
local ins = self.ins |
||||
local outs = self.outs |
||||
if self.name ~= name then |
||||
do |
||||
local _accum_0 = { } |
||||
local _len_0 = 1 |
||||
local _list_0 = self.ins |
||||
for _index_0 = 1, #_list_0 do |
||||
local elem = _list_0[_index_0] |
||||
_accum_0[_len_0] = patsubst(name, self.name, elem) |
||||
_len_0 = _len_0 + 1 |
||||
end |
||||
ins = _accum_0 |
||||
end |
||||
do |
||||
local _accum_0 = { } |
||||
local _len_0 = 1 |
||||
local _list_0 = self.outs |
||||
for _index_0 = 1, #_list_0 do |
||||
local elem = _list_0[_index_0] |
||||
_accum_0[_len_0] = patsubst(name, self.name, elem) |
||||
_len_0 = _len_0 + 1 |
||||
end |
||||
outs = _accum_0 |
||||
end |
||||
print("Building " .. tostring(self.name) .. " as " .. tostring(name)) |
||||
else |
||||
print("Building " .. tostring(name)) |
||||
end |
||||
local ok, err = pcall(function() |
||||
return self.fn({ |
||||
ins = ins, |
||||
outs = outs, |
||||
infile = ins[1], |
||||
outfile = outs[1], |
||||
name = name |
||||
}) |
||||
end) |
||||
if not (ok) then |
||||
error("Can't build " .. tostring(self.name) .. ": lua error\n" .. tostring(err)) |
||||
end |
||||
for _index_0 = 1, #outs do |
||||
local f = outs[_index_0] |
||||
if not (exists(f)) then |
||||
error("Can't build " .. tostring(self.name) .. ": output file " .. tostring(f) .. " not created") |
||||
end |
||||
end |
||||
skip[name] = true |
||||
end, |
||||
shouldbuild = function(self, name) |
||||
if args.noskip then |
||||
return true |
||||
end |
||||
if #self.ins == 0 or #self.outs == 0 then |
||||
return true |
||||
end |
||||
local ins |
||||
if self.name ~= name then |
||||
do |
||||
local _accum_0 = { } |
||||
local _len_0 = 1 |
||||
local _list_0 = self.ins |
||||
for _index_0 = 1, #_list_0 do |
||||
local elem = _list_0[_index_0] |
||||
_accum_0[_len_0] = patsubst(name, self.name, elem) |
||||
_len_0 = _len_0 + 1 |
||||
end |
||||
ins = _accum_0 |
||||
end |
||||
else |
||||
ins = self.ins |
||||
end |
||||
local itimes |
||||
do |
||||
local _accum_0 = { } |
||||
local _len_0 = 1 |
||||
for _index_0 = 1, #ins do |
||||
local f = ins[_index_0] |
||||
_accum_0[_len_0] = mtime(f) |
||||
_len_0 = _len_0 + 1 |
||||
end |
||||
itimes = _accum_0 |
||||
end |
||||
for i = 1, #self.ins do |
||||
if not (itimes[i]) then |
||||
error("Can't build " .. tostring(self.name) .. ": missing inputs") |
||||
end |
||||
end |
||||
local outs |
||||
if self.name ~= name then |
||||
do |
||||
local _accum_0 = { } |
||||
local _len_0 = 1 |
||||
local _list_0 = self.outs |
||||
for _index_0 = 1, #_list_0 do |
||||
local elem = _list_0[_index_0] |
||||
_accum_0[_len_0] = patsubst(name, self.name, elem) |
||||
_len_0 = _len_0 + 1 |
||||
end |
||||
outs = _accum_0 |
||||
end |
||||
else |
||||
outs = self.outs |
||||
end |
||||
local otimes |
||||
do |
||||
local _accum_0 = { } |
||||
local _len_0 = 1 |
||||
for _index_0 = 1, #outs do |
||||
local f = outs[_index_0] |
||||
_accum_0[_len_0] = mtime(f) |
||||
_len_0 = _len_0 + 1 |
||||
end |
||||
otimes = _accum_0 |
||||
end |
||||
for i = 1, #self.outs do |
||||
if not otimes[i] then |
||||
return true |
||||
end |
||||
end |
||||
return (max(itimes)) > (min(otimes)) |
||||
end |
||||
} |
||||
_base_0.__index = _base_0 |
||||
_class_0 = setmetatable({ |
||||
__init = function(self, name, outs, ins, deps, fn) |
||||
if outs == nil then |
||||
outs = { } |
||||
end |
||||
if ins == nil then |
||||
ins = { } |
||||
end |
||||
if deps == nil then |
||||
deps = { } |
||||
end |
||||
if fn == nil then |
||||
fn = function(self) end |
||||
end |
||||
self.name, self.outs, self.ins, self.deps, self.fn = name, outs, ins, deps, fn |
||||
self.skip = false |
||||
if all[self.name] then |
||||
error("Duplicate build name " .. tostring(self.name)) |
||||
end |
||||
all[self.name] = self |
||||
end, |
||||
__base = _base_0, |
||||
__name = "BuildObject" |
||||
}, { |
||||
__index = _base_0, |
||||
__call = function(cls, ...) |
||||
local _self_0 = setmetatable({}, _base_0) |
||||
cls.__init(_self_0, ...) |
||||
return _self_0 |
||||
end |
||||
}) |
||||
_base_0.__class = _class_0 |
||||
local self = _class_0 |
||||
all = { } |
||||
skip = { } |
||||
self.find = function(self, name) |
||||
local target = all[name] |
||||
if target then |
||||
return target |
||||
end |
||||
for glob, tgt in pairs(all) do |
||||
if match(name, glob) then |
||||
return tgt |
||||
end |
||||
end |
||||
return nil |
||||
end |
||||
self.list = function(self) |
||||
local _tbl_0 = { } |
||||
for name, target in pairs(all) do |
||||
do |
||||
local _tbl_1 = { } |
||||
local _list_0 = target.deps |
||||
for _index_0 = 1, #_list_0 do |
||||
local dep = _list_0[_index_0] |
||||
_tbl_1[dep] = self:find(dep) |
||||
end |
||||
_tbl_0[target] = _tbl_1 |
||||
end |
||||
end |
||||
return _tbl_0 |
||||
end |
||||
self.build = function(self, name, upper) |
||||
local target = (self:find(name)) or error("No such target: " .. tostring(name)) |
||||
return target:build(name, upper) |
||||
end |
||||
BuildObject = _class_0 |
||||
end |
||||
if setfenv then |
||||
error("Need Lua >=5.2") |
||||
end |
||||
local targets = { } |
||||
local defaulttarget = 'all' |
||||
local buildscope = { |
||||
default = function(target) |
||||
defaulttarget = target.name |
||||
return target |
||||
end, |
||||
public = function(target) |
||||
insert(targets, target.name) |
||||
return target |
||||
end, |
||||
target = function(name, params) |
||||
local tout = flatten(params.out) |
||||
local tin = flatten(params["in"]) |
||||
local tdeps = flatten(params.deps) |
||||
local _list_0 = flatten(params.from) |
||||
for _index_0 = 1, #_list_0 do |
||||
local f = _list_0[_index_0] |
||||
insert(tin, f) |
||||
insert(tdeps, f) |
||||
end |
||||
return BuildObject(name, tout, tin, tdeps, params.fn) |
||||
end |
||||
} |
||||
for k, fn in pairs(util) do |
||||
buildscope[k] = fn |
||||
end |
||||
setmetatable(buildscope, { |
||||
__index = function(self, k) |
||||
local global = rawget(_G, k) |
||||
if global then |
||||
return global |
||||
end |
||||
return function(...) |
||||
return Command(k, ...) |
||||
end |
||||
end |
||||
}) |
||||
local file = first({ |
||||
'Build.moon', |
||||
'Buildfile.moon', |
||||
'Build', |
||||
'Buildfile' |
||||
}, exists) |
||||
if not (file) then |
||||
error("No Build.moon or Buildfile found") |
||||
end |
||||
local buildfn = loadwithscope(file, buildscope) |
||||
if not (buildfn) then |
||||
error("Failed to load build function") |
||||
end |
||||
local ok, err = pcall(buildfn) |
||||
if not (ok) then |
||||
if err then |
||||
io.stderr:write(err, '\n') |
||||
else |
||||
io.stderr:write("Unknown error\n") |
||||
end |
||||
os.exit(1) |
||||
end |
||||
if args.list then |
||||
io.write("Available targets:\n") |
||||
io.write("\t" .. tostring(concat(targets, ', ')) .. "\n") |
||||
os.exit(0) |
||||
end |
||||
if args.deps then |
||||
io.write("Targets:\n") |
||||
for target, deps in sortedpairs(BuildObject:list(), function(a, b) |
||||
return a.name < b.name |
||||
end) do |
||||
io.write("\t" .. tostring(target.name) .. " ") |
||||
if #target.ins == 0 then |
||||
if #target.outs == 0 then |
||||
io.write("[no in/out]") |
||||
else |
||||
io.write("[spontaneous generation]") |
||||
end |
||||
else |
||||
if #target.outs == 0 then |
||||
io.write("[consumer]") |
||||
else |
||||
io.write("(" .. tostring(concat(target.ins, ', ')) .. " -> " .. tostring(concat(target.outs, ', ')) .. ")") |
||||
end |
||||
end |
||||
io.write("\n") |
||||
for name, dep in sortedpairs(deps) do |
||||
io.write("\t\t" .. tostring(name) .. " (" .. tostring(dep.name) .. ")\n") |
||||
end |
||||
end |
||||
os.exit(0) |
||||
end |
||||
if #args.targets == 0 then |
||||
BuildObject:build(defaulttarget) |
||||
end |
||||
local _list_0 = args.targets |
||||
for _index_0 = 1, #_list_0 do |
||||
local target = _list_0[_index_0] |
||||
BuildObject:build(target) |
||||
end |
@ -1,88 +0,0 @@ |
||||
import dir, attributes from require 'lfs' |
||||
|
||||
import gmatch, match, gsub, sub from string |
||||
import insert, concat from table |
||||
|
||||
ls = (d) -> |
||||
[f for f in dir d when f!='.' and f!='..'] |
||||
|
||||
lswithpath = (d) -> |
||||
if d=='' |
||||
return ls '.' |
||||
[d..'/'..f for f in dir d when f!='.' and f!='..'] |
||||
|
||||
exists = (f) -> |
||||
(attributes f) != nil |
||||
|
||||
isdir = (f) -> |
||||
a = attributes f |
||||
a and a.mode == 'directory' or false |
||||
|
||||
mtime = (f) -> |
||||
a = attributes f |
||||
a and a.modification |
||||
|
||||
matchglob = (str, glob) -> |
||||
patt = '^'..(gsub (gsub glob, '%*%*', '.*'), '%*', '[^/]*')..'$' |
||||
rst = if (type str)=='table' |
||||
results, i = {}, 1 |
||||
for s in *str |
||||
rst = (match s, patt) and s |
||||
results[i], i = rst, i+1 if rst |
||||
results |
||||
else |
||||
(match str, patt) and str |
||||
rst |
||||
|
||||
wildcard = (glob) -> |
||||
parts = [part for part in gmatch glob, '[^/]+'] |
||||
absolute = (sub glob, 1, 1)=='/' |
||||
|
||||
for i, part in ipairs parts |
||||
prevpath = (absolute and '/' or '') .. concat parts, '/', 1, i-1 |
||||
currpath = prevpath .. '/' .. part |
||||
|
||||
if match part, '%*%*.*%*%*' |
||||
error "Two '**' in the same path component in a wildcard" |
||||
|
||||
if match part, '%*%*' |
||||
prefix = match currpath, '^(.*)%*%*' |
||||
suffix = (match part, '%*%*(.*)$') .. (i==#parts and '' or ('/'..concat parts, '/', i+1, #parts)) |
||||
files = lswithpath prevpath |
||||
|
||||
results = {} |
||||
for file in *files |
||||
if matchglob file, currpath |
||||
if i==#parts |
||||
insert results, file |
||||
elseif isdir file |
||||
for result in *wildcard file .. '/' .. concat parts, '/', i+1, #parts |
||||
insert results, result |
||||
if (matchglob file, prefix..'**') and isdir file |
||||
for result in *wildcard file .. '/**' .. suffix |
||||
insert results, result |
||||
return results |
||||
|
||||
if match part, '%*' |
||||
files = lswithpath prevpath |
||||
|
||||
if i==#parts |
||||
return matchglob files, glob |
||||
|
||||
results = {} |
||||
for file in *files |
||||
if (matchglob file, currpath) and isdir file |
||||
for result in *wildcard file .. '/' .. concat parts, '/', i+1, #parts |
||||
insert results, result |
||||
return results |
||||
|
||||
if exists glob |
||||
return {glob} |
||||
else |
||||
return {} |
||||
|
||||
{ |
||||
:wildcard |
||||
:exists, :isdir |
||||
:mtime |
||||
} |
@ -0,0 +1,26 @@ |
||||
package: moonbuild |
||||
source: |
||||
url: git://github.com/natnat-mc/moonbuild |
||||
description: |
||||
summary: Small build system in between make and a build.sh |
||||
detailed: > |
||||
moonbuild is a small build system that simplifies your |
||||
build definitions by allowing you to use declarative as |
||||
well as imperative rules. |
||||
It represents the build as a DAG with explicit ordering, |
||||
and doesn't give you any default confusing rules (unlike |
||||
make) |
||||
homepage: https://github.com/natnat-mc/moonbuild |
||||
dependencies: |
||||
- lua >= 5.3 |
||||
- luafilesystem >= 1.7.0 |
||||
build: |
||||
type: builtin |
||||
modules: |
||||
moonbuild.util: moonbuild/util.lua |
||||
moonbuild.fsutil: moonbuild/fsutil.lua |
||||
moonbuild.stringutil: moonbuild/stringutil.lua |
||||
moonbuild.tableutil: moonbuild/tableutil.lua |
||||
install: |
||||
bin: |
||||
moonbuild: bin/moonbuild.lua |
@ -0,0 +1,29 @@ |
||||
build = { |
||||
install = { |
||||
bin = { |
||||
moonbuild = "bin/moonbuild.lua" |
||||
} |
||||
}, |
||||
modules = { |
||||
["moonbuild.fsutil"] = "moonbuild/fsutil.lua", |
||||
["moonbuild.stringutil"] = "moonbuild/stringutil.lua", |
||||
["moonbuild.tableutil"] = "moonbuild/tableutil.lua", |
||||
["moonbuild.util"] = "moonbuild/util.lua" |
||||
}, |
||||
type = "builtin" |
||||
} |
||||
dependencies = { |
||||
"lua >= 5.3", |
||||
"luafilesystem >= 1.7.0" |
||||
} |
||||
description = { |
||||
detailed = "moonbuild is a small build system that simplifies your build definitions by allowing you to use declarative as well as imperative rules. It represents the build as a DAG with explicit ordering, and doesn't give you any default confusing rules (unlike make)\n", |
||||
summary = "Small build system in between make and a build.sh" |
||||
} |
||||
package = "moonbuild" |
||||
rockspec_format = "3.0" |
||||
source = { |
||||
tag = "v1.0.0", |
||||
url = "git://github.com/natnat-mc/moonbuild" |
||||
} |
||||
version = "1.0.0-1" |
@ -0,0 +1,29 @@ |
||||
build = { |
||||
install = { |
||||
bin = { |
||||
moonbuild = "bin/moonbuild.lua" |
||||
} |
||||
}, |
||||
modules = { |
||||
["moonbuild.fsutil"] = "moonbuild/fsutil.lua", |
||||
["moonbuild.stringutil"] = "moonbuild/stringutil.lua", |
||||
["moonbuild.tableutil"] = "moonbuild/tableutil.lua", |
||||
["moonbuild.util"] = "moonbuild/util.lua" |
||||
}, |
||||
type = "builtin" |
||||
} |
||||
dependencies = { |
||||
"lua >= 5.3", |
||||
"luafilesystem >= 1.7.0" |
||||
} |
||||
description = { |
||||
detailed = "moonbuild is a small build system that simplifies your build definitions by allowing you to use declarative as well as imperative rules. It represents the build as a DAG with explicit ordering, and doesn't give you any default confusing rules (unlike make)\n", |
||||
summary = "Small build system in between make and a build.sh" |
||||
} |
||||
package = "moonbuild" |
||||
rockspec_format = "3.0" |
||||
source = { |
||||
tag = "v1.0.0", |
||||
url = "git://github.com/natnat-mc/moonbuild" |
||||
} |
||||
version = "1.0.0-2" |
@ -1,25 +0,0 @@ |
||||
import match, gmatch, sub from string |
||||
import upper, lower from string |
||||
|
||||
GLOB_PATT='^([^%%]*)%%([^%%]*)$' |
||||
|
||||
patsubst = (str, pattern, replacement) -> |
||||
return [patsubst s, pattern, replacement for s in *str] if (type str)=='table' |
||||
prefix, suffix = match pattern, GLOB_PATT |
||||
return str unless prefix |
||||
reprefix, resuffix = match replacement, GLOB_PATT |
||||
return replacement unless reprefix |
||||
|
||||
if (sub str, 1, #prefix)==prefix and (sub str, -#suffix)==suffix |
||||
return reprefix..(sub str, #prefix+1, -#suffix-1)..resuffix |
||||
str |
||||
|
||||
splitsp = (str) -> |
||||
[elem for elem in gmatch str, '%S+'] |
||||
|
||||
{ |
||||
:patsubst |
||||
:splitsp |
||||
|
||||
:upper, :lower |
||||
} |
@ -1,66 +0,0 @@ |
||||
import insert, remove, concat, sort from table |
||||
unpack or= table.unpack |
||||
|
||||
sortedpairs = (table, cmp) -> |
||||
keys = [k for k in pairs table] |
||||
sort keys, cmp |
||||
coroutine.wrap -> |
||||
for key in *keys |
||||
coroutine.yield key, table[key] |
||||
|
||||
min = (table, cmp=(a, b) -> a<b) -> |
||||
val = table[1] |
||||
for i=2, #table |
||||
elem = table[i] |
||||
if cmp val, elem |
||||
val = elem |
||||
val |
||||
|
||||
max = (table, cmp=(a, b) -> a<b) -> |
||||
val = table[1] |
||||
for i=2, #table |
||||
elem = table[i] |
||||
if not cmp val, elem |
||||
val = elem |
||||
val |
||||
|
||||
foreach = (tab, fn) -> |
||||
[fn e for e in *tab] |
||||
|
||||
first = (tab, fn) -> |
||||
for e in *tab |
||||
return e if fn e |
||||
|
||||
exclude = (tab, ...) -> |
||||
i=1 |
||||
while i<=#tab |
||||
removed=false |
||||
for j=1, select '#', ... |
||||
if tab[i]==select j, ... |
||||
remove tab, i |
||||
removed = true |
||||
break |
||||
i += 1 unless removed |
||||
tab |
||||
|
||||
flatten = (tab) -> |
||||
return {tab} if (type tab)!='table' |
||||
out = {} |
||||
for e in *tab |
||||
if (type e)=='table' |
||||
insert out, v for v in *flatten e |
||||
else |
||||
insert out, e |
||||
out |
||||
|
||||
{ |
||||
:min, :max |
||||
:foreach |
||||
:first |
||||
:exclude |
||||
:flatten |
||||
:sortedpairs |
||||
|
||||
:insert, :remove, :concat, :sort |
||||
:unpack |
||||
} |
@ -1,95 +0,0 @@ |
||||
import wildcard, exists, isdir, mtime from require 'fsutil' |
||||
import foreach, first, flatten, exclude, sortedpairs, min, max from require 'tableutil' |
||||
import patsubst, splitsp from require 'stringutil' |
||||
|
||||
import insert, concat, sort, pairs from require 'tableutil' |
||||
import upper, lower from require 'stringutil' |
||||
|
||||
GLOB_PATT='^([^%%]*)%%([^%%]*)$' |
||||
|
||||
-- command functions |
||||
escapecmdpart= (p) -> |
||||
if (type p)=='table' |
||||
return p.raw if p.raw |
||||
return concat [escapecmdpart part for part in *p], ' ' |
||||
return p if p\match '^[a-zA-Z0-9_./-]+$' |
||||
'"'..p\gsub('\\', '\\\\')\gsub('"', '\\"')..'"' |
||||
escapecmd= (c, args={}) -> |
||||
c=escapecmdpart c |
||||
for a in *flatten args |
||||
c..=' '..escapecmdpart a if a |
||||
c |
||||
run= (c, args, params={}) -> |
||||
escaped=escapecmd c, args |
||||
print escaped if params.print |
||||
ret, _, code=os.execute escaped |
||||
ret, code=ret==0, ret if (type ret)=='number' |
||||
error "#{c} failed with code #{code}" if params.error and not ret |
||||
ret, code |
||||
popen= (c, args, mode='r', params={}) -> |
||||
escaped=escapecmd c, args |
||||
print escaped if params.print |
||||
io.popen escaped, mode |
||||
|
||||
calccdeps= (infile, includesys=false) -> |
||||
data=(popen 'cc', {includesys and '-M' or '-MM', infile})\read '*a' |
||||
rawdeps=data\gsub('\\\n', '')\match ':(.+)' |
||||
[dep for dep in rawdeps\gmatch '%S+' when dep!=infile] |
||||
|
||||
findclib= (name, mode='all') -> |
||||
args={name} |
||||
insert args, '--cflags' if mode=='all' or mode=='cc' |
||||
insert args, '--libs' if mode=='all' or mode=='ld' |
||||
[arg for arg in (popen 'pkg-config', args)\read('*a')\gmatch '%S+'] |
||||
|
||||
-- glob match |
||||
match= (str, glob) -> |
||||
prefix, suffix=glob\match GLOB_PATT |
||||
return str==glob unless prefix |
||||
return str\sub #prefix+1, -#suffix-1 if (str\sub 1, #prefix)==prefix and (str\sub -#suffix)==suffix |
||||
false |
||||
|
||||
-- is a valid glob |
||||
isglob= (glob) -> |
||||
return if glob\match GLOB_PATT |
||||
true |
||||
else |
||||
false |
||||
|
||||
-- getenv |
||||
env= (key, def) -> |
||||
(os.getenv key) or def |
||||
|
||||
{ |
||||
-- table function |
||||
:min, :max |
||||
:foreach |
||||
:first |
||||
:exclude |
||||
:flatten |
||||
:sortedpairs |
||||
|
||||
:insert, :remove, :concat, :sort |
||||
:unpack |
||||
|
||||
-- file functions |
||||
:wildcard |
||||
:mtime |
||||
:exists, :isdir |
||||
|
||||
-- command functions |
||||
:run, :popen |
||||
:calccdeps, :findclib |
||||
|
||||
-- string functions |
||||
:patsubst |
||||
:splitsp |
||||
|
||||
:upper, :lower |
||||
|
||||
-- glob functions |
||||
:match, :isglob |
||||
|
||||
-- env functions |
||||
:env |
||||
} |
Loading…
Reference in new issue