diff options
author | Karl Berry <karl@freefriends.org> | 2021-09-21 19:48:22 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-09-21 19:48:22 +0000 |
commit | 7ae12e79acacd03b0dc8508a6f64762c1d0b3ce0 (patch) | |
tree | aefaa6856303bd1ff794c62b19f87b042c059bb7 /Master/texmf-dist/tex/luatex/penlight/penlightextras.lua | |
parent | f8978870d707711cf4790fe169054f49679bd3bf (diff) |
penlight (21sep21)
git-svn-id: svn://tug.org/texlive/trunk@60574 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/luatex/penlight/penlightextras.lua')
-rw-r--r-- | Master/texmf-dist/tex/luatex/penlight/penlightextras.lua | 413 |
1 files changed, 413 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/luatex/penlight/penlightextras.lua b/Master/texmf-dist/tex/luatex/penlight/penlightextras.lua new file mode 100644 index 00000000000..f612bd3370f --- /dev/null +++ b/Master/texmf-dist/tex/luatex/penlight/penlightextras.lua @@ -0,0 +1,413 @@ +-- requires penlight +local pl = _G['penlight'] or _G['pl'] -- penlight for this namespace is pl +local bind = bind or pl.func.bind + +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 + s2 = s2 or '' + wrt('\nvvvvv '..s2) + if type(s1) == 'table' then + wrt(pl.pretty.write(s1)) + else + wrt(tostring(s1)) + end + wrt('^^^^^\n') +end + + +function prt_array2d(t) + for _, r in ipairs(t) do + local s = '' + for _, v in ipairs(r) do + s = s.. tostring(v)..', ' + end + print(s) + 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]) +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 + + +-- -- -- -- + +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 + 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, 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) + end + return __func +end + + +-- -- -- -- -- -- -- +-- -- -- -- functions below extend the array2d module + + +local function 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 + +local function 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 + end + return M +end + +local function 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 + +local function 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 + + +-- -- -- -- -- -- -- -- + +function 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 + +local function like(M1, v) + v = v or 0 + r, c = pl.array2d.size(M1) + return pl.array2d.new(r,c,v) +end + +function 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 + +function 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 + +-- -- -- -- -- -- -- + +-- add to array2d module +pl.array2d['map_columns'] = map_columns +pl.array2d['map_rows'] = map_rows +pl.array2d['map_slice2'] = map_slice2 +pl.array2d['map_slice1'] = map_slice1 +pl.array2d['from_table'] = from_table +pl.array2d['toTeX'] = toTeX +pl.array2d['sortOP'] = sortOP +pl.array2d['like'] = like + + + + +-- -- -- -- -- -- -- -- -- -- -- -- functions below extend the operator module + +local function strgt(a,b) return tostring(a) > tostring(b) end +local function strlt(a,b) return tostring(a) < tostring(b) end +pl.operator['strgt'] = strgt +pl.operator['strlt'] = strlt + + + + + +local function gextract(s, pat) --extract a pattern from string, returns both + local s_extr = '' + local s_rem = s + for e in s:gmatch(pat) do + s_extr = s_extr..e + s_rem = s_rem:gsub(e,'') + end + return s_extr, s_rem +end + +local function 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 + end + end +end + +local function 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 + else --consider Other word + O = O or '' + S = S .. O + end + return S +end + +local mt = getmetatable("") -- register functions with str +mt.__index["gextract"] = gextract +mt.__index["gfirst"] = gfirst +mt.__index["app_if"] = appif + + +function mod(a, b) -- math modulo, return remainder only + return a - (math.floor(a/b)*b) +end + +function mod2(a) -- math modulo 2 + return mod(a,2) +end + +function hasval(x) -- if something has value + -- todo check for Lists, other penlight objects + if (x == nil) or (x == false) or (x == 0) or (x == '') then + return false + elseif type(x) == 'table' then + if #x == 0 then + return false + else + return true + end + end + return true +end + + + + +-- testing here +____zzz__ = [[ +function hasStrKey(T) + --checks if a Table contains a string-type key + local hasaStrKey = false + for k, v in pairs(T) do --look through table pairs + if type(k) == "string" then --if any string found, return true + hasaStrKey = true + break + end + end + return hasaStrKey +end + + +function any() + --todo go through table or list of args and return true of anything is something +end + +function all() + --todo go through table or list of args and return true of anything is something +end + + + --elseif x == {} then + -- return false + +n = nil +b = false +z = 0 +e = '' +t = {} + +--s = 'a' +--n = 1 + + +if is(nil) then + print('TRUE') +else + print('FALSE') +end + +--print({}=={}) +--print(0.0==0) + + +]] + + + + + + + + + + + +-- Some simple and helpful LaTeX functions +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +--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-' + + +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 +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 +end + + + +_NumBkts = 0 +function reset_bkt_cnt(n) + n = n or 0 + _NumBkts = n +end + +function add_bkt_cnt(n) + n = n or 1 + _NumBkts = _NumBkts + n +end + +function close_bkt_cnt() + local s = ('}'):rep(_NumBkts) + reset_bkt_cnt() + return s +end + + + + + + + + +--definition helpers -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +-- todo add 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}') +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 + + +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}{}') + else + defcmd(cs, val) + 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) + end +end + +local function renewcmd(cs, val) -- provide command via lua + if token.is_defined(cs) then + defcmd(cs, val) + else + tex.print('\\PackageError{luadefs}{Command '..cs..' already defined}{}') + end +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) + end +end + + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- |