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

150 lines
3.1 KiB

import wildcard, exists, isdir, mtime from require 'fsutil'
4 years ago
import insert, concat, sort from table
4 years ago
unpack or=table.unpack
GLOB_PATT='^([^%%]*)%%([^%%]*)$'
4 years ago
-- 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
4 years ago
if (type e)=='table'
4 years ago
insert out, v for v in *flatten e
else
insert out, e
out
-- 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
4 years ago
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
4 years ago
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+']
4 years ago
-- string pattern
patsubst= (str, pattern, replacement) ->
return [patsubst s, pattern, replacement for s in *str] if (type str)=='table'
prefix, suffix=pattern\match GLOB_PATT
return str unless prefix
reprefix, resuffix=replacement\match GLOB_PATT
return replacement unless reprefix
4 years ago
if (str\sub 1, #prefix)==prefix and (str\sub -#suffix)==suffix
return reprefix..(str\sub #prefix+1, -#suffix-1)..resuffix
str
splitsp= (str) ->
[elem for elem in str\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
4 years ago
env= (key, def) ->
(os.getenv key) or def
sortedpairs= (table, cmp) ->
keys = [k for k in pairs table]
sort keys, cmp
coroutine.wrap ->
for key in *keys
coroutine.yield key, table[key]
4 years ago
{
-- table functions
:min, :max
:foreach
:first
:insert, :unpack, :concat, :sort
4 years ago
:exclude
:flatten
:sortedpairs
4 years ago
-- file functions
:wildcard
:mtime
:exists, :isdir
4 years ago
-- command functions
:run, :popen
:calccdeps, :findclib
4 years ago
-- string functions
:patsubst, :match, :isglob
4 years ago
:env
:splitsp
4 years ago
}