summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/penlight/penlightextras.lua
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-09-21 19:48:22 +0000
committerKarl Berry <karl@freefriends.org>2021-09-21 19:48:22 +0000
commit7ae12e79acacd03b0dc8508a6f64762c1d0b3ce0 (patch)
treeaefaa6856303bd1ff794c62b19f87b042c059bb7 /Master/texmf-dist/tex/luatex/penlight/penlightextras.lua
parentf8978870d707711cf4790fe169054f49679bd3bf (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.lua413
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
+
+
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --