diff --git a/README.md b/README.md index ced6439..36a1760 100644 --- a/README.md +++ b/README.md @@ -557,10 +557,13 @@ The standard Lua API is extended with the following features: * `string:split(delimeter)` - splits the string using the specified delimiter and returns a table; * `string:replace(regexp, string)` - replaces the text found by the regular expression with another text; * `slice(table, start, end)` - returns the part of the table starting with the `start` index and ending with `end` index; -* `get_index(table, value)` - returns the index of the table element; -* `get_key(table, value)` - returns the key of the table element; -* `concat_tables(table1, table2)` - adds elements from array table `table2` to `table1`; +* `index(table, value)` - returns the index of the table element; +* `key(table, value)` - returns the key of the table element; +* `concat(table1, table2)` - adds elements from array table `table2` to `table1`; +* `reverse(table)` - returns a table in which the elements follow in reverse order; +* `serialize(table)` - serializes the table into executable Lua code; * `round(x, n)` - rounds the number; +* `map(function, table)`, `filter(function, table)`, `head(table)`, `tail(table)`, `reduce(function, table)` - several convenience functional utilities form Haskell, Python etc. AIO Launcher also includes: @@ -620,7 +623,8 @@ Some tips on writing and debugging scripts: * The most convenient way to upload scripts to your smartphone is to use the `install-scripts.sh` script from this repository. This is a sh script for UNIX systems which loads all the scripts from the repository onto the (virtual) memory card of the smartphone using ADB. You can edit it to your liking. * The easiest way to reload an updated widget script is to swipe the widget to the right and then press the "reload" button. The search scripts will be reloaded automatically next time you open the search window. * Since version 4.3.0 AIO Launcher supports widget scripts hot reloading. To enable it, go to AIO Settings -> About and click on the version number 7 times. Then open AIO Settings -> Testing and enable the option "Hot reload scripts on resume". Now when you change the script, it will be automatically reloaded when you return to the desktop. -* Since version 4.4.2 AIO Launcher includes `debug` module with methods: `debug:log(text)`, `debug:toast(text)` and `debug:dialog(text)`. +* Since version 4.4.2 AIO Launcher includes `debug` module with methods: `debug:log(text)`, `debug:toast(text)` and `debug:dialog(text)`; +* Since version 4.8.0 you can use `--testing = "true"` meta tag. In this case, launcher will gray out the script and place it at the end of the list in the side menu. # Contribution diff --git a/lib/utils.lua b/lib/utils.lua index f2f74a2..0918600 100644 --- a/lib/utils.lua +++ b/lib/utils.lua @@ -29,7 +29,7 @@ function slice(tbl, s, e) return new end -function get_index(tab, val) +function index(tab, val) for index, value in ipairs(tab) do if value == val then return index @@ -39,7 +39,12 @@ function get_index(tab, val) return 0 end -function get_key(tab, val) +-- Deprecated +function get_index(tab, val) + return index(tab, val) +end + +function key(tab, val) for index, value in pairs(tab) do if value == val then return index @@ -49,13 +54,30 @@ function get_key(tab, val) return 0 end -function concat_tables(t1, t2) +-- Deprecated +function get_key(tab, val) + return key(tab, val) +end + +function concat(t1, t2) for _,v in ipairs(t2) do table.insert(t1, v) end end -function serialize_table(tab, ind) +-- Deprecated +function concat_tables(t1, t2) + concat(t1, t2) +end + +function reverse(tab) + for i = 1, math.floor(#tab/2) do + tab[i], tab[#tab-i+1] = tab[#tab-i+1], tab[i] + end + return tab +end + +function serialize(tab, ind) ind = ind and (ind .. " ") or " " local nl = "\n" local str = "{" .. nl @@ -94,4 +116,158 @@ function use(module, ...) end end +-- Functional Library +-- +-- @file functional.lua +-- @author Shimomura Ikkei +-- @date 2005/05/18 +-- +-- @brief porting several convenience functional utilities form Haskell,Python etc.. +-- map(function, table) +-- e.g: map(double, {1,2,3}) -> {2,4,6} +function map(func, tbl) + local newtbl = {} + for i,v in pairs(tbl) do + newtbl[i] = func(v) + end + return newtbl +end + +-- filter(function, table) +-- e.g: filter(is_even, {1,2,3,4}) -> {2,4} +function filter(func, tbl) + local newtbl= {} + for i,v in pairs(tbl) do + if func(v) then + newtbl[i]=v + end + end + return newtbl +end + +-- head(table) +-- e.g: head({1,2,3}) -> 1 +function head(tbl) + return tbl[1] +end + +-- tail(table) +-- e.g: tail({1,2,3}) -> {2,3} +-- +-- XXX This is a BAD and ugly implementation. +-- should return the address to next porinter, like in C (arr+1) +function tail(tbl) + if table.getn(tbl) < 1 then + return nil + else + local newtbl = {} + local tblsize = table.getn(tbl) + local i = 2 + while (i <= tblsize) do + table.insert(newtbl, i-1, tbl[i]) + i = i + 1 + end + return newtbl + end +end + +-- foldr(function, default_value, table) +-- e.g: foldr(operator.mul, 1, {1,2,3,4,5}) -> 120 +function foldr(func, val, tbl) + for i,v in pairs(tbl) do + val = func(val, v) + end + return val +end + +-- reduce(function, table) +-- e.g: reduce(operator.add, {1,2,3,4}) -> 10 +function reduce(func, tbl) + return foldr(func, head(tbl), tail(tbl)) +end + +-- curry(f,g) +-- e.g: printf = curry(io.write, string.format) +-- -> function(...) return io.write(string.format(unpack(arg))) end +function curry(f,g) + return function (...) + return f(g(unpack(arg))) + end +end + +-- bind1(func, binding_value_for_1st) +-- bind2(func, binding_value_for_2nd) +-- @brief +-- Binding argument(s) and generate new function. +-- @see also STL's functional, Boost's Lambda, Combine, Bind. +-- @examples +-- local mul5 = bind1(operator.mul, 5) -- mul5(10) is 5 * 10 +-- local sub2 = bind2(operator.sub, 2) -- sub2(5) is 5 -2 +function bind1(func, val1) + return function (val2) + return func(val1, val2) + end +end +function bind2(func, val2) -- bind second argument. + return function (val1) + return func(val1, val2) + end +end + +-- is(checker_function, expected_value) +-- @brief +-- check function generator. return the function to return boolean, +-- if the condition was expected then true, else false. +-- @example +-- local is_table = is(type, "table") +-- local is_even = is(bind2(math.mod, 2), 1) +-- local is_odd = is(bind2(math.mod, 2), 0) +is = function(check, expected) + return function (...) + if (check(unpack(arg)) == expected) then + return true + else + return false + end + end +end + +-- operator table. +-- @see also python's operator module. +operator = { + mod = math.mod; + pow = math.pow; + add = function(n,m) return n + m end; + sub = function(n,m) return n - m end; + mul = function(n,m) return n * m end; + div = function(n,m) return n / m end; + gt = function(n,m) return n > m end; + lt = function(n,m) return n < m end; + eq = function(n,m) return n == m end; + le = function(n,m) return n <= m end; + ge = function(n,m) return n >= m end; + ne = function(n,m) return n ~= m end; + +} + +-- enumFromTo(from, to) +-- e.g: enumFromTo(1, 10) -> {1,2,3,4,5,6,7,8,9} +-- TODO How to lazy evaluate in Lua? (thinking with coroutine) +enumFromTo = function (from,to) + local newtbl = {} + local step = bind2(operator[(from < to) and "add" or "sub"], 1) + local val = from + while val <= to do + table.insert(newtbl, table.getn(newtbl)+1, val) + val = step(val) + end + return newtbl +end + +-- make function to take variant arguments, replace of a table. +-- this does not mean expand the arguments of function took, +-- it expand the function's spec: function(tbl) -> function(...) +function expand_args(func) + return function(...) return func(arg) end +end