A compromise between the speed of make and the ease of use of a build script
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
moonbuild/util.moon

144 lines
3.0 KiB

5 years ago
import attributes, dir from require 'lfs'
import insert, concat from table
unpack or=table.unpack
-- min and max of table
max= (t) ->
m=t[1]
for i=2, #t
v=t[i]
m=v if v>m
m
min= (t) ->
m=t[1]
for i=2, #t
v=t[i]
m=v if v<m
m
-- simpler constructs
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, ...
table.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' and e[1]
insert out, v for v in *flatten e
else
insert out, e
out
-- file functions
mtime= (f) ->
a=attributes f
a and a.modification
exists= (f) ->
(attributes f)!=nil
-- 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
c..=' '..escapecmdpart a for a in *args
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
-- file matcher
wildcard= (pattern) ->
prefix, suffix=pattern\match '^(.*)%*%*(.*)$'
if prefix
fd=popen 'find', {(raw: '*'), '-name', "*#{suffix}"}
found={}
for line in fd\lines!
insert found, line if (line\sub 1, #prefix)==prefix
fd\close!
return found
5 years ago
directory, prefix, suffix=pattern\match '^(.*)/(.*)%*(.*)$'
5 years ago
if directory
found={}
for file in dir directory
if (file\sub 1, #prefix)==prefix and (file\sub -#suffix)==suffix
insert found, "#{directory}/#{file}"
return found
prefix, suffix=pattern\match '^(.*)%*(.*)$'
if prefix
found={}
for file in dir '.'
if (file\sub 1, #prefix)==prefix and (file\sub -#suffix)==suffix
insert found, file
return found
error "Invalid wildcard pattern: #{pattern}"
-- string pattern
patsubst= (str, pattern, replacement) ->
return [patsubst s, pattern, replacement for s in *str] if (type str)=='table'
prefix, suffix=pattern\match '^(.*)%%(.*)$'
error "Invalid pattern #{pattern}" unless prefix
reprefix, resuffix=replacement\match '^(.*)%%(.*)$'
error "Invalid replacement pattern #{pattern}" unless reprefix
if (str\sub 1, #prefix)==prefix and (str\sub -#suffix)==suffix
return reprefix..(str\sub #prefix+1, -#suffix-1)..resuffix
str
env= (key, def) ->
(os.getenv key) or def
{
-- table functions
:min, :max
:foreach
:first
:insert, :unpack, :concat
:exclude
:flatten
-- file functions
:wildcard
:mtime, :exists
-- command functions
:run, :popen
-- string functions
:patsubst
:env
}