texlive[72426] Master/texmf-dist: penlightplus (30sep24)

commits+karl at tug.org commits+karl at tug.org
Mon Sep 30 22:11:31 CEST 2024


Revision: 72426
          https://tug.org/svn/texlive?view=revision&revision=72426
Author:   karl
Date:     2024-09-30 22:11:31 +0200 (Mon, 30 Sep 2024)
Log Message:
-----------
penlightplus (30sep24)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/luatex/penlightplus/penlightplus.pdf
    trunk/Master/texmf-dist/doc/luatex/penlightplus/penlightplus.tex
    trunk/Master/texmf-dist/tex/luatex/penlightplus/penlightplus.lua
    trunk/Master/texmf-dist/tex/luatex/penlightplus/penlightplus.sty

Modified: trunk/Master/texmf-dist/doc/luatex/penlightplus/penlightplus.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/luatex/penlightplus/penlightplus.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/penlightplus/penlightplus.tex	2024-09-30 20:11:22 UTC (rev 72425)
+++ trunk/Master/texmf-dist/doc/luatex/penlightplus/penlightplus.tex	2024-09-30 20:11:31 UTC (rev 72426)
@@ -1,5 +1,5 @@
 % Kale Ewasiuk (kalekje at gmail.com)
-% 2024-08-17
+% 2024-09-30
 % Copyright (C) 2021-2024 Kale Ewasiuk
 %
 % Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -64,12 +64,31 @@
 
 \maketitle
 
-This package first loads the \cmd{[import]penlight} package.\\
+\section*{Package Options and Set-Up}
+
+This package first loads the \cmd{[import]penlight} package---see the documentation here \url{https://lunarmodules.github.io/Penlight/index.html}.\\
 The \texttt{pl} option may be passed to this package to create an alias for \cmd{penlight}.\\
-\texttt{globals} option may be used to make several of the functions global (as discussed below).
 
+The following global Lua variables are defined:
+
+\cmd{__SKIP_TEX__} If using the \cmd{penlightplus} package with \cmd{texlua} (good for troubleshooting), set this global before loading \cmd{penlight}\\
+\cmd{__PL_GLOBALS__} If using this package with \cmd{texlua} and you want to set some functions as globals (described in next sections), set this variable to \cmd{true} before loading \cmd{penlight}\\
+\cmd{__PL_NO_HYPERREF__} a flag used to change the behaviour of some functions, depending on if you don't use the hyperref package\\
+\cmd{__PDFmetadata__} a table used to store PDF meta-data for pdfx package.
+
+
+\subsubsection*{globals option}
+If the package option \cmd{globals} is used, many additional globals are set for easier scripting.
+\cmd{pl.hasval},  \cmd{pl.COMP}, \cmd{pl.utils.kpairs}, \cmd{pl.utils.npairs} become globals.
+\cmd{pl.tablex} is aliased as \cmd{pl.tbx and tbx} (which also includes all native Lua table functions), and
+\cmd{pl.array2d} is aliased as \cmd{pl.a2d and a2d}. Since this package uses the penlight \cmd{import} option,
+all \cmd{stringx} functions are injected into the \cmd{string} meta-table and you can use them like so: \cmd{'first name':upfirst()}.
+
+If you want global \cmd{pl.tex} functions and variables, call \cmd{pl.make_tex_global()}.\\
+
+
 \subsection*{texlua usage}
-If you want to use penlightplus.lua  with the \texttt{texlua} interpreter
+If you want to use \cmd{penlightplus.lua}  with the \texttt{texlua} interpreter
 (no document is made, but useful for testing your Lua code),
 you can access it by setting \cmd{__SKIP_TEX__ = true} before loading. For example:
  \begin{verbatim}
@@ -87,29 +106,12 @@
 
 
 
+\section*{penlight additions}
 
-The following global Lua variables are defined:
+Some functionality is added to penlight and Lua.
 
-\cmd{__SKIP_TEX__} If using the \cmd{penlightplus} package with \cmd{texlua} (good for troubleshooting), set this global before loading \cmd{penlight}\\
-The gloals flags below are taken care of in the package options:\\
-\cmd{__PL_GLOBALS__} If using package with \cmd{texlua} and you don't want to set some globals (described in next sections), set this global before to \cmd{true} loading \cmd{penlight}\\
-\cmd{__PL_NO_HYPERREF__} a flag used to change the behaviour of a function, depending on if you don't use the hyperref package\\
-\cmd{__PDFmetadata__} a table used to store PDF meta-data
+\subsection*{General Additions}
 
-
-\subsubsection*{global extras}
-If the package option \cmd{globals} is used, many additional globals are set for easier scripting.
-\cmd{pl.hasval},  \cmd{pl.COMP}, \cmd{pl.utils.kpairs}, \cmd{pl.utils.npairs} become globals.
-\cmd{pl.tablex} is aliased as \cmd{pl.tbx and tbx} (which also includes all native Lua table functions), and
-\cmd{pl.array2d} is aliased as \cmd{pl.a2d and a2d}.
-
-If you want global \cmd{pl.tex} funcs and vars, call \cmd{pl.make_tex_global()}\\
-
-
-\subsubsection*{penlight additions}
-
-Some functionality is added to penlight and Lua.
-
 \llcmd{pl.hasval(x)} Python-like boolean testing\\
 \llcmd{COMP'xyz'()} Python-like comprehensions:\\\url{https://lunarmodules.github.io/Penlight/libraries/pl.comprehension.html}\\
 
@@ -119,6 +121,16 @@
 
 \llcmd{math.mod(n,d)}, \cmd{math.mod2(n)} math modulous\\
 
+\llcmd{pl.utils.}\cmd{filterfiles}\cmd{(dir,filt,rec)} Get files from dir and apply glob-like filters. Set rec to \cmd{true} to include sub directories\\
+
+
+\llcmd{pl.}\cmd{char(n)} return letter corresponding to 1=a, 2=b, etc.\\
+\llcmd{pl.}\cmd{Char(n)} return letter corresponding to 1=A, 2=B, etc.\\
+
+
+
+\subsection*{string additions}
+
 \llcmd{string.}\cmd{upfirst(s)} uppercase first letter\\
 \llcmd{string.}\cmd{delspace(s)} delete all spaces\\
 \llcmd{string.}\cmd{trimfl(s)}remove first and last chars\\
@@ -138,6 +150,7 @@
 is processed by luakeys.\\
 \llcmd{string.}\cmd{parsekv(s, opts)} parse a string using \cmd{penlight.luakeys}. A string or table can be used for opts.
 
+\subsection*{tablex additions}
 \llcmd{tablex.}\cmd{fmt(t, f)} format a table with table or key-value string f\\
 \llcmd{tablex.}\cmd{strinds(t)} convert integer indexes to string indices (1 -> '1')\\
 \llcmd{tablex.}\cmd{filterstr(t,e,case)} keep only values in table t that contain expression e, case insensitive by default.\\
@@ -145,15 +158,32 @@
 \llcmd{tablex.}\cmd{listcontains(t,v)} checks if a value is in a array-style list \\
 
 
+\subsubsection*{seq additions}
+A syntax to produce sequences or a 'train' of numbers is provided. This may be useful for including pages from a pdf, or selecting rows of a table with a concise syntax.
+\cmd{seq.train(trn, len)} produces a pl.List according to the arguments (like choo-choo train)\\
+\cmd{seq.itrain(trn, len)} produces an iterator according to the arguments.
 
+An example syntax for \cmd{trn} is \cmd{'i1, i2, r1:r2', etc.}  where \cmd{i1} and \cmd{i2} are individual indexes/elements, separated by \cmd{,} and
+\cmd{r1:r2} is a range (inclusive of end-point) denoted with a \cmd{:}. The range format follows python's numpy indexing, and
+a 'stride' can be given by including a second colon like \cmd{::2  ->  is 1,3,5,...}, or \cmd{2::3  ->  2,5,8,...}.
+Negative numbers can be used to index relative to the length of the table, eg, \cmd{-1  ->  len}, but
+if length is not given, negative indexing cannot be used and a number after the first colon must be provided.
+A missing left-number on the colon assumes \cmd{1}, and missing right number assumes \cmd{len}. A missing 'stride' (number after the optional second colon) assumes a value of 1.
 
-\llcmd{pl.}\cmd{char(n)} return letter corresponding to 1=a, 2=b, etc.\\
-\llcmd{pl.}\cmd{Char(n)} return letter corresponding to 1=A, 2=B, etc.\\
+The default colon and comma separators for ranges and elements can be set with \cmd{seq.train_range_sep} and \cmd{seq.train_element_sep}, respectively.
+\begin{LTXexample}[width=0.5\linewidth]
+\begin{luacode*}
+  for i in
+    pl.seq.itrain('1, :, 6, 0::2, -3 ',
+                    5) do
+      tex.print(i..',')
+    end
+\end{luacode*}
+\end{LTXexample}
 
-\llcmd{pl.utils.}\cmd{filterfiles}\cmd{(dir,filt,rec)} Get files from dir and apply glob-like filters. Set rec to \cmd{true} to include sub directories\\
 
 
-\subsubsection*{A \cmd{pl.tex.} module is added}
+\subsection*{A \cmd{pl.tex.} module is added}
 \llcmd{add_bkt}\cmd{_cnt(n), }\cmd{close_bkt_cnt(n), reset_bkt_cnt} functions to keep track of adding curly brackets as strings. \cmd{add} will return \cmd{n} (default 1) \{'s and increment a counter. \cmd{close} will return \cmd{n} \}'s (default will close all brackets) and decrement.\\
 \llcmd{_NumBkts} internal integer for tracking the number of brackets\\
 \llcmd{opencmd(cs)} prints \cmd{\cs}\{ and adds to the bracket counters.\\
@@ -163,7 +193,7 @@
 \llcmd{prt(x),prtn(x)} print without or with a newline at end. Tries to help with special characters or numbers printing.\\
 \llcmd{prtl(l),prtt(t)} print a literal string, or table\\
 \llcmd{wrt(x), wrtn(x)} write to log\\
-\llcmd{wrh}\cmd{(s1, s2)} pretty-print something to console. S2 is a flag to help you find., alias is \cmd{help_wrt}, also in \cmd{pl.wrth}\\
+\llcmd{wrth}\cmd{(s1, s2)} pretty-print something to console. S2 is a flag to help you find., alias is \cmd{help_wrt}, also in \cmd{pl.wrth}\\
 \llcmd{prt_array2d(tt)} pretty print a 2d array\\
 \\
 \llcmd{pkgwarn}\cmd{(pkg, msg1, msg2)} throw a package warning\\
@@ -179,7 +209,10 @@
 is true, it will overwrite an existing command (using \cmd{defcmd}), otherwise, it will throw error like \cmd{newcmd}.\\
 \llcmd{get_ref_info(l)}accesses the \cmd{\r at label} and returns a table\\
 
-\subsubsection*{Recording latex input}
+
+
+
+\subsection*{Recording LaTeX input as a lua variable}
 \cmd{penlight.tex.startrecording()} start recording input buffer without printing to latex\\
 \cmd{penlight.tex.stoprecording()} stop recording input buffer\\
 \cmd{penlight.tex.readbuf()} internal-use function that interprets the buffer. This will ignore an environment ending (eg. \cmd{end{envir}})\\\\
@@ -186,20 +219,32 @@
 \cmd{penlight.tex.recordedbuf} the string variable where the recorded buffer is stored\\
 
 
+\section*{penlightplus LaTeX Macros}
 
 
 \subsection*{Macro helpers}
 \cmd{\MakeluastringCommands[def]{spec}} will let \cmd{\plluastring(A|B|C..)} be \cmd{\luastring(N|O|T|F)}
-based on the letters that \cmd{spec} is set to (or \cmd{def} if nothing is provided)
+based on the letters that \cmd{spec} is set to (or \cmd{def}(ault) if nothing is provided)
 This is useful if you want to write a command with flexibility on argument expansion.
 The user can specify \cmd{n}, \cmd{o}, \cmd{t}, and \cmd{f} (case insensitve) if they want
-no, once, twice, or full expansion. For example, we can control the expansion of args 2 and 3 with arg 1:
+none, once, twice, or full expansion.
 
+%\cmd{e} expansion expands every token in the argument only once.
+%\cmd{\luastringE{m}}, expands each token once (note that \cmd{\luastringO} only expands the first token once)
+
+
+
+Variants of luastring are added:\\
+\cmd{\luastringF{m}} = \cmd{\luastring{m}} \\
+\cmd{\luastringT{m}}, expand the first token of m twice\\
+
+For example, we can control the expansion of args 2 and 3 with arg 1:
+
 \begin{verbatim}
 	\NewDocumentCommand{\splittocomma}{ O{nn} m m }{%
-  \MakeluastringCommands[nn]{#1}%
-  \luadirect{penlight.tex.split2comma(\plluastringA{#2},\plluastringB{#3})}%
-}
+    \MakeluastringCommands[nn]{#1}%
+    \luadirect{penlight.tex.split2comma(\plluastringA{#2},\plluastringB{#3})}%
+   }
 \end{verbatim}
 
 %   BELOW IS FOR TROUBLESHOOTING ABOVE
@@ -221,7 +266,7 @@
 %\luastringExpTest{ n o t f }{\NOTexp}
 
 
-\subsection*{Lua boolean expressions and a case-switch for conditionals}
+\subsection*{Lua boolean expressions}
 
 \cmd{\ifluax{<Lua expr>}{<do if true>}[<do if false>]} and\\ \cmd{\ifluax{<Lua expr>}{<do if true>}[<do if false>]} for truthy (uses \cmd{penlight.hasval})
 
@@ -233,6 +278,8 @@
 \ifluaxv{''}{true}[false]\\
 \end{LTXexample}
 
+\subsection*{Case-switch for Conditionals}
+
 \cmd{\caseswitch{case}{kev-val choices}} The starred version will throw an error if the case is not found.
 Use \_\_ as a placeholder for a case that isn't matched.
 
@@ -244,39 +291,55 @@
 %\caseswitch*{\mycase}{dog=DOG, cat=CAT, __=INVALID}
 
 
-\subsection*{Creating and using Lua tables in LaTeX}
+\subsection*{Creating and using Lua tables in LaTeX - tbl interace}
+
 \cmd{penlightplus} provides a Lua-table interface. Tables are stored in the
 \cmd{penlight.tbls} table.
+You can access a table item within lua by using:
+\cmd{penlight.tbl'i'}.
 
 %%%
 
 \cmd{\tblnew{t}} declares a new table with name \cmd{t}\\
 \cmd{\tblchg{t}} changes the 'recent' table\\
+\\
 \cmd{\tblfrkv{t}{key-val string}[luakeys opts]} new table from key-vals using \cmd{luakeys} \\
 \cmd{\tblfrkvN{t}{key-val string}[luakeys opts]} does not expand key-val string \cmd{luakeys} \\
 \cmd{\tblfrkvCD{t}{key-val string}[luakeys opts]} define tbl from key-val,
 check if any were not defined as defaults (see below), and then push all to definitions\\
+\\
 \cmd{\tblkvundefcheck} will throw an error if you use define a table from key-values
-and use a key that was not specified in the luakeys parse options via \cmd{opts.defaults} or \cmd{opts.defs}.
+and use a key that was not specified in the luakeys parse options via \cmd{opts.defaults} or \cmd{opts.defs}.\\
+\\
  \cmd{\tblfrcsv{t}{csv}} a shorthand \cmd{\tblfrkv{t}{csv}[naked_as_value=true,opts]}, a good way to convert  a comma-separated list to an array\\
- \cmd{\tblfrcsvN{t}{csv}} same as above, but the csv is not expanded.
+ \cmd{\tblfrcsvN{t}{csv}} same as above, but the csv is not expanded.\\
+\\
 \cmd{\tblset{i}{v}} sets a value of the table/index \cmd{i} to \cmd{v}\\
+\cmd{\tblsetN{i}{v}} same as above, but the value is not expanded.\\
+\\
 \cmd{\tblget{i}} gets the value and \cmd{tex.sprint()}s it\\
+\\
 \cmd{\tbladd{i}{v}} add a new value to a table using index method\\
 \cmd{\tbladdN{i}{v}} above, but don't expand the value argument\\
+\\
 \cmd{\tblcon{t}{csv}} concatenate an array-style csv\\
+\cmd{\tblconN{t}{csv}}\\
+\\
 \cmd{\tblapp{t}{v}} append a value (integer-wise) to a table\\
+\cmd{\tblappN{t}{v}}\\
+\\
 \cmd{\tbldef{i}{d}} pushes the value to macro \cmd{d}\\
 \cmd{\tbldefall{t}{d}} define all item in table \cmd{t} (use recent if blank) with format \cmd{d<key>} where d is your prefix. If d is blank, keys will be defined as \cmd{\dtbl<t><k>}
 \cmd{\tblgdef{i}{d}} pushes the defined value to a global\\
 \cmd{\tbldefxy{i}{d}} splits the value of item by spaces creates two definitions \cmd{\dx} and \cmd{\dy}. Useful for pasing tikz coordinates like \cmd{xy=0 5}\\
 For definiting tables, if \cmd{d} is blank, commands are defined as \cmd{dtbl<t><k>}\\
+\\
 \cmd{\iftbl{i}{tr}[fa]} runs code \cmd{ta} if the item is true else \cmd{fr}\\
-\cmd{\iftblv{i}{tr}[fa]} runs code \cmd{ta} if the item is truthy else \cmd{fr}\\
+\cmd{\iftblv{i}{tr}[fa]} runs code \cmd{ta} if the item is truthy (using \cmd{pl.hasval}) else \cmd{fr}\\
 
 \cmd{\tblprt{t}} print the table in console
 
-There are 3 ways to use the index (placeholder \cmd{{i}} above).
+There are 3 ways to use the index (placeholder \cmd{{i}} above, note that this argument is fully expanded).
 \cmd{t.key} where \cmd{t} is the table name and \cmd{key} is a string key,
 \cmd{t/int} where \cmd{int} is an integer index (ie. uses \cmd{t[int]}, note that negative indexes are allowered where -1 is the last element),
 or simply use \cmd{ind} without the table name, where the assumed table is the last one that was created or changed to, (passing a number will used as an integer index).
@@ -333,8 +396,6 @@
 %\tblget{Bonjour}
 
 
-Note: for this versions: all latex tbl commands are now prefixed with \cmd{tbl}, eg., \cmd{tblget}, \cmd{tblset}.
-Old-style commands eg. \cmd{gettbl} will be kept as aliases for a few more releases then removed.
 
 
 \subsubsection*{A practical tbl example}
@@ -369,6 +430,7 @@
 \end{LTXexample}
 
 
+
 \subsection*{Splitting strings}
 Splitting text (or a cmd) into oxford comma format via:
 \cmd{\splittocomma[expansion level]{text}{text to split on}}:
@@ -396,13 +458,67 @@
 
 
 
-\subsubsection*{PDF meta data (for pdfx package)}
-\cmd{\writePDFmetadatakv*{m}} Take a key-value string (eg. \cmd{title=whatever, author=me}) and writes to the \cmd{jobname.xmpdata} file, to be used by pdfx. \cmd{*} will first clear the data\\
+\subsection*{PDF meta data (for pdfx package)}
+\cmd{\writePDFmetadatakv*[x]{kv}} Take a key-value string (eg. \cmd{title=whatever, author=me}) and then writes to the \cmd{jobname.xmpdata} file, which is used by pdfx. \cmd{*} will first clear \cmd{__PDFmetadata__} which contains the metadata. The un-starred version updates that table.
+You can control the expansion of the key-val argument with \cmd{[x]}, which is fully expanded by default.
+Command sequences are ultimately stripped from the values, except for \cmd{\and} is converted to \cmd{\sep} for pdfx usage (\url{https://texdoc.org/serve/pdfx/0}).
+\\
+
 \cmd{\writePDFmetadata} runs the lua function \cmd{penlight.tex.writePDFmetadata()},
 which pushes the lua variable \cmd{__PDFmetadata__} (a table) to the xmpdata file.
+This might be useful if you're updating \cmd{__PDFmetadata__} by some other means.
 
+\def\thekeywords{A\and B\and C}
+\def\thekeywords{ABC}
+\begin{LTXexample}
+\writePDFmetadatakv{author=Some One} %
+\writePDFmetadatakv*[n]{author=Kale \and You\xspace} % Overwrites above. Does not expant kv
+\writePDFmetadatakv{date=2024-02-01}
+\end{LTXexample}
 
 
+
+%\writePDFmetadatakv{datxe=2024-02-01} % would throw error, invalid key
+%\writePDFmetadatakv[E]{keywords=\thekeywords} %
+
+%\luadirect{texio.write_nl(\luastringE{keywords=\thekeywords})}
+
+
+
+
+%%%%% SAND BOX
+%
+%\xtokcycleenvironment\luastringAenv
+%  {\addcytoks{##1}}
+%  {\processtoks{##1}}
+%  {\addcytoks[1]{##1}}
+%  {\addcytoks{##1}}
+%  {}
+%  {\cytoks\expandafter{\expandafter\luastringO\expandafter{\the\cytoks}}}
+%
+%\def\luastringA#1{\luastringAenv#1\endluastringAenv}
+%\def\zzz{Hi Mom}
+%\NewDocumentCommand{\testcommand}{m}{%
+%  \luastringA{#1}  % this works as requested :)
+%%  \luadirect{texio.write_nl(\luastringA{#1}..' <<<')}
+% }
+%
+%\luastringA{Hmmm. \zzz.}
+%\testcommand{Hmmm. \zzz.}
+
+
+
+
+
+
+
+
+% todo why isnt this working???
+
+
+
+%
+
 %\pyth{} % erro
 
 
@@ -431,25 +547,27 @@
 %
 %  \THINg[color=blue,size=tiny]{Kale}
 %
-\begin{luacode*}
-function prttol()
-  local dec = penlight.tbls.tol[4] or 1
-  penlight.wrth(dec,'??')
-  penlight.tbls.tol[3] =  penlight.tbls.tol[3] or 3
-  penlight.tbls.tol[4] =  penlight.tbls.tol[1]*(1.0-penlight.tbls.tol[3]/100.0) + 0.0
-  penlight.tbls.tol[5] =  penlight.tbls.tol[1]*(1.0+penlight.tbls.tol[3]/100.0) + 0.0
-  --penlight.tbls.tol['k'] = 'fuckboi'
-  --ttt = pl.tbx.fmt(penlight.tbls.tol, '.3f')
-  penlight.wrth(('$1\\$2 (\\pmpct{$3} tolerance, $4\\ndash$5\\$2)'):fmt(penlight.tbls.tol, '4=.'..dec..'f, 5=.'..dec..'f'), 'XYZ')
-end
-\end{luacode*}
-\NewDocumentCommand{\prttol}{ m }{\tblfrcsv{tol}{#1}\luadirect{prttol()}}%  {50.0,kV,3,P}   % 50\us (\pmpct{20} tolerance, 40=--60\us), P is optional and precision of the range (number of decimals)
 
-\prttol{50,kV,3}
+%
+%\begin{luacode*}
+%function prttol()
+%  local dec = penlight.tbls.tol[4] or 1
+%  penlight.wrth(dec,'??')
+%  penlight.tbls.tol[3] =  penlight.tbls.tol[3] or 3
+%  penlight.tbls.tol[4] =  penlight.tbls.tol[1]*(1.0-penlight.tbls.tol[3]/100.0) + 0.0
+%  penlight.tbls.tol[5] =  penlight.tbls.tol[1]*(1.0+penlight.tbls.tol[3]/100.0) + 0.0
+%  --penlight.tbls.tol['k'] = 'fuckboi'
+%  --ttt = pl.tbx.fmt(penlight.tbls.tol, '.3f')
+%  penlight.wrth(('$1\\$2 (\\pmpct{$3} tolerance, $4\\ndash$5\\$2)'):fmt(penlight.tbls.tol, '4=.'..dec..'f, 5=.'..dec..'f'), 'XYZ')
+%end
+%\end{luacode*}
+%\NewDocumentCommand{\prttol}{ m }{\tblfrcsv{tol}{#1}\luadirect{prttol()}}%  {50.0,kV,3,P}   % 50\us (\pmpct{20} tolerance, 40=--60\us), P is optional and precision of the range (number of decimals)
+%
+%\prttol{50,kV,3}
+%
+%\begin{luacode*}
+%  pl.wrth(pl.filterfiles('.',true,'.*%.tex'), 'FF')
+%\end{luacode*}
 
-\begin{luacode*}
-  pl.wrth(pl.filterfiles('.',true,'.*%.tex'), 'FF')
-\end{luacode*}
 
-
 \end{document}
\ No newline at end of file

Modified: trunk/Master/texmf-dist/tex/luatex/penlightplus/penlightplus.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/penlightplus/penlightplus.lua	2024-09-30 20:11:22 UTC (rev 72425)
+++ trunk/Master/texmf-dist/tex/luatex/penlightplus/penlightplus.lua	2024-09-30 20:11:31 UTC (rev 72426)
@@ -1,5 +1,5 @@
 --% Kale Ewasiuk (kalekje at gmail.com)
---% 2024-08-17
+--% 2024-09-30
 --% Copyright (C) 2021-2024 Kale Ewasiuk
 --%
 --% Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -295,7 +295,7 @@
     s = s:delspace():upper():tolist()
     d = d:delspace():upper():tolist()
     for i, S in penlight.seq.enum(d:slice_assign(1,#s,s)) do
-        if (S == 'E') or (S == 'F') then S = '' end  -- E or F is fully expanded
+        if (S == 'F') then S = '' end  -- F is fully expanded
         penlight.tex.prtn('\\let\\plluastring'..penlight.Char(i)..'\\luastring'..S)
     end
 end
@@ -495,6 +495,85 @@
 
 
 
+
+
+
+
+
+
+
+-- -- -- -- -- -- -- -- -- -- -- --  functions below extend the seq module
+
+
+function penlight.seq.check_neg_index(i, len, fallback)
+i = tostring(i):delspace()
+if i == '' then return fallback end
+i = tonumber(i)
+if i == nil then
+  local _ = 1*'"Attempted to use seqstr indexing with negative number, but length of list not provided"'
+  return fallback -- fallback is the number to fall back on if i isn't provided
+end
+len = tonumber(len)
+if i < 0 then
+    if len == nil then
+      local _ = 1*'"Attempted to use seqstr indexing with negative number, but length of list not provided"'
+      return pl.utils.raise("Attempted to use seqstr indexing with negative number, but length of list not provided")
+    end
+  i = len + 1 + i -- negative index
+end
+return i
+end
+
+penlight.seq.train_element_sep = ','
+penlight.seq.train_range_sep = ':'
+
+function penlight.seq.train(s, len)
+    -- parse a range given a string indexer
+    -- syntax is: s = 'i1, i2, r1:r2'  where i1 and i2 are individual indexes.
+    -- r1:r2 is a range (inclusive).
+    -- a 'stride' can be given to ranges, eg. ::2 is 1,3,5,..., or 2::3 is 2,5,8,...
+    -- negative numbers can be used to index relative to the length of the table, eg, -1 -> len
+    -- if length is not given, negative indeing cannot be used
+    -- returns a penlight list of numbers
+
+    local t = penlight.List() -- list of indexes
+    local check_neg = penlight.seq.check_neg_index
+    for _, r in ipairs(s:split(penlight.seq.train_element_sep)) do
+      if r:find(penlight.seq.train_range_sep) then
+        r = r:split(penlight.seq.train_range_sep) -- if it's a range
+        t:extend(penlight.List.range(check_neg(r[1], len, 1),
+                               check_neg(r[2], len, len),
+                               tonumber(r[3])))
+      else
+        t:append(check_neg(r, len))
+      end
+    end
+    return t
+end
+
+function penlight.seq.itrain(s, len)
+-- iterator version of sequence-string
+    local t = penlight.seq.train(s, len)
+    local i = 0
+  return function ()
+      i = i + 1
+      if i <= #t then return t[i] end
+  end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 -- -- -- -- -- -- -- -- -- -- -- --  functions below extend the operator module
 
 function penlight.operator.strgt(a,b) return tostring(a) > tostring(b) end
@@ -517,8 +596,6 @@
 
 
 
-
-
 -- table stuff below
 
 function penlight.tablex.strinds(t) -- convert indices that are numbers to string indices
@@ -772,18 +849,30 @@
 penlight.tex.add_xspace_intext = true
 
 
-function penlight.tex.updatePDFtable(k, v, o) -- key val overwrite
-    k = k:upfirst()
-    if penlight.hasval(o) or (__PDFmetadata__[k] == nil) then
-        __PDFmetadata__[k] = v
+function penlight.tex.checkPDFkey(k)
+    k = k:delspace():upfirst()
+    local keys_allowed = 'Title Author Subject Date Language Keywords Publisher Copyright CopyrightURL Copyrighted Owner CertificateURL Coverage PublicationType Relation Source Doi ISBN URLlink Journaltitle Journalnumber Volume Issue Firstpage Lastpage CoverDisplayDate CoverDate Advisory BaseURL Identifier Nickname Thumbnails '
+    if not keys_allowed:find(k ..' ') then
+        penlight.tex.pkgerror('penlightplus', 'invalid PDF metadata key assigned "'..k..'"')
     end
+    return k
 end
 
+function penlight.tex.makePDFtablekv(kv)
+    local t_new = {}
+    for k, v in pairs(penlight.luakeys.parse(kv)) do
+       k = penlight.tex.checkPDFkey(k)
+       v = penlight.tex.makePDFvarstr(v)
+       t_new[k] = v
+    end
+    return t_new
+end
+
+
 penlight.tex.writePDFmetadata = function(t) -- write PDF metadata to xmpdata file
   t = t or __PDFmetadata__
   local str = ''
   for k, v in pairs(t) do
-    k = k:upfirst()
     str = str..'\\'..k..'{'..v..'}'..'\n'
   end
   penlight.utils.writefile(tex.jobname..'.xmpdata', str)
@@ -790,13 +879,9 @@
 end
 
 
-
-function penlight.tex.clear_cmds_str(s)
-    return s:gsub('%s+', ' '):gsub('\\\\',' '):gsub('\\%a+',''):gsub('{',' '):gsub('}',' '):gsub('%s+',' '):strip()
-end
-
 function penlight.tex.makePDFvarstr(s)
     s = s:gsub('%s*\\sep%s+','\0'):gsub('%s*\\and%s+','\0')  -- turn \and into \sep
+    -- todo preserve \%, \{, \}, \backslash, and \copyright
     s = penlight.tex.clear_cmds_str(s)
     s = s:gsub('\0','\\sep ')
     --penlight.tex.help_wrt(s,'PDF var string')
@@ -803,6 +888,10 @@
     return s
 end
 
+function penlight.tex.clear_cmds_str(s)
+    return s:gsub('%s+', ' '):gsub('\\\\',' '):gsub('\\%a+',''):gsub('{',' '):gsub('}',' '):gsub('%s+',' '):strip()
+end
+
 function penlight.tex.makeInTextstr(s)
     local s, c_and = s:gsub('%s*\\and%s+','\0')
     s = penlight.tex.clear_cmds_str(s)
@@ -878,6 +967,11 @@
 penlight.rec_tbl = ''
 penlight.rec_tbl_opts = {}
 
+
+function penlight.tbl(s)
+    return penlight.get_tbl_item(s)
+end
+
 function penlight.get_tbl_name(s)
     if s == '' then
         return penlight.rec_tbl
@@ -1042,116 +1136,3 @@
 end
 
 
-
-
--- graveyard
-
-    --_xTrue = penlight.tex._xTrue
-    --_xFalse = penlight.tex._xFalse
-    --_xNoValue = penlight.tex._xNoValue
-    --
-    --prt = penlight.tex.prt
-    --prtn = penlight.tex.prtn
-    --wrt = penlight.tex.wrt
-    --wrtn = penlight.tex.wrtn
-    --
-    --prtl = penlight.tex.prtl
-    --prtt = penlight.tex.prtt
-    --
-    --help_wrt = penlight.tex.help_wrt
-    --prt_array2d = penlight.tex.prt_array2d
-    --
-    --pkgwarn = penlight.tex.pkgwarn
-    --pkgerror = penlight.tex.pkgerror
-    --
-    --defcmd = penlight.tex.defcmd
-    --prvcmd = penlight.tex.prvcmd
-    --newcmd = penlight.tex.newcmd
-    --renewcmd = penlight.tex.renewcmd
-    --deccmd = penlight.tex.deccmd
-    --
-    --_NumBkts = penlight.tex._NumBkts
-    --opencmd = penlight.tex.opencmd
-    --reset_bkt_cnt = penlight.tex.reset_bkt_cnt
-    --add_bkt_cnt = penlight.tex.add_bkt_cnt
-    --close_bkt_cnt = penlight.tex.close_bkt_cnt
-
-
--- graveyard
-
-
--- luakeys parses individual keys as ipairs, this changes the list to a pure map
---function penlight.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 = penlight.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 penlight.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 penlight.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 penlight.seq.range(i1,i2) do
-    --    for j in penlight.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 = penlight.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
-

Modified: trunk/Master/texmf-dist/tex/luatex/penlightplus/penlightplus.sty
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/penlightplus/penlightplus.sty	2024-09-30 20:11:22 UTC (rev 72425)
+++ trunk/Master/texmf-dist/tex/luatex/penlightplus/penlightplus.sty	2024-09-30 20:11:31 UTC (rev 72426)
@@ -1,5 +1,5 @@
 % Kale Ewasiuk (kalekje at gmail.com)
-% 2024-08-17
+% 2024-09-30
 % Copyright (C) 2021-2024 Kale Ewasiuk
 %
 % Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -22,13 +22,15 @@
 % OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
 % OR OTHER DEALINGS IN THE SOFTWARE.
 
-\ProvidesPackage{penlightplus}[2024-08-17]
+\ProvidesPackage{penlightplus}[2024-09-30]
 
 \RequirePackage{luacode}
 \RequirePackage{luakeys}
 \RequirePackage[import]{penlight}
 \RequirePackage{etoolbox}
+\RequirePackage{tokcycle}
 
+
 \DeclareOption{globals}{\luadirect{__PL_GLOBALS__ = true}}
 \DeclareOption{pl}{\directlua{pl = penlight}}
 \ProcessOptions*\relax
@@ -40,17 +42,17 @@
 
 \global\newcommand{\writePDFmetadata}{\luadirect{penlight.tex.writePDFmetadata()}}
 
-\NewDocumentCommand{\writePDFmetadatakv}{ s m }{
+\NewDocumentCommand{\writePDFmetadatakv}{ s O{f} m }{%
+\MakeluastringCommands[f]{#2}%
 \IfBooleanTF{#1}{% if *, overwrite everything
   \luadirect{
-    __PDFmetadata__ = penlight.luakeys.parse(\luastring{#2})
-      penlight.tex.writePDFmetadata()
+    __PDFmetadata__ = penlight.tex.makePDFtablekv(\plluastringA{#3})
   }}{
     \luadirect{
     __PDFmetadata__ = __PDFmetadata__ or {}
-    penlight.tablex.update(__PDFmetadata__, penlight.luakeys.parse(\luastring{#2}))
-    penlight.tex.writePDFmetadata()
-  }}
+    penlight.tablex.update(__PDFmetadata__, penlight.tex.makePDFtablekv(\plluastringA{#3}))
+  }}%
+  \writePDFmetadata{}%
 }
 
 
@@ -57,6 +59,20 @@
 \gdef\luastringT#1{\luastring{\unexpanded\expandafter\expandafter\expandafter{#1}}}  % expand luastring twice
 \global\let\luastringF\luastring  % fully expanded luastring
 
+
+\xtokcycleenvironment\luastringeenv
+  {\addcytoks{##1}}
+  {\processtoks{##1}}
+  {\addcytoks[1]{##1}}
+  {\addcytoks{##1}}
+  {}
+  {\cytoks\expandafter{\expandafter\luastringO\expandafter{\the\cytoks}}}
+
+\def\luastringE#1{\luastringeenv#1\endluastringeenv}
+%\gdef\luastringE#1{\begin{luastringeenv#1\endluastringeenv}
+
+
+
 % allow control over expansion of arguments to a latex function
 \NewDocumentCommand{\MakeluastringCommands}{O{} m }{% #1 the desired commands #2 defaults
   \luadirect{penlight.tex.aliasluastring(\luastring{#2},\luastring{#1})}%
@@ -146,6 +162,13 @@
   table.insert(penlight.tbls[__tbl__], \luastring{#2})
 }}
 
+
+\NewDocumentCommand{\tblappN}{m m}{\luadirect{% append to a table (ie using integer index)  with a value (second arg) # todo option for string or number
+  __tbl__ = penlight.get_tbl_name(\luastring{#1})
+  table.insert(penlight.tbls[__tbl__], \luastringN{#2})
+}}
+
+
 \NewDocumentCommand{\tblcon}{m m}{\luadirect{% concatenate to a table (ie using integer index)  with a  list of comma separated values (second arg) #
   __tbl__ = penlight.get_tbl_name(\luastring{#1})
   for k, v in ipairs(penlight.luakeys.parse(string.subpar(\luastring{#2}), {naked_as_value=true})) do
@@ -153,6 +176,14 @@
   end
 }}
 
+
+\NewDocumentCommand{\tblconN}{m m}{\luadirect{% concatenate to a table (ie using integer index)  with a  list of comma separated values (second arg) #
+  __tbl__ = penlight.get_tbl_name(\luastring{#1})
+  for k, v in ipairs(penlight.luakeys.parse(string.subpar(\luastringN{#2}), {naked_as_value=true})) do
+    table.insert(penlight.tbls[__tbl__], v)
+  end
+}}
+
 \NewDocumentCommand{\tbladd}{m m}{\luadirect{% add a kv pair to a table
   __tbl__, __key__ = penlight.get_tbl_index(\luastring{#1}, true)
   penlight.tbls[__tbl__][__key__] = \luastring{#2}
@@ -179,7 +210,11 @@
   penlight.set_tbl_item(\luastring{#1}, \luastring{#2})
 }}
 
+\NewDocumentCommand{\tblsetN}{m m}{\luadirect{% set item with {value}
+  penlight.set_tbl_item(\luastring{#1}, \luastringN{#2})
+}}
 
+
 \NewDocumentCommand{\tbldef}{ m m }{\luadirect{penlight.def_tbl(\luastring{#1}, \luastring{#2})}}
 
 % define a table, use * to make global definition
@@ -211,11 +246,3 @@
   penlight.tbls[__tbl__][\luastring{#2}] = \luastringN{#3}
 }}
 
-\let\chgtbl\tblchg
-\let\newtbl\tblnew
-\let\gettbl\tblget
-\let\settbl\tblset
-\let\deftbl\tbldef
-\let\gdeftbl\tblgdef
-\let\iftbl\tblif
-\let\iftblv\tblifv
\ No newline at end of file



More information about the tex-live-commits mailing list.