diff options
Diffstat (limited to 'macros/luatex/generic/penlight/penlightextras.lua')
-rw-r--r-- | macros/luatex/generic/penlight/penlightextras.lua | 738 |
1 files changed, 534 insertions, 204 deletions
diff --git a/macros/luatex/generic/penlight/penlightextras.lua b/macros/luatex/generic/penlight/penlightextras.lua index 3479eb3fa0..0cdec03763 100644 --- a/macros/luatex/generic/penlight/penlightextras.lua +++ b/macros/luatex/generic/penlight/penlightextras.lua @@ -1,172 +1,264 @@ + +__SKIP_TEX__ = __SKIP_TEX__ or false --if declared true before here, it will use regular print functions +-- (for troubleshooting with texlua instead of actual use in lua latex) + +__PL_NO_GLOBALS__ = __PL_NO_GLOBALS__ or false + -- requires penlight local pl = _G['penlight'] or _G['pl'] -- penlight for this namespace is pl -local bind = bind or pl.func.bind --- some bonus string operations, % text operator, and functional programmng + +-- some bonus string operations, % text operator, and functional programming pl.stringx.import() pl.text.format_operator() -pl.utils.import('pl.func') +pl.utils.import('pl.func') -- allow placeholder expressions _1 +1 etc. + +pl.COMP = require'pl.comprehension'.new() -- for comprehensions + +-- http://lua-users.org/wiki/SplitJoin -- todo read me!! + +pl.tex = {} -- adding a sub-module for tex related stuff + +local bind = bind or pl.func.bind + + +function pl.hasval(x) -- if something has value + if (type(x) == 'function') or (type(x) == 'CFunction') or (type(x) == 'userdata') then + return true + elseif (x == nil) or (x == false) or (x == 0) or (x == '') or (x == {}) then + return false + elseif (type(x) ~= 'boolean') and (type(x) ~= 'number') and (type(x) ~= 'string') then -- something else? maybe ths not needed + if #x == 0 then -- one more check, probably no needed though, I was trying to cover other classes but they all tables + return false + else + return true + end + end + return true +end + + +-- Some simple and helpful LaTeX functions -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +-- xparse defaults +pl.tex._xTrue = '\\BooleanTrue ' +pl.tex._xFalse = '\\BooleanFalse ' +pl.tex._xNoValue = '-NoValue-' + +--Generic LuaLaTeX utilities for print commands or environments + +if not __SKIP_TEX__ then + local function check_special_chars(s) -- todo extend to toher special chars? + if type(s) == 'string' then + if string.find(s, '[\n\r\t\0]') then + pl.tex.pkgwarn('penlight', 'printing string with special (eg. newline) char, possible unexpected behaviour on string: '..s) + end + end + end -function help_wrt(s1, s2) -- helpful printing, makes it easy to debug, s1 is object, s2 is note - local wrt = wrt or texio.write_nl - local wrt = wrt or print + -- NOTE: usage is a bit different than default. If number is first arg, you CANT change catcode. + -- We don't need that under normal use, use tex.print or tex.sprint if you need + function pl.tex.prt(s, ...) -- print something, no new line after + check_special_chars(s) + if type(s) == 'number' then s = tostring(s) end + tex.sprint(s, ...) --can print lists as well, but will NOT put new line between them or anything printed + end + + function pl.tex.prtn(s, ...) -- print with new line after, can print lists or nums. C-function not in Lua, apparantly + s = s or '' + check_special_chars(s) + if type(s) == 'number' then s = tostring(s) end + tex.print(s, ...) + end + + pl.tex.wrt = texio.write + pl.tex.wrtn = texio.write_nl +else + pl.tex.prt = io.write + pl.tex.prtn = print --print with new line + pl.tex.wrt = io.write + pl.tex.wrtn = io.write_nl +end + +function pl.tex.prtl(str) -- prints a literal/lines string in latex, adds new line between them + for line in str:gmatch"[^\n]*" do -- gets all characters up to a new line + pl.tex.prtn(line) + end +end + +-- todo option to specify between character? one for first table, on for recursives? +function pl.tex.prtt(tab, d1, d2) -- prints a table with new line between each item + d1 = d1 or '' + d2 = d2 or '\\leavevmode\\\\' + for _, t in pairs(tab) do -- + if type(t) ~= 'table' then + if d1 == '' then + pl.tex.prtn(t) + else + pl.tex.prt(t, d1) + end + else + pl.tex.prtn(d2) + pl.tex.prtt(t,d1,d2) + end + end +end + +function pl.tex.help_wrt(s1, s2) -- helpful printing, makes it easy to debug, s1 is object, s2 is note + local wrt2 = wrt or texio.write_nl or print s2 = s2 or '' - wrt('\nvvvvv '..s2..'\n') + wrt2('\nvvvvv '..s2..'\n') if type(s1) == 'table' then - wrt(pl.pretty.write(s1)) + wrt2(pl.pretty.write(s1)) else - wrt(tostring(s1)) + wrt2(tostring(s1)) end - wrt('\n^^^^^\n') + wrt2('\n^^^^^\n') end -function prt_array2d(t) +function pl.tex.prt_array2d(t) for _, r in ipairs(t) do local s = '' for _, v in ipairs(r) do s = s.. tostring(v)..', ' end - print(s) + pl.tex.prt(s) + pl.tex.prt('\n') end end -- -- -- -- -- - --- -- -- -- functions below are helpers for arrays and 2d - -local function compare_elements(a, b, op, ele) - op = op or pl.oper.gt - ele = ele or 1 - return op(a[ele], b[ele]) +function pl.tex.pkgwarn(pkg, msg1, msg2) + pkg = pkg or '' + msg1 = msg1 or '' + msg2 = msg2 or '' + tex.sprint('\\PackageWarning{'..pkg..'}{'..msg1..'}{'..msg2..'}') end -local function comp_2ele_func(op, ele) -- make a 2 element comparison function, - --sort with function on element nnum - return bind(compare_elements, _1, _2, op, ele) +function pl.tex.pkgerror(pkg, msg1, msg2, stop) + pkg = pkg or '' + msg1 = msg1 or '' + msg2 = msg2 or '' + stop = pl.hasval(stop) + tex.sprint('\\PackageError{'..pkg..'}{'..msg1..'}{'..msg2..'}') + if stop then tex.sprint('\\stop') end -- stop on the spot (say that 10 times) end --- -- -- -- +--definition helpers -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +function pl.tex.defcmd(cs, val) -- simple definitions + val = val or '' + token.set_macro(cs, val, 'global') +end -local function check_index(ij, rc) -- converts array index to positive value if negative - if type(ij) ~= 'number' then - return 1 +function pl.tex.prvcmd(cs, val) -- provide command via lua + if token.is_defined(cs) then + -- do nothing if token is defined already --pkgwarn('penlight', 'Definition '..cs..' is being overwritten') else - if ij < 0 then - ij = rc + ij + 1 - elseif ij > rc then - ij = rc - end - return ij + pl.tex.defcmd(cs, val) end end -local function check_slice(M, i1, j1, i2, j2) -- ensure a slice is valid; i.e. all positive numbers - r, c = pl.array2d.size(M) - i1 = check_index(i1, r) - i2 = check_index(i2, r) - j1 = check_index(j1, c) - j2 = check_index(j2, c) - return i1, j1, i2, j2 -end -local function check_func(func) -- check if a function is a PE, if so, make it a function - if type(func) ~= 'function' then - __func = I(func) +function pl.tex.newcmd(cs, val) -- provide command via lua + if token.is_defined(cs) then + pl.tex.pkgerror('penlight: newcmd',cs..' already defined') + else + pl.tex.defcmd(cs, val) end - return __func end - --- -- -- -- -- -- -- --- -- -- -- functions below extend the array2d module - - -function pl.array2d.map_slice1(func, L, i1, i2) -- map a function to a slice of an array, can use PlcExpr - i2 = i2 or i1 - local len = #L - i1 = check_index(i1, len) - i2 = check_index(i2, len) - func = check_func(func) - for i in pl.seq.range(i1,i2) do - L[i] = func(L[i]) - end - return L +function pl.tex.renewcmd(cs, val) -- provide command via lua + if token.is_defined(cs) then + pl.tex.defcmd(cs, val) + else + pl.tex.pkgerror('penlight: renewcmd',cs..' not defined') + end end -function pl.array2d.map_slice2(func, M, i1, j1, i2, j2) -- map a function to a slice of a Matrix - i1, j1, i2, j2 = check_slice(M, i1, j1, i2, j2) - --for i,j in array2d.iter(M, true, i1, j1, i2, j2) do --todo this did not work, penlight may have fixed this - func = check_func(func) - for i in pl.seq.range(i1,i2) do - for j in pl.seq.range(j1,j2) do - M[i][j] = func(M[i][j]) - end +function pl.tex.deccmd(cs, def, overwrite) -- declare a definition, placeholder throws an error if it used but not set! + overwrite = pl.hasval(overwrite) + local decfun + if overwrite then decfun = pl.tex.defcmd else decfun = pl.tex.newcmd end + if def == nil then + decfun(cs, pkgerror('penlight', cs..' was declared and used in document, but never set')) + else + decfun(cs, def) end - return M end -function pl.array2d.map_columns(func, M, j1, j2) -- map function to columns of matrix - j2 = j2 or j1 - return map_slice2(func, M, 1, j1, -1, j2) -end -function pl.array2d.map_rows(func, M, i1, i2) -- map function to rows of matrix - i2 = i2 or i1 - return map_slice2(func, M, i1, 1, i2, -1) -end +-- +-- -- todo add and improve this, options for args? +--local function defcmd_nest(cs) -- for option if you'd like your commands under a parent ex. \csparent{var} +-- tex.print('\\gdef\\'..cs..'#1{\\csname '..var..'--#1--\\endcsname}') +--end +-- +-- +--local function defcmd(cs, val, nargs) +-- if (nargs == nil) or (args == 0) then +-- token.set_macro(cs, tostring(val), 'global') +-- else +-- local args = '#1' +-- tex.print('\\gdef\\'..cs..args..'{'..val..'}') +-- -- todo https://tex.stackexchange.com/questions/57551/create-a-capitalized-macro-token-using-csname +-- -- \expandafter\gdef\csname Two\endcsname#1#2{1:#1, two:#2} --todo do it like this +-- end +--end +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --- -- -- -- -- -- -- -- -function pl.array2d.sortOP(M, op, ele) -- sort a 2d array based on operator criteria, ele is column, ie sort on which element - M_new = {} - for row in pl.seq.sort(M, comp_2ele_func(op, ele)) do - M_new[#M_new+1] = row - end - return M_new + +-- when nesting commands, this makes it helpful to not worry about brackets +pl.tex._NumBkts = 0 +--prt(opencmd('textbf')..opencmd('texttt')..'bold typwriter'..close_bkt_cnt()) + +function pl.tex.opencmd(cmd) + return '\\'..cmd..add_bkt_cnt() end -function pl.array2d.like(M1, v) - v = v or 0 - r, c = pl.array2d.size(M1) - return pl.array2d.new(r,c,v) +function pl.tex.reset_bkt_cnt(n) + n = n or 0 + _NumBkts = n end -function pl.array2d.from_table(t) -- turns a labelled table to a 2d, label-free array - t_new = {} - for k, v in pairs(t) do - if type(v) == 'table' then - t_new_row = {k} - for _, v_ in ipairs(v) do - t_new_row[#t_new_row+1] = v_ - end - t_new[#t_new+1] = t_new_row - else - t_new[#t_new+1] = {k, v} - end - end - return t_new +function pl.tex.add_bkt_cnt(n) + -- add open bracket n times, returns brackets + n = n or 1 + _NumBkts = _NumBkts + n + return ('{'):rep(n) end -function pl.array2d.toTeX(M, EL) --puts & between columns, can choose to end line with \\ if EL is true (end-line) - EL = EL or false - if EL then EL = '\\\\' else EL = '' end - return pl.array2d.reduce2(_1..EL.._2, _1..'&'.._2, M)..EL +function pl.tex.close_bkt_cnt(n) + n = n or _NumBkts + local s = ('}'):rep(n) + _NumBkts = _NumBkts - n + return s end --- -- -- -- -- -- -- +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + + --- -- -- -- -- -- -- -- -- -- -- -- functions below extend the operator module -function pl.operator.strgt(a,b) return tostring(a) > tostring(b) end -function pl.operator.strlt(a,b) return tostring(a) < tostring(b) end +-- -- -- -- math stuff +function math.mod(a, b) -- math modulo, return remainder only + return a - (math.floor(a/b)*b) +end + +function math.mod2(a) -- math modulo 2 + return math.mod(a,2) +end + -- -- -- -- string stuff @@ -184,14 +276,13 @@ local number = P{"number", } -local mt = getmetatable("") -- register functions with str - +local str_mt = getmetatable("") -- register functions with str -function mt.__index.gnum(s) +function str_mt.__index.gnum(s) return number:match(s) end -function mt.__index.gextract(s, pat) --extract a pattern from string, returns both +function str_mt.__index.gextract(s, pat) --extract a pattern from string, returns both local s_extr = '' local s_rem = s for e in s:gmatch(pat) do @@ -201,7 +292,7 @@ function mt.__index.gextract(s, pat) --extract a pattern from string, returns bo return s_extr, s_rem end -function mt.__index.gfirst(s, t) -- get the first pattern found from a table of pattern +function str_mt.__index.gfirst(s, t) -- get the first pattern found from a table of pattern for _, pat in pairs(t) do if string.find(s, pat) then return pat @@ -209,7 +300,7 @@ function mt.__index.gfirst(s, t) -- get the first pattern found from a table of end end -function mt.__index.appif(S, W, B, O) --append W ord to S tring if B oolean true, otherwise O ther +function str_mt.__index.appif(S, W, B, O) --append W ord to S tring if B oolean true, otherwise O ther --append Word to String if B then --if b is true S = S .. W @@ -221,155 +312,394 @@ function mt.__index.appif(S, W, B, O) --append W ord to S tring if B oolean true end - --- -- -- -- -- math stuffs - -function mod(a, b) -- math modulo, return remainder only - return a - (math.floor(a/b)*b) + function str_mt.__index.containsany(s, exp) + if type(exp) ~= 'table' then exp = {exp} end + for _, e in ipairs(exp) do + if s:find(e) then return true end + end + return false end -function mod2(a) -- math modulo 2 - return mod(a,2) +function str_mt.__index.containsanycase(s, exp) + if type(exp) ~= 'table' then exp = {exp} end + for _, e in ipairs(exp) do + if s:lower():find(e:lower()) then return true end + end + return false end -function hasval(x) -- if something has value - if (type(x) == 'function') then - return true - elseif (x == nil) or (x == false) or (x == 0) or (x == '') then - return false - elseif (type(x) ~= 'boolean') and (type(x) ~= 'number') and (type(x) ~= 'string') then - if #x == 0 then - return false - else - return true - end +function str_mt.__index.totable(str) + local t = {} + for i = 1, #str do + t[i] = str:sub(i, i) end - return true + return t end +-- -- -- -- function stuff + +function pl.clone_function(fn) + local dumped = string.dump(fn) + local cloned = loadstring(dumped) + local i = 1 + while true do + local name = debug.getupvalue(fn, i) + if not name then + break + end + debug.upvaluejoin(cloned, i, fn, i) + i = i + 1 + end + return cloned +end +-- -- -- -- -- -- -- -- -- -- -- -- functions below extend the operator module --- Some simple and helpful LaTeX functions --- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +function pl.operator.strgt(a,b) return tostring(a) > tostring(b) end +function pl.operator.strlt(a,b) return tostring(a) < tostring(b) end ---Generic LuaLaTeX utilities for print commands or environments --- http://lua-users.org/wiki/SplitJoin -- todo read me!! -__SKIP_TEX__ = __SKIP_TEX__ or false --if declared true before here, it will use regular print functions --- (for troubleshooting with texlua) --- xparse defaults -_xTrue = '\\BooleanTrue ' -_xFalse = '\\BooleanFalse ' -_xNoValue = '-NoValue-' +-- -- -- -- functions below are helpers for arrays and 2d -if not __SKIP_TEX__ then - prt = tex.sprint --can print lists, but will NOT put new line between them - prtn = tex.print --can print lists and will put new line. C-function not in Lua. think P rint R return - wrt = texio.write - wrtn = texio.write_nl -else - prt = io.write - prtn = print --print with new line - wrt = io.write - wrtn = io.write_nl +local function compare_elements(a, b, op, ele) + op = op or pl.oper.gt + ele = ele or 1 + return op(a[ele], b[ele]) end -function prtl(str) -- prints a literal string to latex, adds new line between them - for line in str:gmatch"[^\n]*" do -- gets all characters up to a new line - prtn(line) - end +local function comp_2ele_func(op, ele) -- make a 2 element comparison function, + --sort with function on element nnum + return bind(compare_elements, _1, _2, op, ele) end -_NumBkts = 0 -function reset_bkt_cnt(n) - n = n or 0 - _NumBkts = n -end -function add_bkt_cnt(n) - -- add open bracket n times, returns brackets - n = n or 1 - _NumBkts = _NumBkts + n - return ('{'):rep(n) + +-- table stuff below + + +function pl.tablex.map_slice(func, T, j1, j2) + if type(j1) == 'string' then + return pl.array2d.map_slice(func, {T}, ','..j1)[1] + else + return pl.array2d.map_slice(func, {T}, 1, j1, 1, j2)[1] + end end -function close_bkt_cnt() - local s = ('}'):rep(_NumBkts) - reset_bkt_cnt() - return s +pl.array2d.map_slice1 = pl.tablex.map_slice + + +-- todo option for multiple filters with AND logic, like the filter files?? +function pl.tablex.filterstr(t, exp, case) + -- case = case sensitive + case = hasval(case) + -- apply lua patterns to a table to filter iter + -- str or table of str's can be passed, OR logic is used if table is passed + if case then + return pl.tablex.filter(t, bind(string.containsany,_1,exp)) + else + return pl.tablex.filter(t, bind(string.containsanycase,_1,exp)) + end end +function pl.utils.filterfiles(...) + -- f1 is a series of filtering patterns, or condition + -- f2 is a series of filtering patters, or condition + -- (f1_a or f2_...) and (f2 .. ) must match + local args = table.pack(...) + -- todo -- check where boolean is for recursive or not, set starting argument + -- this could allow one to omit dir + -- todo if no boolean at all, assume dir = '.' and r = false + -- if boolean given, assume dir = '.' + local nstart = 3 + local r = args[2] + local dir = args[1] + if type(args[1]) == 'boolean' then + dir = '.' + r = args[1] + nstart = 2 + elseif type(args[2]) ~= 'boolean' then + dir = '.' + r = false + nstart = 1 + end + local files + if r then files = pl.dir.getallfiles(dir) + else files = pl.dir.getfiles(dir) + end + for i=nstart,args.n do + files = pl.tablex.filter(files, pl.func.compose(bind(string.containsanycase,_1, args[i]), pl.path.basename)) + end + return files +end +-- -- -- -- -- -- -- -- functions below extend the array2d module ---definition helpers -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --- todo add and improve this -local function defcmd_nest(cs) -- for option if you'd like your commands under a parent ex. \csparent{var} - tex.print('\\gdef\\'..cs..'#1{\\csname '..var..'--#1--\\endcsname}') +function pl.array2d.map_slice(func, M, i1, j1, i2, j2) -- map a function to a slice of a Matrix + func = pl.utils.function_arg(1, func) + for i,j in pl.array2d.iter(M, true, i1, j1, i2, j2) do + M[i][j] = func(M[i][j]) + end + return M end +pl.array2d.map_slice2 = pl.array2d.map_slice -local function defcmd(cs, val, nargs) - if (nargs == nil) or (args == 0) then - token.set_macro(cs, tostring(val), 'global') +function pl.array2d.map_cols(func, M, j1, j2) -- map function to columns of matrix + if type(j1) == 'string' then + return pl.array2d.map_slice(func, M, ','..j1) else - local args = '#1' - tex.print('\\gdef\\'..cs..args..'{'..val..'}') - -- todo https://tex.stackexchange.com/questions/57551/create-a-capitalized-macro-token-using-csname - -- \expandafter\gdef\csname Two\endcsname#1#2{1:#1, two:#2} --todo do it like this + j2 = j2 or -1 + return pl.array2d.map_slice(func, M, 1, j1, -1, j2) end end +pl.array2d.map_columns = pl.array2d.map_cols -local function prvcmd(cs, val) -- provide command via lua - if token.is_defined(cs) then - tex.print('\\PackageWarning{YAMLvars}{Variable '..cs..' already defined, could not declare}{}') +function pl.array2d.map_rows(func, M, i1, i2) -- map function to rows of matrix + if type(i1) == 'string' then + return pl.array2d.map_slice(func, M, i1) else - defcmd(cs, val) + i2 = i2 or -1 + return pl.array2d.map_slice(func, M, i1, 1, i2, -1) end end -local function newcmd(cs, val) -- provide command via lua - if token.is_defined(cs) then - tex.print('\\PackageError{luadefs}{Command '..cs..' already defined}{}') - else - defcmd(cs, val) +-- -- -- -- -- -- -- -- + +function pl.array2d.sortOP(M, op, ele) -- sort a 2d array based on operator criteria, ele is column, ie sort on which element + M_new = {} + for row in pl.seq.sort(M, comp_2ele_func(op, ele)) do + M_new[#M_new+1] = row + end + return M_new +end + +function pl.array2d.like(M1, v) + v = v or 0 + r, c = pl.array2d.size(M1) + return pl.array2d.new(r,c,v) +end + +function pl.array2d.from_table(t) -- turns a labelled table to a 2d, label-free array + t_new = {} + for k, v in pairs(t) do + if type(v) == 'table' then + t_new_row = {k} + for _, v_ in ipairs(v) do + t_new_row[#t_new_row+1] = v_ + end + t_new[#t_new+1] = t_new_row + else + t_new[#t_new+1] = {k, v} + end end + return t_new end -local function renewcmd(cs, val) -- provide command via lua - if token.is_defined(cs) then - defcmd(cs, val) +function pl.array2d.toTeX(M, EL) --puts & between columns, can choose to end line with \\ if EL is true (end-line) + EL = EL or false + if EL then EL = '\\\\' else EL = '' end + return pl.array2d.reduce2(_1..EL.._2, _1..'&'.._2, M)..EL +end + + +local function parse_numpy1d(i1, i2, iS) + i1 = tonumber(i1) + i2 = tonumber(i2) + if iS == ':' then + if i1 == nil then i1 = 1 end + if i2 == nil then i2 = -1 end else - tex.print('\\PackageError{luadefs}{Command '..cs..' already defined}{}') + if i1 == nil then + i1 = 1 + i2 = -1 + else + i2 = i1 + end end + return i1, i2 end -local function deccmd(cs, def) - if def == nil then - prvcmd(cs, '\\PackageError{luadefs}{Command "'..cs..'" was declared and used but, not set}{}') - else - prvcmd(cs, def) +function pl.array2d.parse_numpy2d_str(s) + s = s:gsub('%s+', '') + _, _, i1, iS, i2, j1, jS, j2 = string.find(s, "(%-?%d*)(:?)(%-?%d*),?(%-?%d*)(:?)(%-?%d*)") + i1, i2 = parse_numpy1d(i1, i2, iS) + j1, j2 = parse_numpy1d(j1, j2, jS) + return i1, j1, i2, j2 +end + + +local _parse_range = pl.clone_function(pl.array2d.parse_range) + +function pl.array2d.parse_range(s) -- edit parse range to do numpy string if no letter passed + pl.utils.assert_arg(1,s,'string') + if not s:find'%a' then + return pl.array2d.parse_numpy2d_str(s) end + return _parse_range(s) end --- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + + + + +if not __PL_NO_GLOBALS__ then + -- iterators + kpairs = pl.utils.kpairs + npairs = pl.utils.npairs + --enum = utils.enum + + for k,v in pairs(pl.tablex) do -- extend the table table to contain tablex functions + _G['table'][k] = v + end + + hasval = pl.hasval + COMP = pl.COMP + + -- shortcuts +-- http://stevedonovan.github.io/Penlight/api/libraries/pl.utils.html + pl.writefile = pl.utils.writefile + pl.readfile = pl.utils.readfile + pl.readlines = pl.utils.readfile + pl.filterfiles = pl.utils.filterfiles + + pl.a2 = pl.array2d + pl.tbl = pl.tablex + + + for k,v in pairs(pl.tex) do -- make tex functions global + _G[k] = v + end + + --_xTrue = pl.tex._xTrue + --_xFalse = pl.tex._xFalse + --_xNoValue = pl.tex._xNoValue + -- + --prt = pl.tex.prt + --prtn = pl.tex.prtn + --wrt = pl.tex.wrt + --wrtn = pl.tex.wrtn + -- + --prtl = pl.tex.prtl + --prtt = pl.tex.prtt + -- + --help_wrt = pl.tex.help_wrt + --prt_array2d = pl.tex.prt_array2d + -- + --pkgwarn = pl.tex.pkgwarn + --pkgerror = pl.tex.pkgerror + -- + --defcmd = pl.tex.defcmd + --prvcmd = pl.tex.prvcmd + --newcmd = pl.tex.newcmd + --renewcmd = pl.tex.renewcmd + --deccmd = pl.tex.deccmd + -- + --_NumBkts = pl.tex._NumBkts + --opencmd = pl.tex.opencmd + --reset_bkt_cnt = pl.tex.reset_bkt_cnt + --add_bkt_cnt = pl.tex.add_bkt_cnt + --close_bkt_cnt = pl.tex.close_bkt_cnt + +end + + + + + +-- graveyard + + +-- luakeys parses individual keys as ipairs, this changes the list to a pure map +--function pl.luakeystomap(t) +-- local t_new = {} +-- for k, v in pairs(t) do +-- if type(k) == 'number' then +-- t_new[v] = true +-- else +-- t_new[k] = v +-- end +-- end +-- return t_new +--end +--if luakeys then -- if luakeys is already loaded +-- function luakeys.parseN(s, ...) +-- local t = luakeys.parse(s,...) +-- t = pl.luakeystomap(t) +-- return t +-- end +--end +-- might not be needed + + + --local func = check_func(func) +--local function check_func(func) -- check if a function is a PE, if so, make it a function +-- if type(func) ~= 'function' then +-- return I(func) +-- end +-- return func +--end + +-- -- -- -- -- -- -- +-- -- -- -- functions below extend the array2d module + + +--function pl.array2d.map_slice1(func, L, i1, i2) -- map a function to a slice of an array, can use PlcExpr +-- i2 = i2 or i1 +-- local len = #L +-- i1 = check_index(i1, len) +-- i2 = check_index(i2, len) +-- func = check_func(func) +-- for i in pl.seq.range(i1,i2) do +-- L[i] = func(L[i]) +-- end +-- return L +--end + + -- used this below when iter was not working.. + --i1, j1, i2, j2 = check_slice(M, i1, j1, i2, j2) + --for i in pl.seq.range(i1,i2) do + -- for j in pl.seq.range(j1,j2) do + --end + -- penlight may have fixed this +--local function check_index(ij, rc) -- converts array index to positive value if negative +-- if type(ij) ~= 'number' then +-- return 1 +-- else +-- if ij < 0 then +-- ij = rc + ij + 1 +-- elseif ij > rc then +-- ij = rc +-- elseif ij == 0 then +-- ij = 1 +-- end +-- return ij +-- end +--end +--local function check_slice(M, i1, j1, i2, j2) -- ensure a slice is valid; i.e. all positive numbers +-- r, c = pl.array2d.size(M) +-- i1 = check_index(i1 or 1, r) +-- i2 = check_index(i2 or r, r) +-- j1 = check_index(j1 or 1, c) +-- j2 = check_index(j2 or c, c) +-- return i1, j1, i2, j2 +--end + |