summaryrefslogtreecommitdiff
path: root/macros/luatex
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex')
-rw-r--r--macros/luatex/latex/luatruthtable/README.txt9
-rw-r--r--macros/luatex/latex/luatruthtable/luatruthtable.bib20
-rw-r--r--macros/luatex/latex/luatruthtable/luatruthtable.pdfbin0 -> 119179 bytes
-rw-r--r--macros/luatex/latex/luatruthtable/luatruthtable.sty286
-rw-r--r--macros/luatex/latex/luatruthtable/luatruthtable.tex358
-rw-r--r--macros/luatex/latex/piton/README.md26
-rw-r--r--macros/luatex/latex/piton/piton-french.pdfbin0 -> 151124 bytes
-rw-r--r--macros/luatex/latex/piton/piton-french.tex361
-rw-r--r--macros/luatex/latex/piton/piton.dtx810
-rw-r--r--macros/luatex/latex/piton/piton.ins47
-rw-r--r--macros/luatex/latex/piton/piton.lua473
-rw-r--r--macros/luatex/latex/piton/piton.pdfbin0 -> 223287 bytes
12 files changed, 2390 insertions, 0 deletions
diff --git a/macros/luatex/latex/luatruthtable/README.txt b/macros/luatex/latex/luatruthtable/README.txt
new file mode 100644
index 0000000000..60217b2ce6
--- /dev/null
+++ b/macros/luatex/latex/luatruthtable/README.txt
@@ -0,0 +1,9 @@
+# Introduction
+The luatruthtable package is developed to generate Truth Tables of boolean values in LaTeX. It provides an easy way for generating truth tables in LaTeX . There is no need of special environment in the package for generation of Truth Tables. It is written in lua and tex file is to be compiled with LuaLatex engine. The time required for operations is no issue while compiling with LuaLaTeX. There is no need to install lua on users system as tex distributions (TeXLive or MikTeX) come bundled with LuaLaTeX. It is useful for generation of Truth Tables in tex file itself. The package supports nesting of commands for multiple operations. It can be modified or extended by writing custom lua programs.
+
+# License
+The luatruthtable package is released under the LaTeX Project Public License v1.3c or later. The complete license text is available at http://www.latex-project.org/lppl.txt.
+It is developed in lua. Lua is certified open source software available. Its license is simple and liberal which is compatible with GPL.
+
+#Installation and Inclusion
+The installation of luatruthtable package is similar to plain latex package where luatruthtable.sty file is in LaTeX directory of texmf tree. The package can be used by including the command \usepackage{luatruthtable} in the preamble of latex document.The tex file is to be compiled using the LuaLaTeX engine. \ No newline at end of file
diff --git a/macros/luatex/latex/luatruthtable/luatruthtable.bib b/macros/luatex/latex/luatruthtable/luatruthtable.bib
new file mode 100644
index 0000000000..81ee09ad4d
--- /dev/null
+++ b/macros/luatex/latex/luatruthtable/luatruthtable.bib
@@ -0,0 +1,20 @@
+
+
+
+@online{online.latextruthtable,
+ title = {Macro for automating truth tables in LaTeX},
+ url = {https://tex.stackexchange.com/questions/505994},
+ note = {visited on 2022-02-22}
+}
+
+
+@online{online.luacustomoperator,
+ title = {Lua Custom Operator},
+ url = {http://lua-users.org/wiki/CustomOperators},
+ note = {visited on 2022-02-22}
+}
+
+
+
+
+
diff --git a/macros/luatex/latex/luatruthtable/luatruthtable.pdf b/macros/luatex/latex/luatruthtable/luatruthtable.pdf
new file mode 100644
index 0000000000..3e8a60bf51
--- /dev/null
+++ b/macros/luatex/latex/luatruthtable/luatruthtable.pdf
Binary files differ
diff --git a/macros/luatex/latex/luatruthtable/luatruthtable.sty b/macros/luatex/latex/luatruthtable/luatruthtable.sty
new file mode 100644
index 0000000000..1b940c48c9
--- /dev/null
+++ b/macros/luatex/latex/luatruthtable/luatruthtable.sty
@@ -0,0 +1,286 @@
+% luaset package
+% version 1.0
+% Licensed under LaTeX Project Public License v1.3c or later. The complete license text is available at http://www.latex-project.org/lppl.txt.
+%Authors: Chetan Shirore and Dr. Ajit Kumar
+
+\ProvidesPackage{luatruthtable}[1.0]
+\RequirePackage{xkeyval}
+\RequirePackage{amsmath}
+\RequirePackage{luacode}
+\begin{luacode*}
+local function toBinary(x,y)
+ y = y or math.max(1, select(2, math.frexp(x)))
+ local res = {}
+ for i = y, 1, -1 do
+ res[i] = math.fmod(x, 2)
+ x = math.floor((x - res[i]) / 2)
+ end
+ return res
+end
+
+local function _not(a)
+ if a ==0 then return 1
+ else return 0 end
+end
+
+local lognot = {}
+
+local not_mt= {
+ __mul = function(a,b)
+ return _not(b)
+
+ end
+}
+
+setmetatable(lognot, not_mt)
+_G.lognot = lognot
+
+local function _and(a, b)
+ if a == 1 and b == 1 then return 1
+ else return 0 end
+end
+
+local tmp1 = {}
+local logand = {}
+
+local and_mt= {
+ __mul = function(a,b)
+ if b==logand then
+ tmp1[1]=a
+ return tmp1
+ elseif a == tmp1 then
+ return _and(tmp1[1], b)
+ end
+ end
+}
+
+setmetatable(tmp1, and_mt)
+setmetatable(logand, and_mt)
+_G.logand = logand
+
+local function _or(a, b)
+ if a == 0 and b == 0 then return 0
+ else return 1 end
+end
+
+local tmp2 = {}
+local logor = {}
+
+local or_mt= {
+ __mul = function(a,b)
+ if b==logor then
+ tmp2[1]=a
+ return tmp2
+ elseif a == tmp2 then
+ return _or(tmp2[1], b)
+ end
+ end
+}
+
+setmetatable(tmp2, or_mt)
+setmetatable(logor, or_mt)
+_G.logor = logor
+
+local function _imp(a, b)
+ if a == 1 and b == 0 then return 0
+ else return 1 end
+end
+
+local tmp3 = {}
+local imp = {}
+
+local imp_mt= {
+ __mul = function(a,b)
+ if b==imp then
+ tmp3[1]=a
+ return tmp3
+ elseif a == tmp3 then
+ return _imp(tmp3[1], b)
+ end
+ end
+}
+
+setmetatable(tmp3, imp_mt)
+setmetatable(imp, imp_mt)
+_G.imp = imp
+
+local function _iff(a, b)
+ if a == b then return 1
+ else return 0 end
+end
+
+local tmp4 = {}
+local iff = {}
+
+local iff_mt= {
+ __mul = function(a,b)
+ if b==iff then
+ tmp4[1]=a
+ return tmp4
+ elseif a == tmp4 then
+ return _iff(tmp4[1], b)
+ end
+ end
+}
+
+setmetatable(tmp4, iff_mt)
+setmetatable(iff, iff_mt)
+_G.iff = iff
+
+local function _xor(a, b)
+ if a ~= b then return 1
+ else return 0 end
+end
+
+local tmp5 = {}
+local logxor = {}
+
+local xor_mt= {
+ __mul = function(a,b)
+ if b==logxor then
+ tmp5[1]=a
+ return tmp5
+ elseif a == tmp5 then
+ return _xor(tmp5[1], b)
+ end
+ end
+}
+
+setmetatable(tmp5, xor_mt)
+setmetatable(logxor, xor_mt)
+_G.logxor = logxor
+
+local function _nand(a, b)
+ if a ==1 and b == 1 then return 0
+ else return 1 end
+end
+
+local tmp6 = {}
+local lognand = {}
+
+local nand_mt= {
+ __mul = function(a,b)
+ if b==lognand then
+ tmp6[1]=a
+ return tmp6
+ elseif a == tmp6 then
+ return _nand(tmp6[1], b)
+ end
+ end
+}
+
+setmetatable(tmp6, nand_mt)
+setmetatable(lognand, nand_mt)
+_G.lognand = lognand
+
+local function _nor(a, b)
+ if a ==0 and b == 0 then return 1
+ else return 0 end
+end
+
+local tmp7 = {}
+local lognor = {}
+
+local nor_mt= {
+ __mul = function(a,b)
+ if b==lognor then
+ tmp7[1]=a
+ return tmp7
+ elseif a == tmp7 then
+ return _nor(tmp7[1], b)
+ end
+ end
+}
+
+setmetatable(tmp7, nor_mt)
+setmetatable(lognor, nor_mt)
+_G.lognor = lognor
+
+local function _xnor(a, b)
+ if a == b then return 1
+ else return 0 end
+end
+
+local tmp8 = {}
+local logxnor = {}
+
+local xnor_mt= {
+ __mul = function(a,b)
+ if b==logxnor then
+ tmp8[1]=a
+ return tmp8
+ elseif a == tmp8 then
+ return _xnor(tmp8[1], b)
+ end
+ end
+}
+
+setmetatable(tmp8, xnor_mt)
+setmetatable(logxnor, xnor_mt)
+_G.logxnor = logxnor
+
+function truthTable(str0,str,trtext,fltext)
+local eval=""
+local names={lognot=lognot,logand=logand,logor=logor, imp=imp,
+ iff=iff, logxor=logxor,lognand=lognand,lognor=lognor, logxnor=logxnor}
+local vars={}
+local expr={}
+local countexp = 1
+local countvars =1
+local res=""
+local sep=" & "
+trtext = trtext or "$T$"
+fltext = fltext or "$F$"
+for variables in string.gmatch(str0, '([^,]+)') do
+ vars[countvars] = variables
+ countvars = countvars + 1
+end
+
+for subexp in string.gmatch(str, '([^,]+)') do
+ expr[countexp] = subexp
+ countexp = countexp + 1
+end
+
+local n =#vars
+for i =1,2^n do
+ itr = toBinary(i,n)
+
+ for j=1, #itr do
+ names[vars[j]] = itr[j]
+end
+
+ for k = 1, #expr do
+ res= res ..sep.. load("return " .. expr[k],nil,"t",names)()
+ end
+if i~=2^n then
+eval = eval .. table.concat(toBinary(i,n)," & ") .. res .."\\\\"
+else
+eval = eval .. table.concat(toBinary(i,n)," & ") .. res
+end
+ res=""
+end
+
+if trtext:gsub("%s+", "") =="0" or trtext:gsub("%s+", "") == "$0$"
+or fltext:gsub("%s+", "") =="1" or fltext:gsub("%s+", "") == "$1$"
+then
+eval=eval
+else
+eval=eval:gsub(0,fltext):gsub(1,trtext)
+end
+return eval
+end
+
+\end{luacode*}
+
+% ========= KEY DEFINITIONS =========
+\define@key{luatruthtable}{trtext}{\def\luatrtbl@trtext{#1}}
+\define@key{luatruthtable}{fltext}{\def\luatrtbl@fltext{#1}}
+
+% ========= KEY DEFAULTS =========
+\setkeys{luatruthtable}{trtext=$T$,fltext=$F$}%
+% ========= Defining Command =========
+\newcommand{\luaTruthTable}[3][]{%
+ \setkeys{luatruthtable}{#1}
+ \directlua{tex.sprint(truthTable(\luastringN{#2},\luastringN{#3},'\luatrtbl@trtext','\luatrtbl@fltext'))}} %
+
+\endinput
diff --git a/macros/luatex/latex/luatruthtable/luatruthtable.tex b/macros/luatex/latex/luatruthtable/luatruthtable.tex
new file mode 100644
index 0000000000..f50267f6f8
--- /dev/null
+++ b/macros/luatex/latex/luatruthtable/luatruthtable.tex
@@ -0,0 +1,358 @@
+\documentclass{article}
+\usepackage{listings,color,parskip,booktabs,longtable,array,
+hyperref,multirow,multicol,luatruthtable, enumitem}
+\usepackage[top=1.1in, bottom=1.1in, left=1in, right=1in]{geometry}
+\hypersetup{colorlinks,urlcolor=blue}
+\lstset{frame=none,
+ language=[LaTeX]{TeX},
+ aboveskip=3mm,
+ belowskip=3mm,
+ showstringspaces=false,
+ columns=flexible,
+ basicstyle={\ttfamily},
+ numbers=none,
+ numberstyle=\tiny\color{gray},
+ stringstyle=\color{mauve},
+ breaklines=true,
+ breakatwhitespace=true,
+ tabsize=1
+}
+\usepackage[backend=bibtex]{biblatex}
+\addbibresource{luatruthtable}
+\begin{document}
+\title{luatruthtable Package}
+\author{Chetan Shirore and Dr. Ajit Kumar}
+\maketitle
+\section{luatruthtable Package}
+The \emph{luatruthtable} package is developed to generate Truth Tables of boolean values in LaTeX. It provides an easy way for generating truth tables in LaTeX . There is no need of special environment in the package for generation of Truth Tables. It is written in lua and tex file is to be compiled with LuaLatex engine. The time required for operations is no issue while compiling with LuaLaTeX. There is no need to install lua on users system as tex distributions (TeXLive or MikTeX) come bundled with LuaLaTeX. It is useful for generation of Truth Tables in tex file itself. The package supports nesting of commands for multiple operations. It can be modified or extended by writing custom lua programs.
+
+The progamming capabilities of Lua are effectively used in the development of pacakage. The other approaches of generating Truth Table in LaTeX get weired \cite{online.latextruthtable} and probably without using Lua it can't be done in an easier way in LaTeX. The \emph{xkeyval} package is used in its development apart from the \emph{luacode*} package.
+
+\section{License} The \emph{luatruthtable} package is released under the LaTeX Project Public License v1.3c or later. The complete license text is available at \url{http://www.latex-project.org/lppl.txt}.
+It is developed in lua. Lua is certified open source software available. Its license is simple and liberal which is compatible with GPL.
+\section{Installation and Inclusion}
+The installation of \emph{luatruthtable} package is similar to plain latex package where \texttt{.sty} file is in \LaTeX directory of texmf tree. The package can be used by including the command \texttt{\textbackslash usepackage\{luatruthtable\}} in the preamble of latex document. The tex file is to be compiled using the LuaLaTeX engine.
+\section{Core Ideas used in the development of the package} The function \verb|toBinary(x,y)| is used to produce sequence of \emph{True} and \emph{False} values of boolean variables. This function converts the decimal number \verb|x| to a binary number by adding \verb|y| number of leading zeroes. The result of this is stored in a table in Lua. Here \verb|y| corresponds to number of boolean variables. As \(2^y\) permutations of boolean variables are to be produced, the function \verb|toBinary(x,y)| runs inside a loop where \verb|x| takes values from \(1\) to \(y\). The splitting of variables and expressions is done using string methods available in Lua. The nested \emph{metamethods} in Lua are used to define several logical operators. The \emph{load} function in Lua is used to evaluate logical expressions.
+\section{Command luaTruthTable in luatruthtable package}
+The \verb|\luaTruthTable| command is the main command in the \emph{luatruthtable} package which generates truth tables. It has the following syntax.
+\begin{lstlisting}
+\luaTruthTable[trtext,fltext]{list of boolean / logical variables}{list of expressions}
+\end{lstlisting}
+The command has two mandatory arguments. \\
+i) \verb|list of boolean / logical variables| : The list of boolean or logical variables should be separated by comma. \\
+ii) \verb|list of expressions| : The list of logical expressions that are to be evaluated should be separated by comma. \\
+The command has two optional arguments. \\
+i) \verb|trtext| : The \verb|trtext| is the display value for the boolean value \emph{True}. It has the default value \verb|$T$| in the package. It can be any string or number. Assigning value \(0\) should be avoided to \verb|trtext| variable. \\
+ii) \verb|fltext| : The \verb|fltext| is the display value for the boolean value \emph{False}. It has the default value \verb|$F$| in the package. It can be any string or number. Assigning value \(1\) should be avoided to \verb|fltext| variable.
+
+The \verb|\luaTruthTable| command should be used within in the environment \verb|\begin{tabular} ... \end{tabular}| or any other environment in LaTeX for Tables. The sequence of column heads should be same as sequence of \verb|list of boolean / logical variables| and \verb|list of expressions|. Without these correct inputs, the command \verb|\luaTruthTable| can't produce the expected output.
+
+\section{Operations in luatruthtable package}
+\begin{enumerate}[label=\alph*)]
+\item \emph{not}: The value of \emph{ not p} is False when \(p\) is True and it is True when \(p\) is False.
+\begin{center}
+\begin{tabular}{|c|c|}
+\hline
+\(p\) & not \(p\) \\
+\hline
+\luaTruthTable{p}{lognot*p} \\
+\hline
+\end{tabular}
+\end{center}
+
+The command \verb|lognot*| is used in the package to generate truth table for \emph{not} operation.
+\item \emph{and}: The value of \emph{p AND q} is True if and only if both \(p\) and \(q\) are True.
+\begin{center}
+\begin{tabular}{|cc|c|}
+\hline
+\(p\) & \(q\) & \(p\) and \(q\) \\
+\hline
+\luaTruthTable{p,q}{p*logand*q} \\
+\hline
+\end{tabular}
+\end{center}
+The command \verb|*logand*| is used in the package to generate truth table for \emph{and} operation .
+\item \emph{or}: The value of \emph{p or q} is False if and only if both \(p\) and \(q\) are False.
+\begin{center}
+\begin{tabular}{|cc|c|}
+\hline
+\(p\) & \(q\) & \(p\) or \(q\) \\
+\hline
+\luaTruthTable{p,q}{p*logor*q} \\
+\hline
+\end{tabular}
+\end{center}
+The command \verb|*logor*| is used in the package to generate truth table for \emph{or} operation.
+\item \emph{implies}: The value of \emph{p implies q} is False if and only if \(p\) is True and \(q\) is False.
+\begin{center}
+\begin{tabular}{|cc|c|}
+\hline
+\(p\) & \(q\) & \(p\) implies \(q\) \\
+\hline
+\luaTruthTable{p,q}{p*imp*q} \\
+\hline
+\end{tabular}
+\end{center}
+
+The command \verb|*imp*| is used in the package to generate truth table for \emph{implies} operation.
+\item \emph{if and only if} : The value of \emph{p if and only if q} is True if and only if both \(p\) and \(q\) have same truth values.
+\begin{center}
+\begin{tabular}{|cc|c|}
+\hline
+\(p\) & \(q\) & \(p\) iff \(q\) \\
+\hline
+\luaTruthTable{p,q}{p*iff*q} \\
+\hline
+\end{tabular}
+\end{center}
+
+The command \verb|*iff*| is used in the package to generate truth table for \emph{if and only if} operation.
+\item \emph{NAND} : The value of \emph{p NAND q} is \(0\) if and only if both \(p\) and \(q\) have value \(1\).
+\begin{center}
+\begin{tabular}{|cc|c|}
+\hline
+\(p\) & \(q\) & \(p\) NAND \(q\) \\
+\hline
+\luaTruthTable[trtext=$1$,fltext=$0$]{p,q}{p*lognand*q} \\
+\hline
+\end{tabular}
+\end{center}
+
+The command \verb|*lognand*| is used in the package to generate truth table for \emph{NAND} operation.
+\item \emph{XOR} : The value of \emph{p XOR q} is \(0\) if and only if \(p\) and \(q\) have same values.
+\begin{center}
+\begin{tabular}{|cc|c|}
+\hline
+\(p\) & \(q\) & \(p\) XOR \(q\) \\
+\hline
+\luaTruthTable[trtext=$1$,fltext=$0$]{p,q}{p*logxor*q} \\
+\hline
+\end{tabular}
+\end{center}
+
+
+The command \verb|*logxor*| is used in the package to generate truth table for \emph{XOR} operation.
+\item \emph{NOR}: The value of \emph{p NOR q} is \(1\) if and only if both \(p\) and \(q\) have value \(0\).
+\begin{center}
+\begin{tabular}{|cc|c|}
+\hline
+\(p\) & \(q\) & \(p\) NOR \(q\) \\
+\hline
+\luaTruthTable[trtext=$1$,fltext=$0$]{p,q}{p*lognor*q} \\
+\hline
+\end{tabular}
+\end{center}
+
+The command \verb|*lognor*| is used in the package to generate truth table for \emph{NOR} operation.
+\item \emph{XNOR}: The value of \emph{p XNOR q} is \(1\) if and only if both \(p\) and \(q\) have same values.
+\begin{center}
+\begin{tabular}{|cc|c|}
+\hline
+\(p\) & \(q\) & \(p\) XNOR \(q\) \\
+\hline
+\luaTruthTable[trtext=$1$,fltext=$0$]{p,q}{p*logxnor*q} \\
+\hline
+\end{tabular}
+\end{center}
+
+The command \verb|*logxnor*| is used in the package to generate truth table for \emph{XNOR} operation.
+\end{enumerate}
+The following table summarises logical operators in the package.
+\begin{center}
+\begin{longtable}{llm{8cm}}
+\toprule
+\multicolumn{1}{c}{\textcolor{blue}{Operator}} & \multicolumn{1}{l}{\textcolor{blue}{Syntax}} & \multicolumn{1}{c}{\textcolor{blue}{Description}} \\
+\toprule
+\begin{lstlisting}
+lognot*
+\end{lstlisting} &
+\begin{lstlisting}
+lognot*p
+\end{lstlisting} & Negates the boolean variable \(p\)\\
+\midrule
+\begin{lstlisting}
+*logand*
+\end{lstlisting} &
+\begin{lstlisting}
+p*logand*q
+\end{lstlisting} & Gives the truth of the expression \emph{p and q} for boolean variables \(p\) and \(q\).\\
+\midrule
+\begin{lstlisting}
+*logor*
+\end{lstlisting} &
+\begin{lstlisting}
+p*logor*q
+\end{lstlisting} & Gives the truth of the expression \emph{p or q} for boolean variables \(p\) and \(q\).\\
+\midrule
+\begin{lstlisting}
+*imp*
+\end{lstlisting} &
+\begin{lstlisting}
+p*imp*q
+\end{lstlisting} & Gives the truth of the expression \emph{if p then q} for boolean variables \(p\) and \(q\).\\
+\midrule
+\begin{lstlisting}
+*iff*
+\end{lstlisting} &
+\begin{lstlisting}
+p*iff*q
+\end{lstlisting} & Gives the truth of the expression \emph{p if and only if q} for boolean variables \(p\) and \(q\).\\
+\midrule
+\begin{lstlisting}
+*lognand*
+\end{lstlisting} &
+\begin{lstlisting}
+p*lognand*q
+\end{lstlisting} & Gives the truth of the expression \emph{ p NAND q} for boolean variables \(p\) and \(q\).\\
+\midrule
+\begin{lstlisting}
+*logxor*
+\end{lstlisting} &
+\begin{lstlisting}
+p*logxor*q
+\end{lstlisting} & Gives the truth of the expression \emph{ p XOR q} for boolean variables \(p\) and \(q\).\\
+\midrule
+\begin{lstlisting}
+*lognor*
+\end{lstlisting} &
+\begin{lstlisting}
+p*lognor*q
+\end{lstlisting} & Gives the truth of the expression \emph{ p NOR q} for boolean variables \(p\) and \(q\).\\
+\midrule
+\begin{lstlisting}
+*logxnor*
+\end{lstlisting} &
+\begin{lstlisting}
+p*logxnor*q
+\end{lstlisting} & Gives the truth of the expression \emph{ p XNOR q} for boolean variables \(p\) and \(q\).\\
+
+\bottomrule
+\end{longtable}
+\end{center}
+
+\section{Examples and Usage} The \emph{luatruthtable} package can accept finite number of variables. It supports finite number of variables that one would practically need. Few examples of usage are given here.
+\begin{lstlisting}
+\begin{tabular}{|cc|c|c|c|c|c|c|c|c|c|}
+\hline
+\(p\) & \(q\) & \(\neg p\) & \(p \land q\) & \(p\lor q\) & \(p \rightarrow q\)
+ & \(p \leftrightarrow q\) & \( p\) nand \(q\) & \(p\) xor \(q\) & \( p\) nor \(q\) & \(p\) xnor \(q\) \\
+\hline
+\luaTruthTable{p,q}{lognot*p,p*logand*q, p*logor*q, p*imp*q, p*iff*q,
+p*lognand*q, p*logxor*q, p*lognor*q, p*logxnor*q } \\
+\hline
+\end{tabular}
+\end{lstlisting}
+With the packages \emph{luatruthtable},the above code outputs to
+\ \\ \ \\
+\begin{tabular}{|cc|c|c|c|c|c|c|c|c|c|}
+\hline
+\(p\) & \(q\) & \(\neg p\) & \(p \land q\) & \(p\lor q\) & \(p \rightarrow q\)
+ & \(p \leftrightarrow q\) & \( p\) nand \(q\) & \(p\) xor \(q\) & \( p\) nor \(q\) & \(p\) xnor \(q\) \\
+\hline
+\luaTruthTable{p,q}{lognot*p,p*logand*q, p*logor*q, p*imp*q, p*iff*q,
+p*lognand*q, p*logxor*q, p*lognor*q, p*logxnor*q } \\
+\hline
+\end{tabular}
+\ \\ \\
+The following is the code generated by the command \verb|\luaTruthTable| in above code.
+ \begin{lstlisting}
+$F$ & $T$ & $T$ & $F$ & $T$ & $T$ & $F$ & $T$ & $T$ & $F$ & $F$\\
+$T$ & $F$ & $F$ & $F$ & $T$ & $F$ & $F$ & $T$ & $T$ & $F$ & $F$\\
+$T$ & $T$ & $F$ & $T$ & $T$ & $T$ & $T$ & $F$ & $F$ & $F$ & $T$\\
+$F$ & $F$ & $T$ & $F$ & $F$ & $T$ & $T$ & $T$ & $F$ & $T$ & $T$
+ \end{lstlisting}
+ The following example illustrates the use use of \emph{trtext} and \emph{fltext}. Here \(0\) is assigned to \emph{trtext} and \(1\) is assigned to \emph{fltext}.
+ \begin{lstlisting}
+ \begin{tabular}{|cc|c|c|c|c|c|c|c|c|c|}
+\hline
+\(p\) & \(q\) & \(\neg p\) & \(p \land q\) & \(p\lor q\) & \(p \rightarrow q\)
+ & \(p \leftrightarrow q\) & \( p\) nand \(q\) & \(p\) xor \(q\) & \( p\) nor \(q\) & \(p\) xnor \(q\) \\
+\hline
+\luaTruthTable[trtext=$1$,fltext=$0$]{p,q}{lognot*p,p*logand*q, p*logor*q, p*imp*q, p*iff*q,
+p*lognand*q, p*logxor*q, p*lognor*q, p*logxnor*q } \\
+\hline
+\end{tabular}
+ \end{lstlisting}
+
+ With the packages \emph{luatruthtable},the above code outputs to
+\ \\ \ \\
+ \begin{tabular}{|cc|c|c|c|c|c|c|c|c|c|}
+\hline
+\(p\) & \(q\) & \(\neg p\) & \(p \land q\) & \(p\lor q\) & \(p \rightarrow q\)
+ & \(p \leftrightarrow q\) & \( p\) nand \(q\) & \(p\) xor \(q\) & \( p\) nor \(q\) & \(p\) xnor \(q\) \\
+\hline
+\luaTruthTable[trtext=$1$,fltext=$0$]{p,q}{lognot*p,p*logand*q, p*logor*q, p*imp*q, p*iff*q,
+p*lognand*q, p*logxor*q, p*lognor*q, p*logxnor*q } \\
+\hline
+\end{tabular}
+\ \\ \\
+The following is the code generated by the command \verb|\luaTruthTable| in above code.
+\begin{lstlisting}
+$0$ & $1$ & $1$ & $0$ & $1$ & $1$ & $0$ & $1$ & $1$ & $0$ & $0$\\
+$1$ & $0$ & $0$ & $0$ & $1$ & $0$ & $0$ & $1$ & $1$ & $0$ & $0$\\
+$1$ & $1$ & $0$ & $1$ & $1$ & $1$ & $1$ & $0$ & $0$ & $0$ & $1$\\
+$0$ & $0$ & $1$ & $0$ & $0$ & $1$ & $1$ & $1$ & $0$ & $1$ & $1$
+\end{lstlisting}
+The following example involves three variables.
+\begin{lstlisting}
+\begin{tabular}{|ccc|c|}
+\hline
+\(p\) & \(q\) & \(r\) & \((p \land q)\) \rightarrow \(\neg r\) \\
+\hline
+\luaTruthTable{p,q,r}{(p*logand*q) *imp* (lognot*r)} \\
+\hline
+\end{tabular}
+\end{lstlisting}
+ With the packages \emph{luatruthtable},the above code outputs to
+\ \\ \ \\
+\begin{tabular}{|ccc|c|}
+\hline
+\(p\) & \(q\) & \(r\) & \((p \land q)\) \rightarrow \(\neg r\) \\
+\hline
+\luaTruthTable{p,q,r}{(p*logand*q) *imp* (lognot*r)} \\
+\hline
+\end{tabular}
+\ \\ \\
+Here \emph{lognot*r} should be enclosed in parenthesis in order to produce correct results in generated truth table.
+\ \\
+The following is the code generated by the command \verb|\luaTruthTable| in above code.
+\begin{lstlisting}
+$F$ & $F$ & $T$ & $T$\\
+$F$ & $T$ & $F$ & $T$\\
+$F$ & $T$ & $T$ & $T$\\
+$T$ & $F$ & $F$ & $T$\\
+$T$ & $F$ & $T$ & $T$\\
+$T$ & $T$ & $F$ & $T$\\
+$T$ & $T$ & $T$ & $F$\\
+$F$ & $F$ & $F$ & $T$
+\end{lstlisting}
+With the use of optional arguments \verb|[trtext=True, fltext=False]| in the previous example, one gets the following output.
+\ \\ \ \\ \ \\
+\begin{tabular}{|ccc|c|}
+\hline
+\(p\) & \(q\) & \(r\) & \((p \land q)\) \rightarrow \(\neg r\) \\
+\hline
+\luaTruthTable[trtext=True, fltext=False]{p,q,r}{(p*logand*q) *imp* (lognot*r)} \\
+\hline
+\end{tabular}
+\ \\ \\
+
+It is possible to input \emph{trtext} and \emph{trfalse} in mathematics environment. So with the use of optional arguments \verb|[trtext=$True$, fltext=$False$]| in the previous example, one gets the following output.
+\ \\ \ \\ \ \\
+\begin{tabular}{|ccc|c|}
+\hline
+\(p\) & \(q\) & \(r\) & \((p \land q)\) \rightarrow \(\neg r\) \\
+\hline
+\luaTruthTable[trtext=$True$, fltext=$False$]{p,q,r}{(p*logand*q) *imp* (lognot*r)} \\
+\hline
+\end{tabular}
+\ \\ \ \\ \ \\
+Since \emph{luacode*} package is used, the backslash is to be escaped while assigning values to \emph{trtext} and \emph{trfalse}. For example \verb|[trtext=\\(True\\), fltext=\\(False\\)]|
+
+
+\section{Known Issues,Limitations and Scope of the package} The associativity and precedence of operator is not yet supported. The package can give appropriate results only when parentheses are used for each of the operation. It gives eraneous result when parentheses are not used. This point is of utmost importance in using the package. These issues are there is no native way of defining custom operations in Lua \cite{online.luacustomoperator}. However some metamethods can be nested in a way to glimpse the operators. All operators defined in this package are instances of such nestings. The question may be raised that is there better way of accomplishing this in Lua. The answer to the point is that there are alternative ways of doing this. They may be better in some or other sense. For example, instead of defining \emph{*logand*} operator and using it in the fashion \emph{p*logand*q}, one could define function \emph{logand} that takes two arguments and use it in a way \emph{logand(p,q)}. But when it comes to embedding it in LaTeX, again one has to use more and more nested parentheses as number of statements and operations increase. This is the exact reason why such approach is not used in the development of package. Instead of using \emph{implies(logand(p,logor(q,r)),s)} it sounds more natural to use \emph{(p *logand* (q*logor*r) )*implies* s}.
+
+Apart from these issues, there is no error handling mechanism used in the package. It relies on the error handling of Lua and TeX itself. The package currently supports 9 operations viz. \emph{not,and,nand,or, xor, implies, iff, nor, xnor}. The error handling and extending number of operations may be considered in future versions of the package.
+
+\printbibliography
+\end{document}
diff --git a/macros/luatex/latex/piton/README.md b/macros/luatex/latex/piton/README.md
new file mode 100644
index 0000000000..c9ad487bcc
--- /dev/null
+++ b/macros/luatex/latex/piton/README.md
@@ -0,0 +1,26 @@
+# Readme for the package piton
+
+Author: F. Pantigny (`fpantigny@wanadoo.fr`).
+
+CTAN page: `https://ctan.org/pkg/piton`
+
+## License
+The LaTeX extension `piton` is distributed under the LPPL 1.3 license.
+
+## Presentation
+
+The LaTeX package `piton` provides a command `\piton` and an environment `{Piton}` to typeset Python codes by using the Lua library LPEG. It requires the use of `lualatex`. It won't work with `xelatex` nor `pdflatex`.
+
+
+
+## Installation
+
+
+For a manual installation:
+
+* put the files `piton.ins` and `piton.dtx` in the same directory;
+* run `latex piton.ins` in that directory.
+
+The file `piton.sty` will be generated.
+
+The file `piton.sty` is *not* the only file necessary to use the extension `piton`. The file `piton.lua` is also required. You have to put both in the same directory as your document or (best) in a `texmf` tree.
diff --git a/macros/luatex/latex/piton/piton-french.pdf b/macros/luatex/latex/piton/piton-french.pdf
new file mode 100644
index 0000000000..ef7a5a1964
--- /dev/null
+++ b/macros/luatex/latex/piton/piton-french.pdf
Binary files differ
diff --git a/macros/luatex/latex/piton/piton-french.tex b/macros/luatex/latex/piton/piton-french.tex
new file mode 100644
index 0000000000..5e9ee11c7a
--- /dev/null
+++ b/macros/luatex/latex/piton/piton-french.tex
@@ -0,0 +1,361 @@
+% -*- coding: utf-8 ; -*-
+\documentclass[dvipsnames]{article}
+\usepackage[french]{babel}
+\frenchsetup{og = « , fg = »}
+
+\usepackage[escape-inside=$$]{piton}
+
+\usepackage{xcolor}
+
+\usepackage{geometry}
+\geometry{left=2.8cm,right=2.8cm,top=2.5cm,bottom=2.5cm,papersize={21cm,29.7cm}}
+
+\usepackage{enumitem}
+\usepackage{verbatim}
+\usepackage{amsmath}
+\usepackage{tabularx}
+\usepackage{booktabs}
+
+\usepackage{caption}
+\captionsetup{labelfont = bf}
+
+% We use \MakeShortVerb of shortvrb and not \DefineShortVerb of fancyvrb
+% because we don't want the contents of short verbatim colored in gray
+\usepackage{shortvrb}
+\MakeShortVerb{\|}
+
+
+\skip\footins = 2\bigskipamount
+
+\usepackage{fancyvrb}
+\fvset{commandchars=\~\#\@,formatcom=\color{gray}}
+\def\emphase{\bgroup\color{RoyalPurple}\let\next=}
+
+
+\usepackage{titlesec}
+\titlespacing*{\section}{0pt}{6.5ex plus 1ex minus .2ex}{4.3ex plus .2ex}
+\titlespacing*{\subsection}{0pt}{4.5ex plus 1ex minus .2ex}{2ex plus .2ex}
+
+\def\interitem{\vspace{7mm plus 2 mm minus 3mm}}
+
+
+\usepackage{footnote}
+
+\usepackage[hyperfootnotes = false]{hyperref}
+
+\hypersetup
+ {
+ pdfinfo =
+ {
+ Title = L’extension piton ,
+ Subject = Une extension LaTeX ,
+ Author = F. Pantigny
+ }
+ }
+
+
+\NewDocumentEnvironment {scope} {} {} {}
+
+\NewDocumentCommand {\pkg} {m} {\textsf{#1}}
+\NewDocumentCommand {\cls} {m} {\textsf{#1}}
+
+\setlength{\parindent}{0pt}
+
+
+\begin{document}
+
+\VerbatimFootnotes
+
+
+\title{L'extension LaTeX \pkg{piton}\thanks{Ce document correspond à la
+version~\myfileversion\space de \pkg{piton}, à la date du~\myfiledate.}}
+\author{F. Pantigny \\ \texttt{fpantigny@wanadoo.fr}}
+
+\maketitle
+
+\begin{abstract}
+L'extension \pkg{piton} propose des outils pour composer du code Python avec une coloration syntaxique
+en utilisant la bibliothèque Lua LPEG. L'extension \pkg{piton} nécessite l'emploi de LuaLaTeX.
+\end{abstract}
+
+\section{Présentation}
+
+L'extension \pkg{piton} utilise la librarie Lua nommée LPEG\footnote{LPEG est une librairie de capture de motifs
+ (\emph{pattern-matching} en anglais) pour Lua, écrite en C, fondée sur les PEG (\emph{parsing expression
+ grammars}): \url{http://www.inf.puc-rio.br/~roberto/lpeg/}} pour «parser» le code Python et le composer avec un
+coloriage syntaxique. Comme elle utilise du code Lua, elle fonctionne uniquement avec |lualatex| (et ne va pas
+fonctionner avec les autres moteurs de compilation LaTeX, que ce soit |latex|, |pdflatex| ou |xelatex|). Elle
+n'utilise aucun programme extérieur et la compilation ne requiert donc pas |--shell-escape|. La compilation est
+très rapide puisque tout le travail du parseur est fait par la librairie LPEG, écrite en C.
+
+\bigskip
+Voici un exemple de code Python composé avec l'environnement |{Piton}| proposé par \pkg{piton}.
+
+\bigskip
+\begin{Piton}
+from math import pi
+
+def arctan(x,n=10):
+ """Compute the value of arctan(x)
+ n is the number of terms if the sum"""
+ if x < 0:
+ return -arctan(-x) # recursive call
+ elif x > 1:
+ return pi/2 - arctan(1/x)
+ ## (on a utilisé le fait que $\arctan(x)+\arctan(1/x)=\frac{\pi}{2}$ pour $x>0$)\footnote{Cet échappement vers LaTeX a été obtenu en débutant par \ttfamily\#\#.}
+ else
+ s = 0
+ for k in range(n):
+ s += (-1)**k/(2*k+1)*x**(2*k+1)
+ return s
+\end{Piton}
+
+
+
+\section{Installation}
+
+L'extension \pkg{piton} est composée de deux fichiers : |piton.sty| et |piton.lua| (le fichier LaTeX |piton.sty|
+chargé par |\usepackage| va à son tour charger le fichier |piton.lua|). Les deux fichiers doivent être présents
+dans un répertoire où LaTeX pourra les trouver. Le mieux est de les installer dans une arborescence |texmf|.
+
+
+\section{Utilisation de l'extension}
+
+Pour utiliser l'extension \pkg{piton}, l'utilisateur final a seulement à charger l'extension dans son document avec
+la commande classique |\usepackage| et se souvenir que la compilation doit être faite avec LuaLaTeX.
+
+\medskip
+L'extension \pkg{piton} fournit trois outils pour composer du code Python: la commande |\piton|, l'environnement
+|{Piton}| et la commande |\PitonInputFile|.
+
+\begin{itemize}
+\item La commande |\piton| doit être utilisée pour composer de petits éléments de code à l'intérieur d'un
+paragraphe. \emph{Attention} : Cette fonction prend son argument en mode \emph{verbatim} (comme la commande
+\verb|\verb|) et, de ce fait, cette fonction ne peut pas être utilisée à l'intérieur d'un argument d'une autre
+fonction (on peut néanmoins l'utiliser à l'intérieur d'un environnement).
+
+\item L'environnement |{Piton}| doit être utilisé pour composer des codes de plusieurs lignes.
+
+\item La commande |\PitonInputFile| doit être utilisée pour insérer et composer un fichier extérieur.
+\end{itemize}
+
+\bigskip
+Il est possible de composer des commentaires en LaTeX en commençant par |##| (c'est un échappement vers LaTeX). Les
+caractères |##| eux-mêmes ne seront pas imprimés.
+
+
+\section{Personnalisation}
+
+\subsection{La commande \textbackslash PitonOptions}
+
+La commande |\PitonOptions| propose quatre clés : |gobble|, |auto-gobble|, |line-numbers| et |all-line-numbers|.
+
+\begin{itemize}
+\item La clé |gobble| peut comme valeur un entier positif $n$ : les $n$ premiers caractères de chaque ligne sont
+alors retirés (avant formatage du code) dans les environnements |{Piton}|.
+
+\item Quand la clé |auto-gobble| est activée, l'extension \pkg{piton} détermine la valeur minimale $n$ du nombre
+d'espaces successifs débutant chaque ligne (non vide) de l'environnment |{Piton}| et applique |gobble| avec cette
+valeur de~$n$.
+
+\item Avec la clé |line-numbers|, les lignes \emph{non vides} sont numérotées dans les environnements \verb|{Piton}|
+et dans les listings produits par la commande |\PitonInputFile|.
+
+\item Avec la clé |all-line-numbers|, \emph{toutes} les lignes sont numérotées, y compris les lignes vides.
+\end{itemize}
+
+\bigskip
+
+\begingroup
+\fvset{commandchars=\~\&\@,formatcom=\small\color{gray}}
+\begin{Verbatim}
+~emphase&\PitonOptions{line-numbers,auto-gobble}@
+\begin{Piton}
+ from math import pi
+
+ def arctan(x,n=10):
+ """Compute the value of arctan(x)
+ n is the number of terms if the sum"""
+ if x < 0:
+ return -arctan(-x) # recursive call
+ elif x > 1:
+ return pi/2 - arctan(1/x)
+ ## (on a utilisé le fait que $\arctan(x)+\arctan(1/x)=\frac{\pi}{2}$ pour $x>0$)
+ else
+ s = 0
+ for k in range(n):
+ s += (-1)**k/(2*k+1)*x**(2*k+1)
+ return s
+\end{Piton}
+\end{Verbatim}
+\endgroup
+
+\begingroup
+\PitonOptions{line-numbers,auto-gobble}
+\begin{Piton}
+ from math import pi
+
+ def arctan(x,n=10):
+ """Compute the value of arctan(x)
+ n is the number of terms if the sum"""
+ if x < 0:
+ return -arctan(-x) # recursive call
+ elif x > 1:
+ return pi/2 - arctan(1/x)
+ ## (on a utilisé le fait que $\arctan(x)+\arctan(1/x)=\frac{\pi}{2}$ pour $x>0$)
+ else
+ s = 0
+ for k in range(n):
+ s += (-1)**k/(2*k+1)*x**(2*k+1)
+ return s
+\end{Piton}
+\endgroup
+
+\subsection{L'option escape-inside}
+
+L'option |escape-inside| doit être utilisée au chargement de \pkg{piton} (c'est-à-dire dans l'instruction
+|\usepackage|). Pour des raisons techniques, elle ne peut pas être fixée dans |\PitonOptions|. Elle prend comme
+valeur deux caractères qui seront utilisés pour délimiter des parties qui seront composées en LaTeX.
+
+
+\bigskip
+Dans l'exemple suivant, on suppose que l'extension \pkg{piton} a été chargée de la manière suivante :
+
+\smallskip
+\begin{Verbatim}
+\usepackage[~emphase#escape-inside=$$@]{piton}
+\end{Verbatim}
+
+\medskip
+Dans le code suivant, qui est une programmation récursive de la factorielle, on décide de surligner en jaune
+l'instruction qui contient l'appel récursif.
+\begin{Verbatim}
+\begin{Piton}
+def fact(n):
+ if n==0:
+ return 1
+ else:
+ ~emphase#$\colorbox{yellow!50}{$@return n*fact(n-1)~emphase#$}$@
+\end{Piton}
+\end{Verbatim}
+
+\begin{Piton}
+def fact(n):
+ if n==0:
+ return 1
+ else:
+ $\colorbox{yellow!50}{$return n*fact(n-1)$}$
+\end{Piton}
+
+\bigskip
+\emph{Attention} : L'échappement vers LaTeX permis par les caractères de |escape-inside| n'est pas actif dans les
+chaînes de caractères ni dans les commentaires (pour avoir un commentaire entièrement en échappement vers LaTeX,
+il suffit de le faire débuter par |##|).
+
+\subsection{Les styles}
+
+L'extension \pkg{piton} fournit la commande |\SetPitonStyle| pour personnaliser les différents styles utilisés pour
+formater les éléments syntaxiques des listings Python. Ces personnalisations ont une portée qui correspond au
+groupe TeX courant.
+
+\bigskip
+La commande |\SetPitonStyle| prend en argument une liste de couples \textsl{clé=valeur}. Les clés sont les noms des
+styles et les valeurs sont les instructions LaTeX de formatage correspondantes.
+
+\bigskip
+Ces instructions LaTeX doivent être des instructions de formatage du type de |\color{...}|, |\bseries|,
+|\slshape|, etc. (les commandes de ce type sont parfois qualifiées de \emph{semi-globales}). Il est aussi possible
+de mettre, \emph{à la fin de la liste d'instructions}, une commande LaTeX prenant exactement un
+argument.
+
+\bigskip
+Voici un exemple qui change le style utilisé pour le nom d'une fonction Python, au moment de sa définition
+(c'est-à-dire après le mot-clé |def|).
+
+\begin{Verbatim}
+\SetPitonStyle
+ { Name.Function = \bfseries \setlength{\fboxsep}{1pt}\colorbox{yellow!50} }
+\end{Verbatim}
+
+Dans cet exemple, |\colorbox{yellow!50}| doit être considéré comme le nom d'une fonction LaTeX qui prend exactement
+un argument, puisque, habituellement, elle est utilisée avec la syntaxe |\colorbox{yellow!50}{text}|.
+
+\medskip
+\begingroup
+\SetPitonStyle
+ { Name.Function = \bfseries \setlength{\fboxsep}{1pt}\colorbox{yellow!50} }
+Avec ce réglage, on obtient : \piton{def cube(x) : return x * x * x }
+\endgroup
+
+
+
+\medskip
+Les différents styles sont décrits dans la table \ref{Semantic}.
+
+\begin{table}[htb]
+\centering
+\caption{Usage des différents styles}
+\label{Semantic}
+\begin{tabularx}{0.9\textwidth}{@{}>{\ttfamily}l>{\raggedright\arraybackslash}X@{}}
+\toprule
+\normalfont Style & Usage \\
+\midrule
+Number & les nombres \\
+String.Short & les chaînes de caractères courtes (entre \texttt{'} ou \texttt{"}) \\
+String.Long & les chaînes de caractères longues (entre \texttt{'''} ou \texttt{"""}) sauf les chaînes de
+ documentation \\
+String & cette clé fixe à la fois |String.Short| et |String.Long| \\
+String.Doc & les chaînes de documentation \\
+String.Interpol & les éléments syntaxiques des champs des f-strings (c'est-à-dire les caractères \texttt{\{}, \texttt{\}} et \texttt{:}) \\
+Operator & les opérateurs suivants : \texttt{!= == << >> - \~{} + / * \% = < > \& .} \verb+|+ \verb|@| \\
+Operator.Word & les opérateurs suivants : |in|, |is|, |and|, |or| et |not| \\
+Name.Builtin & la plupart des fonctions prédéfinies par Python \\
+Name.Function & le nom des fonctions définies par l'utilisateur \emph{au moment de leur définition}, c'est-à-dire
+ après le mot-clé \verb|def| \\
+Name.Decorator & les décorateurs (instructions débutant par \verb|@| dans les classes) \\
+Name.Namespace & le nom des modules (= bibliothèques extérieures) \\
+Name.Class & le nom des classes au moment de leur définition \\
+Exception & le nom des exceptions prédéfinies (eg: SyntaxError) \\
+Comment & les commentaires commençant par \texttt{\#} \\
+Comment.LaTeX & les commentaires commençant par \texttt{\#\#} qui sont composés en LaTeX par \pkg{piton}
+ (\texttt{\#\#} est une séquence d'échappement vers LaTeX) \\
+Keyword.Constant & |True|, |False| et |None| \\
+Keyword & les mots-clés suivants :
+ \ttfamily assert, break, case, continue, del,
+ elif, else, except, exec, finally, for, from,
+ global, if, import, lambda, non local,
+ pass, raise, return, try, while,
+ with, yield, yield from.\\
+ \bottomrule
+\end{tabularx}
+\end{table}
+
+
+
+\subsection{Définition de nouveaux environnements}
+
+Comme l'environnement |{Piton}| a besoin d'absorber son contenu d'une manière spéciale (à peu près comme du texte
+verbatim), il n'est pas possible de définir de nouveaux environnements directement au-dessus de l'environnement
+|{Piton}|.
+
+C'est pourquoi \pkg{piton} propose une commande |\NewPitonEnvironment|. Cette commande a la même syntaxe que la
+commande classique |\NewDocumentEnvironment|.
+
+\bigskip
+Par exemple, avec l'instruction suivante, un nouvel environnement |{Python}| sera défini avec le même comportement
+que l'environnement |{Piton}|:
+
+\verb|\NewPitonEnvironment{Python}{}{}{}|
+
+\bigskip
+Si on souhaite un environnement |{Python}| qui compose le code inclus dans une boîte de \pkg{tcolorbox}, on peut
+écrire:
+
+\begin{verbatim}
+\NewPitonEnvironment{Python}{}
+ {\begin{tcolorbox}}
+ {\end{tcolorbox}}
+\end{verbatim}
+
+
+\end{document} \ No newline at end of file
diff --git a/macros/luatex/latex/piton/piton.dtx b/macros/luatex/latex/piton/piton.dtx
new file mode 100644
index 0000000000..48e6f777e5
--- /dev/null
+++ b/macros/luatex/latex/piton/piton.dtx
@@ -0,0 +1,810 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2022 by F. Pantigny
+% -----------------------------------
+%
+% This file may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in:
+%
+% http://www.latex-project.org/lppl.txt
+%
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% \fi
+% \iffalse
+\def\myfileversion{0.6}
+\def\myfiledate{2022/09/14}
+%
+%
+%<*batchfile>
+\begingroup
+\input l3docstrip.tex
+\keepsilent
+\usedir{tex/latex/cascade}
+\preamble
+
+Copyright (C) 2022 by F. Pantigny
+-----------------------------------
+
+This file may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either version 1.3
+of this license or (at your option) any later version.
+The latest version of this license is in:
+
+http://www.latex-project.org/lppl.txt
+
+and version 1.3 or later is part of all distributions of LaTeX
+version 2005/12/01 or later.
+
+\endpreamble
+\askforoverwritefalse
+\endgroup
+%</batchfile>
+%
+%<@@=piton>
+%<*driver>
+\documentclass{l3doc}
+\usepackage{geometry}
+\geometry{left=2.8cm,right=2.8cm,top=2.5cm,bottom=2.5cm,papersize={21cm,29.7cm}}
+\usepackage{fontspec}
+\usepackage[dvipsnames]{xcolor}
+\usepackage{caption,tabularx}
+\def\emphase{\bgroup\color{RoyalPurple}\let\next=}
+\fvset{commandchars=\~\#\@,formatcom=\color{gray}}
+\captionsetup{labelfont = bf}
+\usepackage{ragged2e}
+\usepackage[escape-inside=$$]{piton} % $$
+
+\def\interitem{\vskip 7mm plus 2 mm minus 3mm}
+\parindent 0pt
+\skip\footins = 2\bigskipamount
+
+\begin{filecontents}[noheader,overwrite]{example1.txt}
+from math import pi
+
+def arctan(x,n=10):
+ """Compute the value of arctan(x)
+ n is the number of terms if the sum"""
+ if x < 0:
+ return -arctan(-x) # recursive call
+ elif x > 1:
+ return pi/2 - arctan(1/x)
+ ## (we have used that $\arctan(x)+\arctan(1/x)=\frac{\pi}{2}$ for $x>0$)\footnote{This LaTeX escape has been done by beginning the comment by \ttfamily\#\#}
+ else
+ s = 0
+ for k in range(n):
+ s += (-1)**k/(2*k+1)*x**(2*k+1)
+ return s
+\end{filecontents}
+
+\begin{filecontents}[noheader,overwrite]{example2.txt}
+def fact(n):
+ if n==0:
+ return 1
+ else:
+ $\colorbox{yellow!50}{$return n*fact(n-1)$}$
+\end{filecontents}
+
+
+\EnableCrossrefs
+
+\begin{document}
+\DocInput{piton.dtx}
+\end{document}
+%</driver>
+
+% \fi
+% \title{The package \pkg{piton}\thanks{This document corresponds to the
+% version~\myfileversion\space of \pkg{piton}, at the date of~\myfiledate.}}
+% \author{F. Pantigny \\ \texttt{fpantigny@wanadoo.fr}}
+%
+% \maketitle
+%
+% \begin{abstract}
+% The package \pkg{piton} provides tools to typeset Python listings with
+% syntactic highlighting by using the Lua library LPEG. It requires LuaLaTeX.
+% \end{abstract}
+%
+%
+% \section{Presentation}
+%
+%
+% The package \pkg{piton} uses the Lua library LPEG\footnote{LPEG is a
+% pattern-matching library for Lua, written in C, based on \emph{parsing
+% expression grammars}: \url{http://www.inf.puc-rio.br/~roberto/lpeg/}} for
+% parsing Python listings and typeset them with syntactic highlighting. Since it
+% uses Lua code, it works with |lualatex| only (and won't work with the other
+% engines: |latex|, |pdflatex| and |xelatex|). It does not use external program
+% and the compilation does not require |--shell-escape|. The compilation is very
+% fast since all the parsing is done by the library LPEG, written in C.
+%
+% \bigskip
+% Here is an exemple of code typeset by \pkg{piton}, with the environment |{Piton}|.
+%
+% \bigskip
+% \PitonInputFile{Example1.txt}
+%
+%
+% \section{Installation}
+%
+% The package \pkg{piton} is contained in two files: |piton.sty| and
+% |piton.lua| (the LaTeX file |piton.sty| loaded by |\usepackage| will load the
+% Lua file |piton.lua|). Both files must be in a repertory where LaTeX will be
+% able to find them. The best way is to install them in a |texmf| tree.
+%
+%
+% \section{Use of the package}
+%
+% In order to use the package \pkg{piton}, one has only to load the package in
+% its document with the standard command |\usepackage| and remember that the
+% compilation must be done with |lualatex| (and no other LaTeX engine).
+%
+% \medskip
+% The package \pkg{piton} provides three tools to typeset Python code: the
+% command |\piton|, the environment |{Piton}| and the command |\PitonInputFile|.
+%
+% \begin{itemize}
+% \item The command |\piton| should be used to typeset small pieces of code
+% inside a paragraph. \emph{Caution}: That fonction takes in its argument
+% \emph{verbatim}. Therefore, it cannot be used in the argument of another
+% command (however, it can be used within an environment).
+% \item The environment |{Piton}| should be used to typeset multi-lines code.
+%
+% \item The command |\PitonInputFile| is used to insert and typeset a whole
+% external file.
+% \end{itemize}
+%
+% \bigskip
+% It's possible to compose comments in LaTeX by beginning with |##| (it's a
+% ``LaTeX escape''). The characters |##| themselves won't be printed.
+%
+% \section{Customization}
+%
+% \subsection{The command \textbackslash PitonOptions}
+%
+% The command |\PitonOptions| provides four keys: |gobble|, |auto-gobble|,
+% |line-numbers| and |all-line-numbers|.
+%
+% \begin{itemize}
+% \item The key |gobble| takes in as value a positive integer~$n$: the first $n$
+% characters are discarded (before the process of hightlighning of the code) for
+% each line of the environment |{Piton}|.
+%
+% \item Then the key |auto-gobble| is in force, the extnsion \pkg{piton} compute
+% the minimal value $n$ of the number of consecutives space beginning each (non
+% empty) line of the environment |{Piton}| and applies |gobble| with that value
+% of~$n$.
+%
+% \item With the key |line-numbers|, the \emph{non empty} lines are numbered in
+% the environments |{Piton}| and in the listings resulting from the use of
+% |\PitonInputFile|.
+%
+% \item With the key |all-line-numbers|, \emph{all} the lines are numbered,
+% including the empty ones.
+% \end{itemize}
+%
+% \bigskip
+%
+% \begingroup
+% \fvset{commandchars=\~\&\@,formatcom=\small\color{gray}}
+% \begin{Verbatim}
+% ~emphase&\PitonOptions{line-numbers,auto-gobble}@
+% \begin{Piton}
+% from math import pi
+%
+% def arctan(x,n=10):
+% """Compute the value of arctan(x)
+% n is the number of terms if the sum"""
+% if x < 0:
+% return -arctan(-x) # recursive call
+% elif x > 1:
+% return pi/2 - arctan(1/x)
+% ## (on a utilisé le fait que $\arctan(x)+\arctan(1/x)=\frac{\pi}{2}$ pour $x>0$)
+% else
+% s = 0
+% for k in range(n):
+% s += (-1)**k/(2*k+1)*x**(2*k+1)
+% return s
+% \end{Piton}
+% \end{Verbatim}
+% \endgroup
+%
+%
+% \begingroup
+% \PitonOptions{line-numbers,auto-gobble}
+% \PitonInputFile{Example1.txt}
+% \endgroup
+%
+% \subsection{The option escape-inside}
+%
+% The option |escape-inside| must be used when loading the package \pkg{piton}
+% (that is to say in the instruction |\usepackage|). For technical reasons, it
+% can't be used in the command |\PitonOptions|. That option takes in as value
+% two characters which will be used to delimit pieces of code which will
+% composed in LaTeX.
+%
+% \medskip
+% In the following example, we assume that the extension \pkg{piton} has been
+% loaded by the following instruction.
+%
+% \begin{Verbatim}
+% \usepackage[~emphase#escape-inside=$$@]{piton}
+% \end{Verbatim}
+%
+% \medskip
+% In the following code, which is a recursive programmation of the mathematical
+% factorial, we decide to highlight in yellow the instruction which contains the
+% recursive call.
+% \begin{Verbatim}
+% \begin{Piton}
+% def fact(n):
+% if n==0:
+% return 1
+% else:
+% ~emphase#$\colorbox{yellow!50}{$@return n*fact(n-1)~emphase#$}$@
+% \end{Piton}
+% \end{Verbatim}
+%
+% \PitonInputFile{Example2.txt}
+%
+% \bigskip
+%
+% \emph{Caution} : The escape to LaTeX allowed by the characters of
+% |escape-inside| is not active in the strings nor in the Python comments
+% (however, it's possible to have a whole Python comment composed in LaTeX by
+% beginning it with |##|).
+%
+%
+% \subsection{The styles}
+%
+% The package \pkg{piton} provides the command |\SetPitonStyle| to customize the
+% different styles used to format the syntactic elements of the Python listings.
+% The customizations done by that command are limited to the current TeX group.
+%
+% \bigskip
+% The command |\SetPitonStyle| takes in as argument a comma-separated list of
+% \textsl{key=value} pairs. The keys are names of styles and the value are LaTeX
+% formatting instructions.
+%
+% \bigskip
+% These LaTeX instructions must be formatting instructions such as
+% |\color{...}|, |\bfseries|, |\slshape|, etc. (the commands of this kind are
+% sometimes called \emph{semi-global} commands). It's also possible to put,
+% \emph{at the end of the list of instructions}, a LaTeX command taking exactly
+% one argument.
+%
+% \bigskip
+% Here an example which changes the style used to highlight, in the definition
+% of a Python function, the name of the function which is defined.
+%
+% \begin{verbatim}
+% \SetPitonStyle
+% { Name.Function = \bfseries \setlength{\fboxsep}{1pt}\colorbox{yellow!50} }
+% \end{verbatim}
+%
+% In that example, |\colorbox{yellow!50}| must be considered as the name of a
+% LaTeX command which takes in exactly one argument, since, usually, it is used
+% with the syntax |\colorbox{yellow!50}{text}|.
+%
+% \medskip
+% \begingroup
+% \SetPitonStyle
+% { Name.Function = \bfseries \setlength{\fboxsep}{1pt}\colorbox{yellow!50} }
+% With that setting, we will have : \piton{def cube(x) : return x * x * x }
+% \endgroup
+%
+% \medskip
+% The different styles are described in the table \ref{Semantic}.
+%
+%
+%
+% \begin{table}[b]
+% \centering
+% \caption{Usage of the different styles}
+% \label{Semantic}
+% \begin{tabular}{@{}>{\ttfamily}l>{\RaggedRight\arraybackslash}p{9cm}@{}}
+% \toprule
+% \normalfont Style & Usage \\
+% \midrule
+% Number & the numbers \\
+% String.Short & the short strings (between \texttt{'} or \verb|"|) \\
+% String.Long & the long strings (between \texttt{'''} or \verb|"""|) except the
+% documentation strings \\
+% String & that keys sets both |String.Short| and |String.Long| \\
+% String.Doc & the documentation strings \\
+% String.Interpol & the syntactic elements of the fields of the f-strings (that
+% is to say the characters \texttt{\{}, \texttt{\}} and \texttt{:}) \\
+% Operator & the following operators : \texttt{!= == << >> - \~{} + / * \% = < > \& .} \verb+|+ \verb|@|\\
+% Operator.Word & the following operators : \texttt{in}, \texttt{is},
+% \texttt{and}, \texttt{or} et \texttt{not} \\
+% Name.Builtin & the predefined functions of Python \\
+% Name.Function & the name of the functions defined by the user, at the point of
+% their definition (that is to say after the keyword |def|) \\
+% Name.Decorator & the decorators (instructions beginning by \verb|@| in the classes) \\
+% Name.Namespace & the name of the modules (= external libraries) \\
+% Name.Class & the name of the classes at the point of their definition \\
+% Exception & the names of the exceptions (eg: \texttt{SyntaxError}) \\
+% Comment & the comments beginning with \verb|#| \\
+% LaTeX & the comments beginning by \verb|##| which are composed in LaTeX by
+% \pkg{piton} (\verb|##| is an espace sequence to LaTeX) \\
+% Keyword.Constant & |True|, |False| and |None| \\
+% Keyword & the following keywords :
+% \ttfamily assert, break, case, continue, del,
+% elif, else, except, exec, finally, for, from,
+% global, if, import, lambda, non local,
+% pass, raise, return, try, while,
+% with, yield, yield from.\\
+% \bottomrule
+% \end{tabular}
+% \end{table}
+%
+%
+%
+%
+% \subsection{Creation of new environments}
+%
+% Since the environment |{Piton}| has to catch its body in a special way (more
+% or less as verbatim text), it's not possible to construct new environments
+% directly over the environment |{Piton}|
+%
+% That's why \pkg{piton} provides a command |\NewPitonEnvironment|. That
+% command takes in three mandatory arguments.
+
+% That command has the same syntax as the classical environment
+% |\NewDocumentEnvironment|.
+%
+% \bigskip
+% With the following instruction, a new environment |{Python}| will be
+% constructed with the same behaviour as |{Piton}|:
+%
+% \verb|\NewPitonEnvironment{Python}{}{}{}|
+%
+% \bigskip
+% If on wished to format Python code in a box in a box of \pkg{tcolorbox}, it's
+% possible to define an environment |{Python}| with the following code:
+%
+%\begin{verbatim}
+% \NewPitonEnvironment{Python}{}
+% {\begin{tcolorbox}}
+% {\end{tcolorbox}}
+% \end{verbatim}
+%
+%
+% \clearpage
+%
+% \section{Implementation}
+%
+% \begin{macrocode}
+\NeedsTeXFormat{LaTeX2e}
+\RequirePackage{l3keys2e}
+\ProvidesExplPackage
+ {piton}
+ {\myfiledate}
+ {\myfileversion}
+ {Highlight Python codes with LPEG on LuaLaTeX}
+% \end{macrocode}
+%
+% \bigskip
+% We define a set of keys |piton/package| for these options.
+% \begin{macrocode}
+\keys_define:nn { piton / package }
+ {
+ escape-inside .tl_set:N = \c_@@_escape_inside_tl ,
+ unknown .code:n = \msg_error:nn { piton } { unknown~key~for~package }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\msg_new:nnn { piton } { unknown~key~for~package }
+ {
+ Unknown~key\\
+ You~have~used~the~key~'\l_keys_key_str'~but~the~only~key~available~here~
+ is~the~key~'escape-inside'.\\
+ That~key~will~be~ignored.
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\tl_clear_new:N \c_@@_escape_inside_tl
+% \end{macrocode}
+%
+% We process the options when the package is loaded (with |\usepackage|).
+% \begin{macrocode}
+\ProcessKeysOptions { piton / package }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\begingroup
+\cs_new_protected:Npn \@@_set_escape_char:nn #1 #2
+ {
+ \directlua { begin_escape = "#1" }
+ \directlua { end_escape = "#2" }
+ }
+\cs_generate_variant:Nn \@@_set_escape_char:nn { x x }
+\@@_set_escape_char:xx
+ { \tl_head:V \c_@@_escape_inside_tl }
+ { \tl_tail:V \c_@@_escape_inside_tl }
+\endgroup
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\msg_new:nnn { piton } { LuaLaTeX~mandatory }
+ { The~package~'piton'~must~be~used~with~LuaLaTeX.\\ It~won't~be~loaded. }
+\sys_if_engine_luatex:F { \msg_critical:nn { piton } { LuaLaTeX~mandatory } }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\RequirePackage { luatexbase }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\msg_new:nnn { piton } { piton.lua~not~found }
+ {
+ The~file~'piton.lua'~can't~be~found.\\
+ The package~'piton'~won't be loaded.
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\file_if_exist:nF { piton.lua }
+ { \msg_critical:nn { piton } { piton.lua~not~found} }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\lua_now:e { require("piton.lua") }
+% \end{macrocode}
+%
+% \bigskip
+% The following function has not a name with the conventions of L3 because it
+% will be used in the Lua code.
+% \begin{macrocode}
+\cs_new:Npn \pitonEOL
+ {
+ \par \leavevmode
+ \@@_print_number:
+ }
+% \end{macrocode}
+%
+% \medskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_print_number:
+ { \bool_if:NT \l_@@_line_numbers_bool \@@_actually_print_number: }
+% \end{macrocode}
+%
+% \medskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_actually_print_number:
+ {
+% \end{macrocode}
+% The empty lines in the code are not numbered.
+% \begin{macrocode}
+ \bool_if:NF \l_@@_all_line_numbers_bool
+ { \peek_meaning:NF \pitonEOL }
+ \@@_actually_print_number_i:
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_actually_print_number_i:
+ {
+ \int_incr:N \l_@@_lineno_int
+ \hbox_overlap_left:n
+ {
+ { \color{gray} \footnotesize \int_to_arabic:n \l_@@_lineno_int }
+ \quad
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% The following counter will be used to count the lines in the code when the
+% user requires the numbers of the lines to be printed.
+% \begin{macrocode}
+\int_new:N \l_@@_lineno_int
+% \end{macrocode}
+%
+% \bigskip
+% The following integer is the number of characters to gobble on the left side
+% of the Python listings. Of course, the initial value is $0$.
+% \begin{macrocode}
+\int_new:N \l_@@_gobble_int
+% \end{macrocode}
+%
+%
+% \bigskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_define_trim_syntax:n #1
+ { \lua_now:n { define_trim_syntax(#1) } }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\NewDocumentCommand { \piton } { v }
+ {
+ \group_begin:
+ \ttfamily
+ \lua_now:e { Parse(token.scan_argument()) } { #1 }
+ \group_end:
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\NewDocumentCommand { \PitonInputFile } { m }
+ {
+ \group_begin:
+ \ttfamily
+ \bool_if:NT \l_@@_line_numbers_bool
+ {
+ \@@_actually_print_number:
+ \vspace{-\baselineskip}
+ }
+ \lua_now:e { ParseFile(token.scan_argument()) } { #1 }
+ \group_end:
+ }
+% \end{macrocode}
+%
+% \subsection{PitonOptions}
+%
+% \begin{macrocode}
+\bool_new:N \l_@@_line_numbers_bool
+\bool_new:N \l_@@_all_line_numbers_bool
+% \end{macrocode}
+%
+% \begin{macrocode}
+\keys_define:nn { piton / PitonOptions }
+ {
+ gobble .int_set:N = \l_@@_gobble_int ,
+ gobble .value_required:n = true ,
+ auto-gobble .code:n = \int_set:Nn \l_@@_gobble_int { -1 } ,
+ auto-gobble .value_forbidden:n = true ,
+ line-numbers .bool_set:N = \l_@@_line_numbers_bool ,
+ line-numbers .default:n = true ,
+ all-line-numbers .code:n =
+ \bool_set_true:N \l_@@_line_numbers_bool
+ \bool_set_true:N \l_@@_all_line_numbers_bool ,
+ all-line-numbers .value_forbidden:n = true
+ }
+% \end{macrocode}
+%
+% \bigskip
+% The argument of |\PitonOptions| is provided by currification.
+% \begin{macrocode}
+\NewDocumentCommand \PitonOptions { }
+ { \keys_set:nn { piton / PitonOptions } }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\NewDocumentCommand { \NewPitonEnvironment } { m m m m }
+ {
+% \end{macrocode}
+% We construct a TeX macro which will catch as its argument all the tokens
+% until \textsl{\texttt{newline}} + |\end{Piton}| with, in that
+% \textsl{\texttt{newline}}| + \end{Piton}|, the catcode of
+% \textsl{\texttt{newline}}, |\|, |{| and |}| equal to 12 (``\texttt{other}'').
+% The latter explains why the definition of that function is a bit complicated.
+% \begin{macrocode}
+ \use:x
+ {
+ \cs_set_protected:Npn
+ \use:c { __piton_collect_ #1 :w }
+ ####1
+ \c_backslash_str end \c_left_brace_str #1 \c_right_brace_str
+ }
+ {
+ \group_end:
+ \par \addvspace { 0.5 em }
+ {
+ \dim_set_eq:NN \parindent \c_zero_dim
+ \ttfamily
+ \bool_if:NT \l_@@_line_numbers_bool
+ {
+ \@@_actually_print_number:
+ \vspace{-\baselineskip}
+ }
+ \int_case:nnF \l_@@_gobble_int
+ {
+ 0
+% \end{macrocode}
+% Be careful: the last argument is provided by currification.
+% \begin{macrocode}
+ { \lua_now:e { Parse(token.scan_argument()) } }
+ { -1 }
+ { \lua_now:e { AutoGobbleParse(token.scan_argument()) } }
+ }
+ {
+ \exp_args:NV \@@_define_trim_syntax:n \l_@@_gobble_int
+ \lua_now:e { GobbleParse(token.scan_argument()) }
+ }
+ { ##1 }
+ }
+ \par \addvspace { 0.5 em }
+% \end{macrocode}
+% The following |\end{#1}| is only for the groups and the stack of
+% environments of LaTeX.
+% \begin{macrocode}
+ \end { #1 }
+ }
+% \end{macrocode}
+%
+%
+% \bigskip
+% We can now define the new environment by defining the two TeX macros
+% characteristic to the LaTeX environment.
+% \begin{macrocode}
+ \NewDocumentEnvironment { #1 } { #2 }
+ {
+ #3
+ \group_begin:
+ \tl_map_function:nN
+ { \ \\ \{ \} \$ \& \# \^ \_ \% \~ \^^M }
+ \char_set_catcode_other:N
+ \use:c { __piton_collect_ #1 :w }
+ }
+ { #4 }
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\NewPitonEnvironment { Piton } { } { } { }
+% \end{macrocode}
+%
+% \bigskip
+%
+% \begin{macrocode}
+\NewDocumentCommand { \PitonStyle } { m } { \csname pitonStyle#1\endcsname }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\NewDocumentCommand { \SetPitonStyle } { } { \keys_set:nn { piton } }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_math_scantokens:n #1
+ { \normalfont \scantextokens { $#1$ } }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\keys_define:nn { piton }
+ {
+ String.Interpol .tl_set:c = pitonStyle String.Interpol ,
+ String.Interpol .value_required:n = true ,
+ FormattingType .tl_set:c = pitonStyle FormattingType ,
+ FormattingType .value_required:n = true ,
+ Dict.Value .tl_set:c = pitonStyle Dict.Value ,
+ Dict.Value .value_required:n = true ,
+ Name.Decorator .tl_set:c = pitonStyle Name.Decorator ,
+ Name.Decorator .value_required:n = true ,
+ Name.Function .tl_set:c = pitonStyle Name.Function ,
+ Name.Function .value_required:n = true ,
+ Keyword .tl_set:c = pitonStyle Keyword ,
+ Keyword .value_required:n = true ,
+ Keyword.Constant .tl_set:c = pitonStyle Keyword.Constant ,
+ Keyword.constant .value_required:n = true ,
+ String.Doc .tl_set:c = pitonStyle String.Doc ,
+ String.Doc .value_required:n = true ,
+ Interpol.Inside .tl_set:c = pitonStyle Interpol.Inside ,
+ Interpol.Inside .value_required:n = true ,
+ String.Long .tl_set:c = pitonStyle String.Long ,
+ String.Long .value_required:n = true ,
+ String.Short .tl_set:c = pitonStyle String.Short ,
+ String.Short .value_required:n = true ,
+ String .meta:n = { String.Long = #1 , String.Short = #1 } ,
+ Comment.Math .tl_set:c = pitonStyle Comment.Math ,
+ Comment.Math .default:n = \@@_math_scantokens:n ,
+ Comment.Math .initial:n = ,
+ Comment .tl_set:c = pitonStyle Comment ,
+ Comment .value_required:n = true ,
+ InitialValues .tl_set:c = pitonStyle InitialValues ,
+ InitialValues .value_required:n = true ,
+ Number .tl_set:c = pitonStyle Number ,
+ Number .value_required:n = true ,
+ Name.Namespace .tl_set:c = pitonStyle Name.Namespace ,
+ Name.Namespace .value_required:n = true ,
+ Name.Class .tl_set:c = pitonStyle Name.Class ,
+ Name.Class .value_required:n = true ,
+ Name.Builtin .tl_set:c = pitonStyle Name.Builtin ,
+ Name.Builtin .value_required:n = true ,
+ Name.Type .tl_set:c = pitonStyle Name.Type ,
+ Name.Type .value_required:n = true ,
+ Operator .tl_set:c = pitonStyle Operator ,
+ Operator .value_required:n = true ,
+ Operator.Word .tl_set:c = pitonStyle Operator.Word ,
+ Operator.Word .value_required:n = true ,
+ Post.Function .tl_set:c = pitonStyle Post.Function ,
+ Post.Function .value_required:n = true ,
+ Exception .tl_set:c = pitonStyle Exception ,
+ Exception .value_required:n = true ,
+ Comment.LaTeX .tl_set:c = pitonStyle Comment.LaTeX ,
+ Comment.LaTeX .value_required:n = true ,
+ unknown .code:n = \msg_error:nn { piton }{ Unknown~key~for~SetPitonStyle }
+ }
+% \end{macrocode}
+%
+%
+% \bigskip
+% \begin{macrocode}
+\msg_new:nnn { piton } { Unknown~key~for~SetPitonStyle } {
+ The~style~'\l_keys_key_str'~is~unknown.\\
+ This~key~will~be~ignored.\\
+ The~available~styles~are~(in~alphabetic~order):~
+ Comment,~
+ Comment.LaTeX,~
+ Dict.Value,~
+ Exception,~
+ InitialValues,~
+ Keyword,~
+ Keyword.Constant,~
+ Name.Builtin,~
+ Name.Class,~
+ Name.Decorator,~
+ Name.Function,~
+ Name.Namespace,~
+ Number,~
+ Operator,~
+ Operator.Word,~
+ String,~
+ String.Doc,~
+ String.Long,~
+ String.Short,~and~
+ String.Interpol. }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\SetPitonStyle
+ {
+ Comment = \color[HTML]{0099FF} \itshape ,
+ Exception = \color[HTML]{CC0000} ,
+ Keyword = \color[HTML]{006699} \bfseries ,
+ Keyword.Constant = \color[HTML]{006699} \bfseries ,
+ Name.Builtin = \color[HTML]{336666} ,
+ Name.Decorator = \color[HTML]{9999FF},
+ Name.Class = \color[HTML]{00AA88} \bfseries ,
+ Name.Function = \color[HTML]{CC00FF} ,
+ Name.Namespace = \color[HTML]{00CCFF} ,
+ Number = \color[HTML]{FF6600} ,
+ Operator = \color[HTML]{555555} ,
+ Operator.Word = \bfseries ,
+ String = \color[HTML]{CC3300} ,
+ String.Doc = \color[HTML]{CC3300} \itshape ,
+ String.Interpol = \color[HTML]{AA0000} ,
+ Comment.LaTeX = \normalfont \color[rgb]{.468,.532,.6} ,
+ Name.Type = \color[HTML]{336666} ,
+ InitialValues = \piton ,
+ Dict.Value = \piton ,
+ Post.Function = \piton ,
+ Interpol.Inside = \color{black}\piton ,
+ }
+% \end{macrocode}
+%
+%
+% \vspace{1cm}
+% \tableofcontents
+% \end{document}
+%
+% Local Variables:
+% TeX-fold-mode: t
+% TeX-fold-preserve-comments: nil
+% flyspell-mode: nil
+% fill-column: 80
+% End:
+
+
+
+
+
+
diff --git a/macros/luatex/latex/piton/piton.ins b/macros/luatex/latex/piton/piton.ins
new file mode 100644
index 0000000000..04c653960d
--- /dev/null
+++ b/macros/luatex/latex/piton/piton.ins
@@ -0,0 +1,47 @@
+%%
+%% Copyright (C) 2022 by F. Pantigny
+%%
+%%
+%% This file may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either
+%% version 1.3 of this license or (at your option) any later
+%% version. The latest version of this license is in:
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% and version 1.3 or later is part of all distributions of
+%% LaTeX version 2005/12/01 or later.
+%%
+\input l3docstrip.tex
+\keepsilent
+\usedir{tex/latex/cascade}
+\preamble
+
+Copyright (C) 2022 by F. Pantigny
+
+This file may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either
+version 1.3 of this license or (at your option) any later
+version. The latest version of this license is in:
+
+ http://www.latex-project.org/lppl.txt
+
+and version 1.3 or later is part of all distributions of
+LaTeX version 2005/12/01 or later.
+
+\endpreamble
+\generate{\file{piton.sty}{\from{piton.dtx}{package}}}
+\Msg{*********************************************************}
+\Msg{*}
+\Msg{* To finish the installation you have to move the}
+\Msg{* following files into a directory searched by TeX:}
+\Msg{*}
+\Msg{* \space\space piton.sty\space\space and\space\space piton.lua}
+\Msg{*}
+\Msg{* To produce the documentation run the file piton.dtx}
+\Msg{* through LuaLaTeX.}
+\Msg{*}
+\Msg{* Happy TeXing!}
+\Msg{*********************************************************}
+\endbatchfile
+
diff --git a/macros/luatex/latex/piton/piton.lua b/macros/luatex/latex/piton/piton.lua
new file mode 100644
index 0000000000..8ef48f45b1
--- /dev/null
+++ b/macros/luatex/latex/piton/piton.lua
@@ -0,0 +1,473 @@
+-- -*- coding: utf-8 ; -*-
+--
+-- This is file 'piton.lua' which is a part of the Latex package 'piton'
+-- Copyright (C) 2022 by F. Pantigny
+
+-- This file may be distributed and/or modified under the
+-- conditions of the Latex Project Public License, either
+-- version 1.3 of this license or (at your option) any later
+-- version. The latest version of this license is in:
+--
+-- http://www.Latex-project.org/lppl.txt
+--
+-- and version 1.3 or later is part of all distributions of
+-- Latex version 2005/12/01 or later.
+
+
+-- This file is part of the version 0.55 of the package 'piton'
+
+local P, S, V , C , Ct, Cc, Cf = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cf
+
+
+--[[ By convention, a capture which provides as value a table (and not a string), provides, in fact,
+a string (the first element of the table) which is a formatting LaTeX instruction (it will be
+thrown back to TeX with normal catcodes (ant not ``other'' catcode for everybody).]]
+
+local function L(string)
+ return lpeg.Cc ( { string } )
+end
+
+local function K(pattern, style)
+ return
+ L ( "{\\PitonStyle{" .. style .. "}{" )
+ * lpeg.C(pattern)
+ * L ( "}}" )
+end
+
+
+--[[ The text in "escape" (between begin_escape and end_escape) is captured
+and put in a table (with only one component). Indeed, we have decided that a capture
+which is encapsulated in a table must be transmitted to TeX with the normal TeX catcodes.]]
+
+local Escape = P(begin_escape)
+ * Ct ( C ( ( 1 - P(end_escape) ) ^ 1 ) )
+ * P(end_escape)
+
+local EOL = ( P "\r" ) * L ( "\\pitonEOL" )
+
+
+
+lpeg.locale(lpeg) -- mandatory
+
+local alpha , digit , space , punct = lpeg.alpha , lpeg.digit , lpeg.space , lpeg.punct
+
+local letter = alpha + S"âàçéèêëïîôûüÂÀÇÉÈÊËÏÎÔÛÜ_"
+
+local alphanum = letter + digit
+
+local identifier = letter * alphanum ^ 0
+
+local Identifier = C ( identifier )
+
+local Space = C ( ( space - P "\r" ) ^ 1 )
+
+local SkipSpace = C ( ( space - P "\r" ) ^ 0 )
+
+local Punct = C ( punct )
+
+
+local Number =
+ K (
+ ( digit^1 * P "." * digit^0 + digit^0 * P "." * digit^1 + digit^1 )
+ * ( S "eE" * S "+-" ^ -1 * digit^1 ) ^ -1
+ + digit^1
+ , 'Number' )
+
+local Word = C ( ( ( 1 - space ) - S "'\"\r[()]" - digit ) ^ 1 )
+
+local Delim = C ( S "[()]" )
+
+
+local Keyword =
+ K ( P "assert" + P "break" + P "case" + P "continue" + P "del"
+ + P "elif" + P "else" + P "except" + P "exec" + P "finally" + P "for" + P "from"
+ + P "global" + P "if" + P "import" + P "lambda" + P "non local"
+ + P "pass" + P "return" + P "try" + P "while"
+ + P "with" + P "yield" + P "yield from" ,
+ 'Keyword' )
+ + K ( P "True" + P "False" + P "None" , 'Keyword.Constant' )
+
+
+local Builtin =
+ K ( P "__import__" + P "abs" + P "all" + P "any" + P "bin" + P "bool" + P "bytearray"
+ + P "bytes" + P "chr" + P "classmethod" + P "compile" + P "complex" + P "delattr"
+ + P "dict" + P "dir" + P "divmod" + P "enumerate" + P "eval" + P "filter"
+ + P "float" + P "format" + P "frozenset" + P "getattr" + P "globals" + P "hasattr"
+ + P "hash" + P "hex" + P "id" + P "input" + P "int" + P "isinstance" + P "issubclass"
+ + P "iter" + P "len" + P "list" + P "locals" + P "map" + P "max" + P "memoryview" + P "min"
+ + P "next" + P "object" + P "oct" + P "open" + P "ord" + P "pow" + P "print" + P "property"
+ + P "range" + P "repr" + P "reversed" + P "round" + P "set" + P "setattr" + P "slice"
+ + P "sorted" + P "staticmethod" + P "str" + P "sum" + P "super" + P "tuple" + P "type"
+ + P "vars" + P "zip" ,
+ 'Name.Builtin' )
+
+
+local Exception =
+ K ( "ArithmeticError" + P "AssertionError" + P "AttributeError"
+ + P "BaseException" + P "BufferError" + P "BytesWarning" + P "DeprecationWarning"
+ + P "EOFError" + P "EnvironmentError" + P "Exception" + P "FloatingPointError"
+ + P "FutureWarning" + P "GeneratorExit" + P "IOError" + P "ImportError"
+ + P "ImportWarning" + P "IndentationError" + P "IndexError" + P "KeyError"
+ + P "KeyboardInterrupt" + P "LookupError" + P "MemoryError" + P "NameError"
+ + P "NotImplementedError" + P "OSError" + P "OverflowError"
+ + P "PendingDeprecationWarning" + P "ReferenceError" + P "ResourceWarning"
+ + P "RuntimeError" + P "RuntimeWarning" + P "StopIteration"
+ + P "SyntaxError" + P "SyntaxWarning" + P "SystemError" + P "SystemExit"
+ + P "TabError" + P "TypeError" + P "UnboundLocalError" + P "UnicodeDecodeError"
+ + P "UnicodeEncodeError" + P "UnicodeError" + P "UnicodeTranslateError"
+ + P "UnicodeWarning" + P "UserWarning" + P "ValueError" + P "VMSError"
+ + P "Warning" + P "WindowsError" + P "ZeroDivisionError"
+ + P "BlockingIOError" + P "ChildProcessError" + P "ConnectionError"
+ + P "BrokenPipeError" + P "ConnectionAbortedError" + P "ConnectionRefusedError"
+ + P "ConnectionResetError" + P "FileExistsError" + P "FileNotFoundError"
+ + P "InterruptedError" + P "IsADirectoryError" + P "NotADirectoryError"
+ + P "PermissionError" + P "ProcessLookupError" + P "TimeoutError"
+ + P "StopAsyncIteration" + P "ModuleNotFoundError" + P "RecursionError" ,
+ 'Exception' )
+
+local RaiseException = K ( P "raise" , 'Keyword' ) * SkipSpace * Exception * C ( P "(" )
+
+local ExceptionInConsole = Exception * C ( ( 1 - P "\r" ) ^ 0 ) * EOL
+
+
+local Namespace =
+ K ( P "from" , 'Keyword' ) * Space * K ( alphanum^1 , 'Name.Namespace' )
+ * ( Space * K ( P "import" , 'Keyword' ) ) ^ -1
+
+
+local ImportAs = K ( P "import" , 'Keyword' )
+ * Space
+ * K ( identifier , 'Name.Namespace' )
+ * ( SkipSpace * C ( P "," ) * SkipSpace * K ( identifier , 'Name.Namespace' ) ) ^ 0
+ * (
+ Space * K ( P "as" , 'Keyword' ) * Space * K ( identifier , 'Name.Namespace' )
+ ) ^ 0
+
+local Class = K ( P "class" , 'Keyword' ) * Space * K ( identifier , 'Name.Class' )
+
+local Decorator = K ( P "@" * letter^1 , 'Name.Decorator' )
+
+local SingleShortInterpol =
+ K ( P "{" , 'String.Interpol')
+ * K ( ( 1 - S "}':" ) ^ 0 , 'Interpol.Inside' )
+ * C ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1
+ * K ( P "}" , 'String.Interpol' )
+
+local DoubleShortInterpol =
+ K ( P "{" , 'String.Interpol' )
+ * K ( ( 1 - S "}\":" ) ^ 0 , 'Interpol.Inside' )
+ * ( K ( P ":" , 'String.Interpol' ) * C ( (1 - S "}:\"") ^ 0 ) ) ^ -1
+ * K ( P "}" , 'String.Interpol' )
+
+local SingleLongInterpol =
+ K ( P "{" , 'String.Interpol' )
+ * K ( ( 1 - S "}:\r" - P "'''" ) ^ 0 , 'Interpol.Inside' )
+ * C ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1
+ * K ( P "}" , 'String.Interpol' )
+
+local DoubleLongInterpol =
+ K ( P "{" , 'String.Interpol' )
+ * K ( ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 , 'Interpol.Inside' )
+ * C ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1
+ * K ( P "}" , 'String.Interpol' )
+
+local SingleShortPureString = C ( ( P "\\'" + P "{{" + P "}}" + 1 - S "{}'" ) ^ 1 )
+
+local DoubleShortPureString = C ( ( P "\\\"" + P "{{" + P "}}" + 1 - S "{}\"" ) ^ 1 )
+
+local SingleLongPureString = C ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 )
+
+local DoubleLongPureString = C ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 )
+
+local SingleShortString =
+ L ( "{\\PitonStyle{String.Short}{" )
+ * (
+ C ( P "f'" + P "F'" )
+ * ( SingleShortInterpol + SingleShortPureString ) ^ 0
+ * C ( P "'" )
+ +
+ C ( ( P "'" + P "r'" + P "R'" ) * ( P "\\'" + 1 - S "'\r" ) ^ 0 * P "'" )
+ )
+ * L ( "}}" )
+
+local DoubleShortString =
+ L ( "{\\PitonStyle{String.Short}{" )
+ * (
+ C ( P "f\"" + P "F\"" )
+ * ( DoubleShortInterpol + DoubleShortPureString ) ^ 0
+ * C ( P "\"" )
+ +
+ C ( ( P "\"" + P "r\"" + P "R\"" ) * ( P "\\\"" + 1 - S "\"\r" ) ^ 0 * P "\"" )
+ )
+ * L ( "}}" )
+
+
+local ShortString = SingleShortString + DoubleShortString
+
+
+local SingleLongString =
+ L "{\\PitonStyle{String.Long}{"
+ * (
+ C ( S "fF" * P "'''" )
+ * ( SingleLongInterpol + SingleLongPureString ) ^ 0
+ * L "}}"
+ * (
+ EOL
+ +
+ L "{\\PitonStyle{String.Long}{"
+ * ( SingleLongInterpol + SingleLongPureString ) ^ 0
+ * L "}}"
+ * EOL
+ ) ^ 0
+ * L "{\\PitonStyle{String.Long}{"
+ * ( SingleLongInterpol + SingleLongPureString ) ^ 0
+ +
+ C ( ( S "rR" ) ^ -1 * P "'''" * ( 1 - P "'''" - P "\r" ) ^ 0 )
+ * L "}}"
+ * (
+ L "{\\PitonStyle{String.Long}{"
+ * C ( ( 1 - P "'''" - P "\r" ) ^ 0 )
+ * L "}}"
+ * EOL
+ ) ^ 0
+ * L "{\\PitonStyle{String.Long}{"
+ * C ( ( 1 - P "'''" - P "\r" ) ^ 0 )
+ )
+ * C ( P "'''" )
+ * L "}}"
+
+
+local DoubleLongString =
+ L "{\\PitonStyle{String.Long}{"
+ * (
+ C ( S "fF" * P "\"\"\"" )
+ * ( DoubleLongInterpol + DoubleLongPureString ) ^ 0
+ * L "}}"
+ * (
+ EOL
+ +
+ L "{\\PitonStyle{String.Long}{"
+ * ( DoubleLongInterpol + DoubleLongPureString ) ^ 0
+ * L "}}"
+ * EOL
+ ) ^ 0
+ * L "{\\PitonStyle{String.Long}{"
+ * ( DoubleLongInterpol + DoubleLongPureString ) ^ 0
+ +
+ C ( ( S "rR" ) ^ -1 * P "\"\"\"" * ( 1 - P "\"\"\"" - P "\r" ) ^ 0 )
+ * L "}}"
+ * (
+ L "{\\PitonStyle{String.Long}{"
+ * C ( ( 1 - P "\"\"\"" - P "\r" ) ^ 0 )
+ * L "}}"
+ * EOL
+ ) ^ 0
+ * L "{\\PitonStyle{String.Long}{"
+ * C ( ( 1 - P "\"\"\"" - P "\r" ) ^ 0 )
+ )
+ * C ( P "\"\"\"" )
+ * L "}}"
+
+
+
+local LongString = SingleLongString + DoubleLongString
+
+
+local Expression =
+ P { "E" ,
+ E = ( 1 - S "{}()[]\r," ) ^ 0
+ * (
+ ( P "{" * V "F" * P "}"
+ + P "(" * V "F" * P ")"
+ + P "[" * V "F" * P "]" ) * ( 1 - S "{}()[]\r," ) ^ 0
+ ) ^ 0 ,
+ F = ( 1 - S "{}()[]\r\"'" ) ^ 0
+ * ( (
+ P "'" * (P "\\'" + 1 - S"'\r" )^0 * P "'"
+ + P "\"" * (P "\\\"" + 1 - S"\"\r" )^0 * P "\""
+ + P "{" * V "F" * P "}"
+ + P "(" * V "F" * P ")"
+ + P "[" * V "F" * P "]"
+ ) * ( 1 - S "{}()[]\r\"'" ) ^ 0 ) ^ 0 ,
+ }
+
+local Param = SkipSpace * K ( identifier , '' ) * SkipSpace
+ * ( K ( P "=" * Expression , 'InitialValues' )
+ + K ( P ":" , '' ) * SkipSpace * K ( letter^1 , 'Name.Type' ))
+ + SkipSpace * K ( alphanum ^ 1 , '' ) * SkipSpace
+
+local Params = Param * ( K ( P "," , '' ) * Param ) ^ 0
+
+local StringDoc = K ( P "\"\"\"" , 'String.Doc' )
+ * ( K ( (1 - P "\"\"\"" - P "\r" ) ^ 0 , 'String.Doc' ) * EOL ) ^ 0
+ * K ( ( 1 - P "\"\"\"" - P "\r" ) ^ 0 * P "\"\"\"" , 'String.Doc' )
+ + K ( P "'''" , 'String.Doc' )
+ * ( K ( (1 - P "'''" - P "\r")^0 , 'String.Doc' ) * EOL ) ^ 0
+ * K ( ( 1 - P "'''" - P "\r")^0 * P "'''" , 'String.Doc' )
+
+local CommentMath = P "$" * K ( ( 1 - S "$\r" ) ^ 1 , 'Comment.Math' ) * P "$"
+
+
+local Comment = L ( "{\\pitonStyleComment {" )
+ * C ( P "#" ) * ( CommentMath + C ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0
+ * L ( "}}" )
+ * ( EOL + -1 )
+
+local CommentLaTeX =
+ P "##"
+ * L "{\\PitonStyle{Comment.LaTeX}{"
+ * Ct ( C ( ( 1 - P "\r" ) ^ 0 ) )
+ * L "}}"
+ * ( EOL + -1 )
+
+local DefFunction =
+ K ( P "def" , 'Keyword' )
+ * Space
+ * K ( identifier , 'Name.Function' )
+ * ( SkipSpace * K ( P "(" , '' ) * Params * K ( P ")" , '' ) ) ^ -1
+ * ( SkipSpace
+ * K ( ( 1 - S ":\r" )^0 , 'Post.Function' )
+ * K ( P ":" , 'Keyword' )
+ * SkipSpace
+ * ( EOL + CommentLaTeX + Comment )
+ * SkipSpace
+ * StringDoc ) ^ -1
+
+local ItemDict = ShortString * SkipSpace * C ( P ":" ) * K ( Expression , 'Dict.Value' )
+
+local ItemOfSet = SkipSpace * ( ItemDict + ShortString ) * SkipSpace
+
+local Set = C ( P "{" )
+ * ItemOfSet * ( C ( P "," ) * ItemOfSet ) ^ 0
+ * C ( P "}" )
+
+
+local Operator = K ( P "!=" + P "==" + P "<<" + P ">>" + S "-~+/*%=<>&.@|" , 'Operator')
+
+local OperatorWord = K ( P "in" + P "is" + P "and" + P "or" + P "not" , 'Operator.Word')
+
+local SyntaxPython =
+ ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 * space ^ -1 *
+ ( ( space^1 * -1 )
+ + EOL
+ + Space
+ + Escape
+ + CommentLaTeX
+ + LongString
+ + Comment
+ + ExceptionInConsole
+ + Set
+ + Delim
+ + Class * ( Space + Punct + EOL )
+ + Namespace * ( Space + Punct + EOL )
+ + ImportAs
+ + RaiseException
+ + Keyword * ( Space + Punct + EOL )
+ + DefFunction
+ + ShortString
+ + Decorator * ( Space + Punct + EOL )
+ + Operator
+ + OperatorWord * ( Space + Punct + EOL )
+ + Builtin * ( Space + Punct + EOL )
+ + Identifier
+ + Number
+ + Word
+ ) ^0 * -1
+
+
+local MinimalSyntax =
+ P { "S" ;
+ S = K ( (1 - P "\r" ) ^ 0 , '') + EOL * S
+ }
+
+
+--- with cctab, all characters including spaces have catcode 12
+local cctab = luatexbase.catcodetables.CatcodeTableOther
+
+function Parse(code)
+ local t = Ct(SyntaxPython) : match(code)
+ if t then else t = Ct(MinimalSyntax) : match(code) end
+ for i = 1 , #t do
+ if type(t[i]) == 'string'
+ then
+ tex.sprint(cctab, t[i])
+ else
+ tex.sprint( t[i][1] )
+ end
+ end
+end
+
+function ParseFile(name)
+ s = ''
+ for line in io.lines(name) do s = s .. '\r' .. line end
+ Parse(s)
+end
+
+
+function define_gobble_syntax(n)
+ GobbleSyntax = ( 1 - P "\r" ) ^ (-n) * C ( ( 1 - P "\r" ) ^0 )
+ * ( C ( P "\r" )
+ * ( 1 - P "\r" ) ^ (-n)
+ * C ( ( 1 - P "\r" ) ^0 )
+ ) ^ 0
+end
+
+function GobbleParse(code)
+ local t = Ct(GobbleSyntax):match(code)
+ local new_code = ""
+ for i = 1 , #t do
+ new_code = new_code .. t[i]
+ end
+ Parse(new_code)
+end
+
+
+function min(x,y)
+ if x <= y
+ then return x
+ else return y
+ end
+end
+
+function add(acc,new_value)
+ return acc + new_value
+end
+
+
+--[[ The following LPEG returns as capture the minimal number of spaces at
+the beginning of the lines of code]]
+AutoGobbleSyntax =
+ ( space ^ 0 * P "\r" ) ^ -1
+ * Cf (
+ (
+ ( P " " ) ^ 0 * P "\r"
+ +
+ Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add )
+ * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 * P "\r"
+ ) ^ 0
+ *
+ ( Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add )
+ * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 ,
+ min
+ )
+
+
+function AutoGobbleParse(code)
+ local n = AutoGobbleSyntax:match(code)
+ if n==0
+ then Parse(code)
+ else define_gobble_syntax(n)
+ GobbleParse(code)
+ end
+end
+
+
+
+
+
+
+
+
+
+
+
diff --git a/macros/luatex/latex/piton/piton.pdf b/macros/luatex/latex/piton/piton.pdf
new file mode 100644
index 0000000000..34024c336e
--- /dev/null
+++ b/macros/luatex/latex/piton/piton.pdf
Binary files differ