summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2012-02-17 08:15:59 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2012-02-17 08:15:59 +0000
commit50f896f59089364269b694a0210fb7e045dbc9e2 (patch)
treedf46393e2fb7b5df01fecc1d9e694301fe6d3f77
parenta50741c2139274ec94034a18da6d4d0b051c6ff8 (diff)
downloadaports-50f896f59089364269b694a0210fb7e045dbc9e2.tar.bz2
aports-50f896f59089364269b694a0210fb7e045dbc9e2.tar.xz
testing/lua-microlight: new aport
a really compact set of general Lua functions http://stevedonovan.github.com/microlight/
-rw-r--r--testing/lua-microlight/APKBUILD36
-rw-r--r--testing/lua-microlight/ml.lua543
2 files changed, 579 insertions, 0 deletions
diff --git a/testing/lua-microlight/APKBUILD b/testing/lua-microlight/APKBUILD
new file mode 100644
index 000000000..632a65333
--- /dev/null
+++ b/testing/lua-microlight/APKBUILD
@@ -0,0 +1,36 @@
+# Contributor: Natanael Copa <ncopa@alpinelinux.org>
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=lua-microlight
+pkgver=0_git20120215
+pkgrel=0
+pkgdesc="a really compact set of general Lua functions"
+url="http://stevedonovan.github.com/microlight/"
+arch="noarch"
+license="MIT"
+depends="lua"
+makedepends="wget"
+install=""
+subpackages=""
+source="https://raw.github.com/gist/1834789/2bbb01662de1d83af93d2bd2990fee229b473d54/ml.lua"
+
+_builddir=
+prepare() {
+ local i
+ cd "$_builddir"
+ for i in $source; do
+ case $i in
+ *.patch) msg $i; patch -p1 -i "$srcdir"/$i || return 1;;
+ esac
+ done
+}
+
+build() {
+ cd "$_builddir"
+}
+
+package() {
+ cd "$_builddir"
+ install -Dm644 "$srcdir"/ml.lua "$pkgdir"/usr/share/lua/5.1/ml.lua
+}
+
+md5sums="0a1e55c9babf6c093aa24f391c07cfd7 ml.lua"
diff --git a/testing/lua-microlight/ml.lua b/testing/lua-microlight/ml.lua
new file mode 100644
index 000000000..2bbb01662
--- /dev/null
+++ b/testing/lua-microlight/ml.lua
@@ -0,0 +1,543 @@
+-----------------
+-- Microlight - a very compact Lua utilities module
+--
+-- Steve Donovan, 2012; License MIT
+-- @module ml
+
+local ml = {}
+
+--- String utilties.
+-- @section string
+
+--- split a string into a list of strings separated by a delimiter.
+-- @param s The input string
+-- @param re A Lua string pattern; defaults to '%s+'
+-- @param n optional maximum number of splits
+-- @return a list
+function ml.split(s,re,n)
+ local find,sub,append = string.find, string.sub, table.insert
+ local i1,ls = 1,{}
+ if not re then re = '%s+' end
+ if re == '' then return {s} end
+ while true do
+ local i2,i3 = find(s,re,i1)
+ if not i2 then
+ local last = sub(s,i1)
+ if last ~= '' then append(ls,last) end
+ if #ls == 1 and ls[1] == '' then
+ return {}
+ else
+ return ls
+ end
+ end
+ append(ls,sub(s,i1,i2-1))
+ if n and #ls == n then
+ ls[#ls] = sub(s,i1)
+ return ls
+ end
+ i1 = i3+1
+ end
+end
+
+--- escape any 'magic' characters in a string
+-- @param s The input string
+-- @return an escaped string
+function ml.escape(s)
+ return (s:gsub('[%-%.%+%[%]%(%)%$%^%%%?%*]','%%%1'))
+end
+
+--- expand a string containing any ${var} or $var.
+-- @param s the string
+-- @param subst either a table or a function (as in `string.gsub`)
+-- @return expanded string
+function ml.expand (s,subst)
+ local res = s:gsub('%${([%w_]+)}',subst)
+ return (res:gsub('%$([%w_]+)',subst))
+end
+
+--- return the contents of a file as a string
+-- @param filename The file path
+-- @param is_bin open in binary mode, default false
+-- @return file contents
+function ml.readfile(filename,is_bin)
+ local mode = is_bin and 'b' or ''
+ local f,err = io.open(filename,'r'..mode)
+ if not f then return nil,err end
+ local res,err = f:read('*a')
+ f:close()
+ if not res then return nil,err end
+ return res
+end
+
+--- File and Path functions
+-- @section file
+
+--~ exists(filename)
+--- Does a file exist?
+-- @param filename a file path
+-- @return the file path, otherwise nil
+-- @usage exists 'readme' or exists 'readme.txt' or exists 'readme.md'
+function ml.exists (filename)
+ local f = io.open(filename)
+ if not f then
+ return nil
+ else
+ f:close()
+ return filename
+ end
+end
+
+local sep, other_sep = package.config:sub(1,1),'/'
+
+
+--- split a file path.
+-- if there's no directory part, the first value will be the empty string
+-- @param P A file path
+-- @return the directory part
+-- @return the file part
+function ml.splitpath(P)
+ local i = #P
+ local ch = P:sub(i,i)
+ while i > 0 and ch ~= sep and ch ~= other_sep do
+ i = i - 1
+ ch = P:sub(i,i)
+ end
+ if i == 0 then
+ return '',P
+ else
+ return P:sub(1,i-1), P:sub(i+1)
+ end
+end
+
+--- given a path, return the root part and the extension part.
+-- if there's no extension part, the second value will be empty
+-- @param P A file path
+-- @return the name part
+-- @return the extension
+function ml.splitext(P)
+ local i = #P
+ local ch = P:sub(i,i)
+ while i > 0 and ch ~= '.' do
+ if ch == sep or ch == other_sep then
+ return P,''
+ end
+ i = i - 1
+ ch = P:sub(i,i)
+ end
+ if i == 0 then
+ return P,''
+ else
+ return P:sub(1,i-1),P:sub(i)
+ end
+end
+
+--- Extended table functions.
+-- 'list' here is shorthand for 'list-like table'; these functions
+-- only operate over the numeric `1..#t` range of a table and are
+-- particularly efficient for this purpose.
+-- @section table
+
+local function quote (v)
+ if type(v) == 'string' then
+ return ('%q'):format(v)
+ else
+ return tostring(v)
+ end
+end
+
+local tbuff
+function tbuff (t,buff,k)
+ buff[k] = "{"
+ k = k + 1
+ for key,value in pairs(t) do
+ key = quote(key)
+ if type(value) ~= 'table' then
+ value = quote(value)
+ buff[k] = ('[%s]=%s'):format(key,value)
+ k = k + 1
+ if buff.limit and k > buff.limit then
+ buff[k] = "..."
+ error("buffer overrun")
+ end
+ else
+ if not buff.tables then buff.tables = {} end
+ if not buff.tables[value] then
+ k = tbuff(value,buff,k)
+ buff.tables[value] = true
+ else
+ buff[k] = "<cycle>"
+ k = k + 1
+ end
+ end
+ buff[k] = ","
+ k = k + 1
+ end
+ if buff[k-1] == "," then k = k - 1 end
+ buff[k] = "}"
+ k = k + 1
+ return k
+end
+
+--- return a string representation of a Lua table.
+-- Cycles are detected, and a limit on number of items can be imposed.
+-- @param t the table
+-- @param limit the limit on items, default 1000
+-- @return a string
+function ml.tstring (t,limit)
+ local buff = {limit = limit or 1000}
+ pcall(tbuff,t,buff,1)
+ return table.concat(buff)
+end
+
+--- dump a Lua table to a file object.
+-- @param t the table
+-- @param f the file object (anything supporting f.write)
+function ml.tdump(t,...)
+ local f = select('#',...) > 0 and select(1,...) or io.stdout
+ f:write(ml.tstring(t),'\n')
+end
+
+--- map a function over a list.
+-- The output must always be the same length as the input, so
+-- any `nil` values are mapped to `false`.
+-- @param f a function of one or more arguments
+-- @param t the table
+-- @param ... any extra arguments to the function
+-- @return a list with elements `f(t[i])`
+function ml.imap(f,t,...)
+ f = ml.function_arg(f)
+ local res = {}
+ for i = 1,#t do
+ local val = f(t[i],...)
+ if val == nil then val = false end
+ res[i] = val
+ end
+ return res
+end
+
+--- filter a list using a predicate.
+-- @param t a table
+-- @param pred the predicate function
+-- @param ... any extra arguments to the predicate
+-- @return a list such that `pred(t[i])` is true
+function ml.ifilter(t,pred,...)
+ local res,k = {},1
+ pred = ml.function_arg(pred)
+ for i = 1,#t do
+ if pred(t[i],...) then
+ res[k] = t[i]
+ k = k + 1
+ end
+ end
+ return res
+end
+
+--- find an item in a list using a predicate.
+-- @param t the list
+-- @param pred a function of at least one argument
+-- @param ... any extra arguments
+-- @return the item value
+function ml.ifind(t,pred,...)
+ pred = ml.function_arg(pred)
+ for i = 1,#t do
+ if pred(t[i],...) then
+ return t[i]
+ end
+ end
+end
+
+--- return the index of an item in a list.
+-- @param t the list
+-- @param value item value
+-- @return index, otherwise `nil`
+function ml.index (t,value)
+ for i = 1,#t do
+ if t[i] == value then return i end
+ end
+end
+
+--- return a slice of a list.
+-- Like string.sub, the end index may be negative.
+-- @param t the list
+-- @param i1 the start index
+-- @param i2 the end index, default #t
+function ml.sub(t,i1,i2)
+ if not i2 or i2 > #t then
+ i2 = #t
+ elseif i2 < 0 then
+ i2 = #t + i2 + 1
+ end
+ local res,k = {},1
+ for i = i1,i2 do
+ res[k] = t[i]
+ k = k + 1
+ end
+ return res
+end
+
+--- map a function over a Lua table.
+-- @param f a function of one or more arguments
+-- @param t the table
+-- @param ... any optional arguments to the function
+function ml.tmap(f,t,...)
+ f = ml.function_arg(f)
+ local res = {}
+ for k,v in pairs(t) do
+ res[k] = f(v,...)
+ end
+ return res
+end
+
+--- filter a table using a predicate.
+-- @param t a table
+-- @param pred the predicate function
+-- @param ... any extra arguments to the predicate
+-- @usage tfilter({a=1,b='boo'},tonumber) == {a=1}
+function ml.tfilter (t,pred,...)
+ local res = {}
+ pred = ml.function_arg(pred)
+ for k,v in pairs(t) do
+ if pred(v,...) then
+ res[k] = v
+ end
+ end
+ return res
+end
+
+--- add the key/value pairs of `other` to `t`.
+-- For sets, this is their union. For the same keys,
+-- the values from the first table will be overwritten
+-- @param t table to be updated
+-- @param other table
+-- @return the updated table
+function ml.update(t,other)
+ for k,v in pairs(other) do
+ t[k] = v
+ end
+ return t
+end
+
+--- extend a list using values from another.
+-- @param t the list to be extended
+-- @param other a list
+-- @return the extended list
+function ml.extend(t,other)
+ local n = #t
+ for i = 1,#other do
+ t[n+i] = other[i]
+ end
+ return t
+end
+
+--- make a set from a list.
+-- @param t a list of values
+-- @return a table where the keys are the values
+-- @usage set{'one','two'} == {one=true,two=true}
+function ml.set(t)
+ local res = {}
+ for i = 1,#t do
+ res[t[i]] = true
+ end
+ return res
+end
+
+--- extract the keys of a table as a list.
+-- This is the opposite operation to tset
+-- @param t a table
+-- @param a list of keys
+function ml.keys(t)
+ local res,k = {},1
+ for key in pairs(t) do
+ res[k] = key
+ k = k + 1
+ end
+ return res
+end
+
+--- is `other` a subset of `t`?
+-- @param t a set
+-- @param other a possible subset
+-- @return true or false
+function ml.subset(t,other)
+ for k,v in pairs(other) do
+ if t[k] ~= v then return false end
+ end
+ return true
+end
+
+--- are these two tables equal?
+-- This is shallow equality.
+-- @param t a table
+-- @param other a table
+-- @return true or false
+function ml.tequal(t,other)
+ return ml.subset(t,other) and ml.subset(other,t)
+end
+
+--- the intersection of two tables.
+-- Works as expected for sets, otherwise note that the first
+-- table's values are preseved
+-- @param t a table
+-- @param other a table
+-- @return the intersection of the tables
+function ml.intersect(t,other)
+ local res = {}
+ for k,v in pairs(t) do
+ if other[k] then
+ res[k] = v
+ end
+ end
+ return res
+end
+
+--- collect the values of an iterator into a list.
+-- @param iter a single or double-valued iterator
+-- @param count an optional number of values to collect
+-- @return a list of values.
+-- @usage collect(ipairs{10,20}) == {{1,10},{2,20}}
+function ml.collect (iter, count)
+ local res,k = {},1
+ local v1,v2 = iter()
+ local dbl = v2 ~= nil
+ while v1 do
+ if dbl then v1 = {v1,v2} end
+ res[k] = v1
+ k = k + 1
+ if count and k > count then break end
+ v1,v2 = iter()
+ end
+ return res
+end
+
+--- Functional helpers.
+-- @section function
+
+--- create a function which will throw an error on failure.
+-- @param f a function that returns nil,err if it fails
+-- @return an equivalent function that raises an error
+function ml.throw(f)
+ f = ml.function_arg(f)
+ return function(...)
+ local res,err = f(...)
+ if err then error(err) end
+ return res
+ end
+end
+
+--- create a function which will never throw an error.
+-- This is the opposite situation to throw; if the
+-- original function throws an error e, then this
+-- function will return nil,e.
+-- @param f a function which can throw an error
+-- @return a function which returns nil,error when it fails
+function ml.safe(f)
+ f = ml.function_arg(f)
+ return function(...)
+ local ok,r1,r2,r3 = pcall(f,...)
+ if ok then return r1,r2,r3
+ else
+ return nil,r1
+ end
+ end
+end
+--memoize(f)
+
+--- bind the value `v` to the first argument of function `f`.
+-- @param f a function of at least one argument
+-- @param v a value
+-- @return a function of one less argument
+-- @usage (bind1(string.match,'hello')('^hell') == 'hell'
+function ml.bind1(f,v)
+ f = ml.function_arg(f)
+ return function(...)
+ return f(v,...)
+ end
+end
+
+--- compose two functions.
+-- For instance, `printf` can be defined as `compose(io.write,string.format)`
+-- @param f1 a function
+-- @param f2 a function
+-- @return f1(f2(...))
+function ml.compose(f1,f2)
+ f1 = ml.function_arg(f1)
+ f2 = ml.function_arg(f2)
+ return function(...)
+ return f1(f2(...))
+ end
+end
+
+--- is the object either a function or a callable object?.
+-- @param obj Object to check.
+-- @return true if callable
+function ml.callable (obj)
+ return type(obj) == 'function' or getmetatable(obj) and getmetatable(obj).__call
+end
+
+function ml.function_arg(f)
+ assert(ml.callable(f),"expecting a function or callable object")
+ return f
+end
+
+--- Classes.
+-- @section class
+
+--- create a class with an optional base class.
+-- The resulting table has a new() function for invoking
+-- the constructor, which must be named `_init`. If the base
+-- class has a constructor, you can call it as the `super()` method.
+-- The `__tostring` metamethod is also inherited, but others need
+-- to be brought in explicitly.
+-- @param base optional base class
+-- @return the metatable representing the class
+function ml.class(base)
+ local klass, base_ctor = {}
+ klass.__index = klass
+ if base then
+ setmetatable(klass,base)
+ klass._base = base
+ base_ctor = rawget(base,'_init')
+ klass.__tostring = base.__tostring
+ end
+ function klass.new(...)
+ local self = setmetatable({},klass)
+ if rawget(klass,'_init') then
+ klass.super = base_ctor -- make super available for ctor
+ klass._init(self,...)
+ elseif base_ctor then -- call base ctor automatically
+ base_ctor(self,...)
+ end
+ return self
+ end
+ return klass
+end
+
+--- is an object derived from a class?
+-- @param self the object
+-- @param klass a class created with `class`
+-- @return true or false
+function ml.is_a(self,klass)
+ local m = getmetatable(self)
+ if not m then return false end --*can't be an object!
+ while m do
+ if m == klass then return true end
+ m = rawget(m,'_base')
+ end
+ return false
+end
+
+local _type = type
+
+--- extended type of an object.
+-- The type of a table is its metatable, otherwise works like standard type()
+-- @param obj a value
+-- @return the type, either a string or the metatable
+function ml.type (obj)
+ if _type(obj) == 'table' then
+ return getmetatable(obj) or 'table'
+ else
+ return _type(obj)
+ end
+end
+
+return ml