|
|
|
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
|
|
|
|
|
|
|
|
directory, prefix, suffix=pattern\match '^(.*)/(.*)%*(.*)$'
|
|
|
|
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
|
|
|
|
}
|