% \iffalse -*- coding: utf-8 ; -*- \fi 
% \iffalse meta-comment
%
% Copyright (C) 2022-2024 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
% 
%<*batchfile> 
\begingroup
\input l3docstrip.tex
\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,svgnames]{xcolor}
\usepackage{caption,tabularx,tcolorbox,luacolor,lua-ul,upquote}
\def\emphase{\bgroup\color{RoyalPurple}\let\next=}
\fvset{commandchars=\~\#\@,formatcom=\color{gray}}
\captionsetup{labelfont = bf}
\usepackage{ragged2e}
\usepackage[footnotehyper]{piton} 
\PitonOptions
  { 
    splittable = 4 ,
    math-comments,
    begin-escape = ! ,
    end-escape = ! ,
    begin-escape-math = \( , 
    end-escape-math = \) ,
    detected-commands = highLight
  }

\parindent 0pt
\skip\footins = 2\bigskipamount

\def\CC{{C\nolinebreak[4]\hspace{-.05em}\raisebox{.4ex}{\tiny\bfseries ++}}}

\usepackage{makeidx}
\makeindex

\NewDocumentCommand{\indexcommand}{m}{\index{#1@\texttt{\textbackslash #1}}}

\NewDocumentCommand{\indexenv}{m}{\index{#1@\texttt{\{#1\}}}}


\PitonOptions{gobble=2}

\EnableCrossrefs

\begin{document}
\DocInput{piton.dtx}
\end{document}
%</driver>
% \fi
% \iffalse
%<*STY>
% \fi
\def\PitonFileVersion{2.6}
\def\PitonFileDate{2024/02/27}
% \iffalse
%</STY>
%<*LUA>
-- Version 2.6 of 2024/02/27
%</LUA>
%\fi
%
% \catcode`\" = 11 
% 
% \title{The package \pkg{piton}\thanks{This document corresponds to the
% version~\PitonFileVersion\space of \pkg{piton}, at the date of~\PitonFileDate.}} 
% \author{F. Pantigny \\ \texttt{fpantigny@wanadoo.fr}}
%
% \maketitle
%
% \begin{abstract}
% The package \pkg{piton} provides tools to typeset computer listings in Python,
% OCaml, C and SQL 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, OCaml, C
% or SQL listings and typesets them with syntactic highlighting. Since it uses
% the Lua of LuaLaTeX, 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 example of code typeset by \pkg{piton}, with the environment |{Piton}|.
%
% \bigskip
%
%    \begin{Piton}
% from math import pi
%
% def arctan(x,n=10):
%    """Compute the mathematical value of arctan(x)
%
%    n is the number of terms in 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{Piton}
% 
% 
% \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, for instance in a |texmf| tree. However, the best is to install
% \pkg{piton} with a TeX distribution such as MiKTeX, TeX Live or MacTeX.
% 
% \section{Use of the package}
%
% \subsection{Loading the package}
% 
% The package \pkg{piton} should be loaded with the classical command
% |\usepackage|: |\usepackage{piton}|.
%
% \smallskip
% Nevertheless, we have two remarks:
% \begin{itemize}
% \item the package \pkg{piton} uses the package \pkg{xcolor} (but \pkg{piton}
% does \emph{not} load \pkg{xcolor}: if \pkg{xcolor} is not loaded before the
% |\begin{document}|, a fatal error will be raised).
% \item the package \pkg{piton} must be used with LuaLaTeX exclusively: if
% another LaTeX engine (|latex|, |pdflatex|, |xelatex|,\dots ) is used, a
% fatal error will be raised.
% \end{itemize}
%
% \subsection{Choice of the computer language}
%
% In current version, the package \pkg{piton} supports four computer languages:
% Python, OCaml, SQL and C (in fact \CC). It supports also a special language
% called ``|minimal|'': cf. p.~\pageref{minimal}.
%
% \smallskip
% By default, the language used is Python.
%
% \smallskip
% \index{language (key)}
% It's possible to change the current language with the command |\PitonOptions|
% and its key |language|: |\PitonOptions{language = C}|.
%
% \smallskip
% For the developpers, let's say that the name of the current language is stored
% (in lower case) in the L3 public variable |\l_piton_language_str|.
%
% \smallskip
% In what follows, we will speak of Python, but the features described also
% apply to the other languages.
% 
% \subsection{The tools provided to the user}
%
% \indexenv{Piton}
% 
% The package \pkg{piton} provides several tools to typeset Python code: the
% command |\piton|, the environment |{Piton}| and the command |\PitonInputFile|.
%
% \begin{itemize}\setlength{\fboxsep}{1pt}
% \item The command \colorbox{gray!20}{\texttt\textbackslash piton} should be
% used to typeset small pieces of code inside a paragraph. For example:
% 
% {\color{gray}\verb|\piton{def square(x): return x*x}|}\qquad 
% \piton{def square(x): return x*x}
%
% The syntax and particularities of the command |\piton| are detailed below.
%
% \item The environment \colorbox{gray!20}{\ttfamily\{Piton\}} should be used to
% typeset multi-lines code. Since it takes its argument in a verbatim mode, it
% can't be used within the argument of a LaTeX command. For sake of
% customization, it's possible to define new environments similar to the
% environment |{Piton}| with the command |\NewPitonEnvironment|:
% cf.~\ref{NewPitonEnvironment} p.~\pageref{NewPitonEnvironment}.
%
% \item The command \colorbox{gray!20}{\ttfamily\textbackslash PitonInputFile}
% is used to insert and typeset a external file.
%
% It's possible to insert only a part of the file: cf.
% part~\ref{part-of-a-file}, p.~\pageref{part-of-a-file}. 
%
% The key |path| of the command |\PitonOptions| specifies a path where the files
% included by |\PitonInputFile| will be searched.
% \end{itemize}
%
% \subsection{The syntax of the command \textbackslash piton}
% 
% \indexcommand{piton}
% 
% In fact, the command |\piton| is provided with a double syntax. It may be used
% as a standard command of LaTeX taking its argument between curly braces
% (|\piton{...}|) but it may also be used with a syntax similar to the syntax of
% the command
% |\verb|, that is to say with the argument delimited by two identical characters (e.g.: \verb!\piton|...|!).
% 
% \begin{itemize}
% \item {\color{blue} \textsf{Syntax} \verb|\piton{...}|}\par\nobreak
% When its argument is given between curly braces, the command |\piton| does not
% take its argument in verbatim mode. In particular:
% \begin{itemize}
% \item several consecutive spaces will be replaced by only one space (and the
% also the character of end on line),
% 
% {\color{cyan} but the command |\|␣ is provided to force the insertion of a space};
%
% \item it's not possible to use |%| inside the argument,
%
% {\color{cyan} but the command |\%| is provided to insert a |%|};
%
% \item the braces must be appear by pairs correctly nested
%
% {\color{cyan} but the commands |\{| and |\}| are also provided for individual braces};
%
% \item the LaTeX commands\footnote{That concerns the commands beginning with a
% backslash but also the active characters (with catcode equal to 13).} are
% fully expanded and not executed,
%
% {\color{cyan} so it's possible to use |\\| to insert a backslash}.
% \end{itemize}
%
%
% The other characters (including |#|, |^|, |_|, |&|, |$| and |@|)
% must be inserted without backslash.
% 
% \bigskip
%\begin{tabular}{>{\color{gray}}w{l}{75mm}@{\hspace*{1cm}}l}
% \omit Examples : \hfil \\
% \noalign{\vskip1mm}
% \verb|\piton{MyString = '\\n'}| & 
% \piton{MyString = '\\n'} \\
% \verb|\piton{def even(n): return n\%2==0}| & 
% \piton{def even(n): return n\%2==0} \\
% \verb|\piton{c="#"    # an affectation }| & 
% \piton{c="#"     # an affectation } \\
% \verb|\piton{c="#" \ \ \ # an affectation }| & 
% \piton{c="#" \ \ \ # an affectation } \\
% \verb|\piton{MyDict = {'a': 3, 'b': 4 }}| &
% \piton{MyDict = {'a': 3, 'b': 4 }}
% \end{tabular}
%
% \bigskip
% It's possible to use the command |\piton| in the arguments of a
% LaTeX command.\footnote{For example, it's possible to use the command
% \texttt{\textbackslash piton} in a footnote. Example :
% \piton{s = 'A string'}.}
%
% \bigskip
% \item {\color{blue} \textsf{Syntaxe} \verb!\piton|...|!}\par\nobreak
%
% When the argument of the command |\piton| is provided between two identical
% characters, that argument is taken in a \emph{verbatim mode}. Therefore, with
% that syntax, the command |\piton| can't be used within the argument of another
% command. 
%
% \medskip
%
% \begin{tabular}{>{\color{gray}}w{l}{75mm}@{\hspace*{1cm}}l}
% \omit Examples : \hfil \\
% \noalign{\vskip1mm}
% \verb!\piton|MyString = '\n'|! & 
% \piton|MyString = '\n'| \\
% \verb|\piton!def even(n): return n%2==0!| & 
% \piton!def even(n): return n%2==0! \\
% \verb|\piton+c="#"    # an affectation +| & 
% \piton+c="#"     # an affectation + \\
% \verb|\piton?MyDict = {'a': 3, 'b': 4}?| &
% \piton!MyDict = {'a': 3, 'b': 4}!
% \end{tabular}
%
% \end{itemize}
% 
% \section{Customization}
%
% With regard to the font used by \pkg{piton} in its listings, it's only the
% current monospaced font. The package \pkg{piton} merely uses internally the
% standard LaTeX command |\texttt|.
%
% \subsection{The keys of the command \textbackslash PitonOptions}
%
%
% \NewDocumentCommand{\Definition}{m}
%   {{\setlength{\fboxsep}{1pt}\colorbox{gray!20}{\ttfamily \vphantom{gl}#1}}}
%
% \indexcommand{PitonOptions}
% 
% The command |\PitonOptions| takes in as argument a comma-separated list of
% \textsl{key=value} pairs. The scope of the settings done by that command is
% the current TeX group.\footnote{We remind that a LaTeX environment is, in
% particular, a TeX group.}
%
% These keys may also be applied to an individual environment |{Piton}| (between
% square brackets).
%
% \begin{itemize}
% \item The key \Definition{language} speficies which computer language is
% considered (that key is case-insensitive). Five values are allowed :
% |Python|, |OCaml|, |C|, |SQL| and |minimal|. The initial value is |Python|.
% 
% \item \index{path} The key \Definition{path} specifies a path where the files
% included by |\PitonInputFile| will be searched.
% 
% \item \index{gobble}\label{gobble} The key \Definition{gobble} takes in as
% value a positive integer~$n$: the first $n$ characters are discarded (before
% the process of highlightning of the code) for each line of the environment
% |{Piton}|. These characters are not necessarily spaces.
%
% \item \index{auto-gobble}\index{gobble!auto-gobble} When the key
% \Definition{auto-gobble} is in force, the extension \pkg{piton} computes the
% minimal value $n$ of the number of consecutive spaces beginning each (non
% empty) line of the environment |{Piton}| and applies |gobble| with that value
% of~$n$.
%
% \item \index{env-gobble}\index{gobble!env-gobble}
% When the key \Definition{env-gobble} is in force, \pkg{piton} analyzes the last
% line of the environment |{Piton}|, that is to say the line which contains
% |\end{Piton}| and determines whether that line contains only spaces followed
% by the |\end{Piton}|. If we are in that situation, \pkg{piton} computes the
% number~$n$ of spaces on that line and applies |gobble| with that value of~$n$.
% The name of that key comes from \emph{environment gobble}: the effect of
% gobble is set by the position of the commands |\begin{Piton}| and
% |\end{Piton}| which delimit the current environment.
%
% \item \index{write} The key \Definition{write} takes in as argument a name of
% file (with its extension) and write the content\footnote{In fact, it's not
% exactly the body of the environment but the value of |piton.get_last_code()|
% which is the body without the overwritten LaTeX formatting instructions (cf.
% the part~\ref{API}, p.~\pageref{API}).} of the current environment in
% that file. At the first use of a file by \pkg{piton}, it is erased.
%
% \item \index{path-write}\colorbox{yellow!50}{\bfseries New 2.5}\enskip The key
% \Definition{path-write} specifies a path where the files written by the key
% |write| will be written.
%
% \item \index{line-numbers} The key \Definition{line-numbers} activates the
% line numbering in the environments |{Piton}| and in the listings resulting
% from the use of |\PitonInputFile|.
% 
% In fact, the key |line-numbers| has several subkeys.
% \begin{itemize}
% \item With the key \Definition{line-numbers/skip-empty-lines}, the empty lines
% are considered as non existent for the line numbering (if the key |/absolute|
% is in force, the key |/skip-empty-lines| is no-op in |\PitonInputFile|). The
% initial value of that key is |true| (and not |false|).\footnote{For the
% language Python, the empty lines in the docstrings are taken into account (by
% design).}
% \item With the key \Definition{line-numbers/label-empty-lines}, the labels
% (that is to say the numbers) of the empty lines are displayed. If the key
% |/skip-empty-line| is in force, the clé |/label-empty-lines| is no-op. The
% initial value of that key is~|true|.
% \item With the key \Definition{line-numbers/absolute}, in the listings
% generated in |\PitonInputFile|, the numbers of the lines displayed are
% \emph{absolute} (that is to say: they are the numbers of the lines in the
% file). That key may be useful when |\PitonInputFile| is used to insert only a
% part of the file (cf. part~\ref{part-of-a-file}, p.~\pageref{part-of-a-file}).
% The key |/absolute| is no-op in the environments |{Piton}| and those created
% by |\NewPitonEnvironment|.
% \item The key \Definition{line-numbers/start} requires that the line numbering
% begins to the value of the key. 
% \item With the key \Definition{line-numbers/resume}, the counter of lines is
% not set to zero at the beginning of each environment |{Piton}| or use of
% |\PitonInputFile| as it is otherwise. That allows a numbering of the lines
% across several environments.
% \item The key \Definition{line-numbers/sep} is the horizontal distance between
% the numbers of lines (inserted by |line-numbers|) and the beginning of the
% lines of code. The initial value is 0.7~em.
% \end{itemize}
%
% For convenience, a mechanism of factorisation of the prefix |line-numbers| is
% provided. That means that it is possible, for instance, to write:
% \begin{Verbatim}
% \PitonOptions
%   {
%     line-numbers = 
%       { 
%         skip-empty-lines = false ,
%         label-empty-lines = false ,
%         sep = 1 em
%       }
%   }
% \end{Verbatim}
%
%
% \item \index{left-margin} The key \Definition{left-margin} corresponds to a
% margin on the left. That key may be useful in conjonction with the key
% |line-numbers| if one does not want the numbers in an overlapping position on
% the left. 
%
% It's possible to use the key |left-margin| with the value |auto|. With that
% value, if the key |line-numbers| is in force, a margin will be automatically
% inserted to fit the numbers of lines. See an example part
% \ref{example-numbering} on page~\pageref{example-numbering}.
%
% \item \index{background-color} The key \Definition{background-color} sets the
% background color of the environments |{Piton}| and the listings produced by
% |\PitonInputFile| (it's possible to fix the width of that background with the
% key |width| described below). 
%
% \smallskip
% The key |background-color| supports also as value a \emph{list} of colors. In
% this case, the successive rows are colored by using the colors of the list in
% a cyclic way.
%
% \emph{Example} : |\PitonOptions{background-color = {gray!5,white}}|
%
% The key |background-color| accepts a color defined «on the fly». For example,
% it's possible to write |background-color = [cmyk]{0.1,0.05,0,0}|.
%
% \item \index{prompt-background-color} With the key
% \Definition{prompt-background-color}, \pkg{piton} adds a 
% color background to the lines beginning with the prompt ``|>>>|'' (and its
% continuation ``|...|'') characteristic of the Python consoles with
% \textsc{repl} (\emph{read-eval-print loop}).
%
% \item \index{width} The key \Definition{width} will fix the width of the
% listing. That width applies to the colored backgrounds specified by
% |background-color| and |prompt-background-color| but also for the automatic
% breaking of the lines (when required by |break-lines|: cf.~\ref{line-breaks},
% p.~\pageref{line-breaks}).
%
% That key may take in as value a numeric value but also the special
% value~|min|. With that value, the width will be computed from the maximal
% width of the lines of code. Caution: the special value~|min| requires two
% compilations with LuaLaTeX\footnote{The maximal width is computed during the
% first compilation, written on the |aux| file and re-used during the second
% compilation. Several tools such as |latexmk| (used by Overleaf) do
% automatically a sufficient number of compilations.}.
%
% For an example of use of |width=min|, see the section~\ref{example-comments},
% p.~\pageref{example-comments}. 
%
%
% \item \index{show-spaces-in-strings} When the key
% \Definition{show-spaces-in-strings} is activated, the spaces in the 
% strings of characters\footnote{With the language Python that feature applies
% only to the short strings (delimited by~\verb|'| or~\verb|"|). In OCaml, that
% feature does not apply to the \emph{quoted strings}.} are replaced by the
% character~␣ (U+2423 : \textsc{open box}). Of course, that character~U+2423
% must be present in the monospaced font which is used.\footnote{The package
% \pkg{piton} simply uses the current monospaced font. The best way to change
% that font is to use the command \texttt{\textbackslash setmonofont} of the
% package \pkg{fontspec}.}\par\nobreak \begingroup
% \PitonOptions{show-spaces-in-strings} Example : 
% \piton|my_string = 'Very good answer'| \endgroup
%
% With the key \index{show-spaces} \Definition{show-spaces}, all the spaces are
% replaced by U+2423 (and no line break can occur on those ``visible spaces'',
% even when the key |break-lines|\footnote{cf. \ref{line-breaks}
% p.~\pageref{line-breaks}} is in force).
% \end{itemize}
%
% \bigskip
% \begingroup
% \fvset{commandchars=\~\&\@,formatcom=\small\color{gray}}
% \begin{Verbatim}
% ~emphase&\begin{Piton}[language=C,line-numbers,auto-gobble,background-color = gray!15]@
%     void bubbleSort(int arr[], int n) {
%         int temp;
%         int swapped;
%         for (int i = 0; i < n-1; i++) {
%             swapped = 0;
%             for (int j = 0; j < n - i - 1; j++) {
%                 if (arr[j] > arr[j + 1]) {
%                     temp = arr[j];
%                     arr[j] = arr[j + 1];
%                     arr[j + 1] = temp;
%                     swapped = 1; 
%                 }
%             }
%             if (!swapped) break;
%         }
%     }   
% \end{Piton}
% \end{Verbatim}
% \endgroup
%
% \begingroup
% \PitonOptions{language=C,line-numbers,gobble=6,background-color = gray!15}
%     \begin{Piton}
%     void bubbleSort(int arr[], int n) {
%         int temp;
%         int swapped;
%         for (int i = 0; i < n-1; i++) {
%             swapped = 0;
%             for (int j = 0; j < n - i - 1; j++) {
%                 if (arr[j] > arr[j + 1]) {
%                     temp = arr[j];
%                     arr[j] = arr[j + 1];
%                     arr[j + 1] = temp;
%                     swapped = 1; 
%                 }
%             }
%             if (!swapped) break;
%         }
%     }   
%     \end{Piton}
% \endgroup
%
% 
% \bigskip
% The command |\PitonOptions| provides in fact several other keys which will be
% described further (see in particular the ``Pages breaks and line breaks''
% p.~\pageref{breakable}). 
%
% \subsection{The styles}
%
% \label{styles}
%
% \subsubsection{Notion of style}
%
% 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.\footnote{We remind that a LaTeX environment is, in particular, a TeX group.}
%
% \bigskip
% \indexcommand{SetPitonStyle}
% 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. That code
% uses the command |\highLight| of \pkg{lua-ul} (that package requires also the
% package \pkg{luacolor}).
%
% \begin{verbatim}
% \SetPitonStyle{ Name.Function = \bfseries \highLight[red!50] }
% \end{verbatim}
%
% In that example, |\highLight[red!50]| must be considered as the name of a
% LaTeX command which takes in exactly one argument, since, usually, it is used
% with |\highLight[red!50]{...}|.
%
% \medskip
% \begingroup
% \SetPitonStyle 
%   { Name.Function = \bfseries \highLight[red!50] }
% With that setting, we will have : \piton{def cube(x) : return x * x * x }
% \endgroup
% 
% \bigskip
% The different styles, and their use by \pkg{piton} in the different languages
% which it supports (Python, OCaml, C, SQL and ``|minimal|''), are described in
% the part \ref{Semantic}, starting at the page \pageref{Semantic}. 
% 
%
% \bigskip
% \indexcommand{PitonStyle}
% The command |\PitonStyle| takes in as argument the name of a style and allows
% to retrieve the value (as a list of LaTeX instructions) of that style.
%
% \smallskip
% For example, it's possible to write |{\PitonStyle{Keyword}{function}}| and we
% will have the word {\PitonStyle{Keyword}{function}} formatted as a keyword.
%
% \smallskip
% The syntax |{\PitonStyle{|\textsl{\texttt{style}}|}{...}}| is mandatory in
% order to be able to deal both with the semi-global commands and the commands
% with arguments which may be present in the definition of the style
% \texttt{\textsl{style}}. 
%
% \bigskip
% \subsubsection{Global styles and local styles}
%
% A style may be defined globally with the command |\SetPitonStyle|. That means
% that it will apply to all the informatic languages that use that style.
%
% \bigskip
% For example, with the command
% \begin{Verbatim}
% \SetPitonStyle{Comment = \color{gray}}
% \end{Verbatim}
% all the comments will be composed in gray in all the listings, whatever
% informatic language they use (Python, C, OCaml, etc.).
% 
% \bigskip
% But it's also possible to define a style locally for a given informatic
% langage by providing the name of that language as optional argument (between
% square brackets) to the command |\SetPitonStyle|.\footnote{We recall, that, in
% the package \pkg{piton}, the names of the informatic languages are
% case-insensitive.}
%
% \bigskip
% For example, with the command
% \begin{Verbatim}
% \SetPitonStyle~emphase#[SQL]@{Keywords = \color[HTML]{006699} \bfseries \MakeUppercase}
% \end{Verbatim}
% the keywords in the SQL listings will be composed in capital letters, even if
% they appear in lower case in the LaTeX source (we recall that, in SQL, the
% keywords are case-insensitive).
%
% \bigskip
% As expected, if an informatic language uses a given style and if that style has
% no local definition for that language, the global version is used. That notion
% of ``global style'' has no link with the notion of global definition in TeX
% (the notion of \emph{group} in TeX).\footnote{As regards the TeX groups, the
% definitions done by \texttt{\textbackslash SetPitonStyle} are always local.}
% 
% \bigskip
% The package \pkg{piton} itself (that is to say the file |piton.sty|) defines
% all the styles globally. 
%
% \bigskip
%
% \subsubsection{The style UserFunction}
%
% \index{UserFunction (style)}
% 
% The extension \pkg{piton} provides a special style called~|UserFunction|. That
% style applies to the names of the functions previously defined by the user
% (for example, in Python, these names are those following the keyword
% \piton{def} in a previous Python listing). The initial value of that style is
% empty, and, therefore, the names of the functions are formatted as standard
% text (in black). However, it's possible to change the value of that style, as
% any other style, with the command |\SetPitonStyle|.
%
% \medskip
% In the following example, we fix as value for that style |UserFunction| the
% initial value of the style |Name.Function| (which applies to the name of
% the functions, \emph{at the moment of their definition}).
%
% \begingroup
%
% \begin{Verbatim}
% \SetPitonStyle{~emphase#UserFunction@ = \color[HTML]{CC00FF}}
% \end{Verbatim}
%
% \SetPitonStyle{UserFunction = \color[HTML]{CC00FF}}
%
% \begin{Piton}
% def transpose(v,i,j):
%     x = v[i]
%     v[i] = v[j]
%     v[j] = x 
%
% def passe(v):
%     for in in range(0,len(v)-1):
%         if v[i] > v[i+1]:
%             transpose(v,i,i+1)
% \end{Piton}
%
% \endgroup
%
% As one see, the name |transpose| has been highlighted because it's the name of
% a Python function previously defined by the user (hence the name
% |UserFunction| for that style).
%
% \PitonClearUserFunctions[Python]
%
% \bigskip
% \begin{small}
% Of course, the list of the names of Python functions previously défined is
% kept in the memory of LuaLaTeX (in a global way, that is to say independently
% of the TeX groups). The extension \pkg{piton} provides a command to clear that
% list : it's the command |\PitonClearUserFunctions|. When it is used without
% argument, that command is applied to all the informatic languages used by the
% user but it's also possible to use it with an optional argument (between
% square brackets) which is a list of informatic languages to which the command
% will be applied.\footnote{We remind that, in \pkg{piton}, the name of the
% informatic languages are case-insensitive.}
% \end{small}
% 
% \subsection{Creation of new environments}
%
% \label{NewPitonEnvironment}
% \indexcommand{NewPitonEnvironment}
% 
% 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}| with the classical commands
% |\newenvironment| (of standard LaTeX) or |\NewDocumentEnvironment| (of
% LaTeX3). 
%
% 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|.\footnote{However, the specifier of argument |b|
% (used to catch the body of the environment as a LaTeX argument) is
% not allowed.}
%
% 
% \bigskip
% With the following instruction, a new environment |{Python}| will be
% constructed with the same behaviour as |{Piton}|:
%
% {\color{gray}\verb|\NewPitonEnvironment{Python}{O{}}{\PitonOptions{#1}}{}|}
% 
% \bigskip
% If one wishes to format Python code in a box of \pkg{tcolorbox}, it's possible
% to define an environment |{Python}| with the following code (of course, the
% package \pkg{tcolorbox} must be loaded).
%
%\begin{verbatim}
% \NewPitonEnvironment{Python}{}
%   {\begin{tcolorbox}}
%   {\end{tcolorbox}}
% \end{verbatim}
%
% \bigskip
% With this new environment |{Python}|, it's possible to write:
%
% \begin{Verbatim}
% ~emphase#\begin{Python}@
% def square(x):
%     """Compute the square of a number"""
%     return x*x
% ~emphase#\end{Python}@
% \end{Verbatim}
%
% \NewPitonEnvironment{Python}{}
%   {\begin{tcolorbox}}
%   {\end{tcolorbox}}
%
% \begin{Python}
% def square(x):
%     """Compute the square of a number"""
%     return x*x
% \end{Python}
%
%
% \section{Advanced features}
%
% \subsection{Page breaks and line breaks}
%
% \label{breakable}
%
% \subsubsection{Page breaks}
% \index{splittable}
%
% By default, the listings produced by the environment |{Piton}| and the command
% |\PitonInputFile| are not breakable.
%
% However, the command |\PitonOptions| provides the key \Definition{splittable}
% to allow such breaks.
%
% \begin{itemize}
% \item If the key |splittable| is used without any value, the
% listings are breakable everywhere.
% \item If the key |splittable| is used with a numeric value~$n$ (which must be
% a non-negative integer number), the listings are breakable but no break will
% occur within the first $n$ lines and within the last $n$ lines. Therefore,
% |splittable=1| is equivalent to |splittable|.
% \end{itemize}
%
% \medskip
% Even with a background color (set by the key |background-color|), the pages
% breaks are allowed, as soon as the key |splittable| is in force.\footnote{With
% the key |splittable|, the environments \texttt{\{Piton\}} are breakable, even
% within a (breakable) environment of \pkg{tcolorbox}. Remind that an
% environment of \pkg{tcolorbox} included in another environment of
% \pkg{tcolorbox} is \emph{not} breakable, even when both environments use the
% key |breakable| of \pkg{tcolorbox}.}
% 
% \subsubsection{Line breaks}
% 
% \label{line-breaks}
% 
% By default, the elements produced by \pkg{piton} can't be broken by an end on
% line. However, there are keys to allow such breaks (the possible breaking
% points are the spaces, even the spaces in the Python strings).
% \begin{itemize}
% \item \index{break-lines!break-lines-in-piton} With the key
% \Definition{break-lines-in-piton}, the line breaks are allowed in the command
% |\piton{...}| (but not in the command \verb+\piton|...|+, that is to say the
% command |\piton| in verbatim mode).
% \item \index{break-lines!break-lines-in-Piton} With the key
% \Definition{break-lines-in-Piton}, the line breaks are allowed in the
% environment |{Piton}| (hence the capital letter |P| in the name) and in the
% listings produced by |\PitonInputFile|.
% \item \index{break-lines} The key \Definition{break-lines} is a conjonction of
% the two previous keys. 
% \end{itemize}
% 
% \bigskip 
% The package \pkg{piton} provides also several keys to control the appearance
% on the line breaks allowed by |break-lines-in-Piton|.
%
% \begin{itemize}
% \item \index{indent-broken-lines} With the key
% \Definition{indent-broken-lines}, the indentation of a 
% broken line is respected at carriage return.
%
% \item The key \Definition{end-of-broken-line} corresponds to the symbol placed
% at the end of a broken line. The initial value is:
% |\hspace*{0.5em}\textbackslash|.
%
% \item \index{continuation-symbol} The key \Definition{continuation-symbol}
% corresponds to the symbol placed at each carriage return. The initial value
% is: |+\;| (the command |\;| inserts a small horizontal space).
%
% \item \index{continuation-symbol-on-indentation} 
% The key \Definition{continuation-symbol-on-indentation} corresponds to
% the symbol placed at each carriage return, on the position of the indentation
% (only when the key |indent-broken-line| is in force). The initial value is:
% |$\hookrightarrow\;$|.
% \end{itemize}
%
%
% \bigskip
% The following code has been composed with the following tuning:
%
% \begin{Verbatim}
% \PitonOptions{width=12cm,break-lines,indent-broken-lines,background-color=gray!15}
% \end{Verbatim}
%
% \begin{center}
% \PitonOptions{width=12cm,break-lines,indent-broken-lines,background-color=gray!15}
% \begin{Piton}
% def dict_of_list(l):
%     """Converts a list of subrs and descriptions of glyphs in a dictionary"""
%     our_dict = {}
%     for list_letter in l:
%         if (list_letter[0][0:3] == 'dup'): # if it's a subr
%             name = list_letter[0][4:-3]
%             print("We treat the subr of number " + name)
%         else:
%             name = list_letter[0][1:-3] # if it's a glyph
%             print("We treat the glyph of number " + name)
%         our_dict[name] = [treat_Postscript_line(k) for k in list_letter[1:-1]]
%     return dict
% \end{Piton}
% \end{center}
%
%
% \bigskip
% \subsection{Insertion of a part of a file}
%
% \label{part-of-a-file}
% \indexcommand{PitonInputFile}
%
% The command |\PitonInputFile| inserts (with formating) the content of a file.
% In fact, it's possible to insert only \emph{a part} of that file. Two
% mechanisms are provided in this aim.
% \begin{itemize}
% \item It's possible to specify the part that we want to insert by the numbers
% of the lines (in the original file).
% \item It's also possible to specify the part to insert with textual markers.
% \end{itemize}
% In both cases, if we want to number the lines with the numbers of the
% lines in the file, we have to use the key |line-numbers/absolute|.
%
% \subsubsection{With line numbers}
%
% The command |\PitonInputFile| supports the keys \Definition{first-line} and
% \Definition{last-line} in order to insert only the part of file between the
% corresponding lines. Not to be confused with the key |line-numbers/start|
% which fixes the first line number for the line numbering. In a sens,
% |line-numbers/start| deals with the output whereas |first-line| and
% |last-line| deal with the input.
%
% \subsubsection{With textual markers}
%
% \index{marker/beginning}
% \index{marker/end}
%
% In order to use that feature, we first have to specify the format of the
% markers (for the beginning and the end of the part to include) with the keys
% \Definition{marker-beginning} and \Definition{marker-end} (usually with the
% command |\PitonOptions|). 
%
%
% \medskip
% Let us take a practical example.
%
% \medskip
% We assume that the file to include contains solutions to exercises of
% programmation on the following model.
%
% \begin{Verbatim}[formatcom=\small\color{gray}]
% ~#[Exercise 1] Iterative version
% def fibo(n):
%     if n==0: return 0 
%     else:
%         u=0
%         v=1
%         for i in range(n-1):
%             w = u+v
%             u = v
%             v = w
%         return v
% ~#<Exercise 1>
% \end{Verbatim}
%
% The markers of the beginning and the end are the strings |#[Exercise 1]| and
% |#<Exercise 1>|. The string ``|Exercise 1|'' will be called the \emph{label}
% of the exercise (or of the part of the file to be included).
%
% In order to specify such markers in \pkg{piton}, we will use the keys
% |marker/beginning| and |marker/end| with the following instruction (the
% character |#| of the comments of Python must be inserted with the protected
% form |\#|). 
%
% \begin{Verbatim}
% \PitonOptions{ ~emphase#marker/beginning@ = \~#[~#1] , ~emphase#marker/end@ = \~#<~#1> } 
% \end{Verbatim}
%
% As one can see, |marker/beginning| is an expression corresponding to the
% mathematical function which transforms the label (here |Exercise 1|) into the
% the beginning marker (in the example |#[Exercise 1]|). The string |#1|
% corresponds to the occurrences of the argument of that function, which the
% classical syntax in TeX. Idem for |marker/end|.
%
% \bigskip 
% Now, you only have to use the key \Definition{range} of |\PitonInputFile| to
% insert a marked content of the file.
%
% \smallskip
% \begin{Verbatim}
% \PitonInputFile[~emphase#range = Exercise 1@]{~textsl#file_name@}
% \end{Verbatim}
%
% \medskip
% \begin{Piton}
% def fibo(n):
%     if n==0: return 0 
%     else:
%         u=0
%         v=1
%         for i in range(n-1):
%             w = u+v
%             u = v
%             v = w
%         return v
% \end{Piton}
%
% \vspace{1cm}
% \index{marker/include-line}
% The key \Definition{marker/include-line} requires the insertion of the lines
% containing the markers.
%
% \begin{Verbatim}
% \PitonInputFile[~emphase#marker/include-lines@,range = Exercise 1]{~textsl#file_name@}
% \end{Verbatim}
%
% \begin{Piton}
% #[Exercise 1] Iterative version
% def fibo(n):
%     if n==0: return 0 
%     else:
%         u=0
%         v=1
%         for i in range(n-1):
%             w = u+v
%             u = v
%             v = w
%         return v
% #<Exercise 1>
% \end{Piton}
%
%
% \bigskip
% \index{begin-range}
% \index{end-range}
% In fact, there exist also the keys \Definition{begin-range} and
% \Definition{end-range} to insert several marked contents at the same time.
%
% For example, in order to insert the solutions of the exercises~3 to~5, we will
% write (if the file has the correct structure!):
%
%
% \begin{Verbatim}
% \PitonInputFile[~emphase#begin-range = Exercise 3, end-range = Exercise 5@]{~textsl#file_name@}
% \end{Verbatim}
%
%
%
% \subsection{Highlighting some identifiers}
%
% \label{SetPitonIdentifier}
%
% \colorbox{yellow!50}{\bfseries Modification 2.4}\par\nobreak
%
% \smallskip
% The command |\SetPitonIdentifier| allows to change the formatting of some
% identifiers.
%
% \smallskip
% That command takes in three arguments: 
%
% \begin{itemize}
% \item The optionnal argument (within square brackets) specifies the informatic
% langage. If this argument is not present, the tunings done by
% |\SetPitonIdentifier| will apply to all the informatic langages of
% \pkg{piton}.\footnote{We recall, that, in the package \pkg{piton}, the
% names of the informatic languages are case-insensitive.}
%
% \item The first mandatory argument is a comma-separated list of names of
% identifiers.
%
% \item The second mandatory argument is a list of LaTeX instructions of the
% same type as \pkg{piton} ``styles'' previously presented (cf~\ref{styles}
% p.~\pageref{styles}). 
% \end{itemize}
% 
% \emph{Caution}: Only the identifiers may be concerned by that key. The
% keywords and the built-in functions won't be affected, even if their name
% appear in the first argument of the command |\SetPitonIdentifier|.
% 
% \begin{Verbatim}
% ~emphase#\SetPitonIdentifier{l1,l2}{\color{red}}@
% \begin{Piton}
% def tri(l):
%     """Segmentation sort"""
%     if len(l) <= 1:
%         return l
%     else:
%         a = l[0]
%         l1 = [ x for x in l[1:] if x < a  ]
%         l2 = [ x for x in l[1:] if x >= a ]
%         return tri(l1) + [a] + tri(l2)
% \end{Piton}
% \end{Verbatim}
%
%
% \bigskip
%
% \begingroup
%
% \SetPitonIdentifier{l1,l2}{\color{red}}
%
% \begin{Piton}
% def tri(l):
%     """Segmentation sort"""
%     if len(l) <= 1:
%         return l
%     else:
%         a = l[0]
%         l1 = [ x for x in l[1:] if x < a  ]
%         l2 = [ x for x in l[1:] if x >= a ]
%         return tri(l1) + [a] + tri(l2)
% \end{Piton}
%
% \endgroup
% 
% \bigskip
% By using the command |\SetPitonIdentifier|, it's possible to add other
% built-in functions (or other new keywords, etc.) that will be detected by
% \pkg{piton}.
%
%
% \begin{Verbatim}
% ~emphase#\SetPitonIdentifier[Python]@
%   {cos, sin, tan, floor, ceil, trunc, pow, exp, ln, factorial}
%   {\PitonStyle{Name.Builtin}}
%
% \begin{Piton}
% from math import *
% cos(pi/2) 
% factorial(5)
% ceil(-2.3) 
% floor(5.4) 
% \end{Piton}
% \end{Verbatim}
%
% \begingroup
%
% \SetPitonIdentifier[Python]
%   {cos, sin, tan, floor, ceil, trunc, pow, exp, ln, factorial}
%   {\PitonStyle{Name.Builtin}}
%
% \begin{Piton}
% from math import *
% cos(pi/2) 
% factorial(5)
% ceil(-2.3) 
% floor(5.4) 
% \end{Piton}
%
%
% \endgroup
%
%
% \subsection{Mechanisms to escape to LaTeX}
%
% \index{escapes to LaTeX}
% 
% The package \pkg{piton} provides several mechanisms for escaping to LaTeX:
% \begin{itemize}
% \item It's possible to compose comments entirely in LaTeX.
% \item It's possible to have the elements between \texttt{\$} in the comments
% composed in LateX mathematical mode.
% \item It's possible to ask \pkg{piton} to detect automatically some LaTeX
% commands, thanks to the key |detected-commands|.
% \item It's also possible to insert LaTeX code almost everywhere in a Python listing.
% \end{itemize}
%
% One should aslo remark that, when the extension \pkg{piton} is used with the
% class \cls{beamer}, \pkg{piton} detects in |{Piton}| many commands and
% environments of Beamer: cf. \ref{beamer} p.~\pageref{beamer}.
%
% \subsubsection{The ``LaTeX comments''}
%
% \index{comment-latex}
%
% In this document, we call ``LaTeX comments'' the comments which begins by
% |#>|. The code following those characters, until the end of the line, will be
% composed as standard LaTeX code. There is two tools to customize those
% comments.
%
% \begin{itemize}
% \item It's possible to change the syntatic mark (which, by default, is |#>|).
% For this purpose, there is a key |comment-latex| available only in the
% preamble of the document, allows to choice the characters which,
% preceded by |#|, will be the syntatic marker.
%
% For example, if the preamble contains the following instruction:
% 
% \quad \verb|\PitonOptions{comment-latex = LaTeX}|
%
% the LaTeX comments will begin by |#LaTeX|.
%
% If the key |comment-latex| is used with the empty value, all the Python
% comments (which begins by |#|) will, in fact, be ``LaTeX comments''.
%
% \smallskip
% \item It's possible to change the formatting of the LaTeX comment itself by
% changing the \pkg{piton} style |Comment.LaTeX|.
%
% For example, with |\SetPitonStyle{Comment.LaTeX = \normalfont\color{blue}}|,
% the LaTeX comments will be composed in blue.
%
% If you want to have a character |#| at the beginning of the LaTeX comment in
% the \textsc{pdf}, you can use set |Comment.LaTeX| as follows:
%
% \begin{Verbatim}
% \SetPitonStyle{Comment.LaTeX = \color{gray}\~#\normalfont\space }
% \end{Verbatim}
% 
% For other examples of customization of the LaTeX comments, see the part
% \ref{example-comments} p.~\pageref{example-comments}
% \end{itemize}
%
% \bigskip
% If the user has required line numbers (with the key |line-numbers|), it's
% possible to refer to a number of line with the command |\label| used in a
% LaTeX comment.\footnote{That feature is implemented by using a redefinition of
% the standard command \texttt{\textbackslash label} in the environments
% \texttt{\{Piton\}}. Therefore, incompatibilities may occur with extensions
% which redefine (globally) that command \texttt{\textbackslash label} (for
% example: \pkg{varioref}, \pkg{refcheck}, \pkg{showlabels}, etc.)}
%
% \subsubsection{The key ``math-comments''}
%
% \index{math-comments}
%
% It's possible to request that, in the standard Python comments (that is to say
% those beginning by |#| and not |#>|), the elements between \texttt{\$} be
% composed in LaTeX mathematical mode (the other elements of the comment being
% composed verbatim).
%
% That feature is activated by the key \Definition{math-comments}, \emph{which is
% available only in the preamble of the document}.
%
% \medskip
% Here is a example, where we have assumed that the preamble of the document
% contains the instruction |\PitonOptions{math-comment}|:
% 
% \begin{Verbatim}
% \begin{Piton}
% def square(x):
%     return x*x ~# compute $x^2$
% \end{Piton}
% \end{Verbatim}
%
% \begin{Piton}
% def square(x):
%     return x*x # compute $x^2$
% \end{Piton}
%
% \subsubsection{The key ``detected-commands''}
%
% \index{detected-commands (key)}
% \label{detected-commands}
%
% The key |detected-commands| of |\PitonOptions| allow to specify a
% (comma-separated) list of names of LaTeX commands that will be detected 
% directly by \pkg{piton}.
%
% \begin{itemize}
% \item The key |detected-commands| must be used in the preamble of the LaTeX document.
% 
% \item The names of the LaTeX commands must appear without the leading
% backslash (eg. |detected-commands = { emph, textbf }|). 
%
% \item These commands must be LaTeX commands with only one (mandatory) argument
% between braces (and these braces must be explicit). 
% \end{itemize}
%
% \medskip
% We assume that the preamble of the LaTeX document contains the following line.
% \begin{Verbatim}
% \PitonOptions{~emphase#detected-commands@ = highLight}
% \end{Verbatim}
%
% Then, it's possible to write directly:
% \begin{Verbatim}
% \begin{Piton}
% def fact(n):
%     if n==0:
%         return 1
%     else:
%         ~emphase#\highLight@{return n*fact(n-1)}
% \end{Piton}
% \end{Verbatim}
%
% \begin{Piton}
% def fact(n):
%     if n==0:
%         return 1
%     else:
%         \highLight{return n*fact(n-1)}
% \end{Piton}
%
% 
% \subsubsection{The mechanism ``escape''}
%
% \label{escape}
%
% It's also possible to overwrite the Python listings to insert LaTeX code
% almost everywhere (but between lexical units, of course). By default,
% \pkg{piton} does not fix any delimiters for that kind of escape.
%
% In order to use this mechanism, it's necessary to specify the delimiters which
% will delimit the escape (one for the beginning and one for the end) by using
% the keys \Definition{begin-escape} and \Definition{end-escape}, \emph{available only
% in the preamble of the document}.
%
% \medskip
% We consider once again the previous example of a recursive programmation of
% the factorial. We want to highlight in pink the instruction containing the
% recursive call. With the package \pkg{lua-ul}, we can use the syntax
% |\highLight[LightPink]{...}|. Because of the optional argument between square
% brackets, it's not possible to use the key |detected-commands| but it's
% possible to acheive our goal with the more general mechanism ``escape''.
%
% \medskip
% We assume that the preamble of the document contains
% the following instruction:
%
% \begin{Verbatim}
% \PitonOptions{~emphase#begin-escape=!,end-escape=!@}
% \end{Verbatim}
%
% \medskip
% Then, it's possible to write:
% \begin{Verbatim}
% \begin{Piton}
% def fact(n):
%     if n==0:
%         return 1
%     else:
%         ~emphase#!\highLight[LightPink]{!@return n*fact(n-1)~emphase#!}!@
% \end{Piton}
% \end{Verbatim}
%
%    \begin{Piton}
% def fact(n):
%     if n==0:
%         return 1
%     else:
%         !\highLight[LightPink]{!return n*fact(n-1)!}!
%    \end{Piton}
%
%
%
% \bigskip
% \emph{Caution} : The escape to LaTeX allowed by the |begin-escape| and
% |end-escape| 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 |#>|; such comments are merely called ``LaTeX comments'' in this
% document).
% 
%
% \subsubsection{The mechanism ``escape-math''}
% 
% The mechanism ``|escape-math|'' is very similar to the mechanism ``|escape|''
% since the only difference is that the elements sent to LaTeX are composed in
% the math mode of LaTeX.
%
% This mechanism is activated with the keys \Definition{begin-escape-math} and
% \Definition{end-escape-math} (\emph{which are available only in the preamble of the
% document}). 
%
% Despite the technical similarity, the use of the the mechanism
% ``|escape-math|'' is in fact rather different from that of the mechanism
% ``|escape|''. Indeed, since the elements are composed in a mathématical mode
% of LaTeX, they are, in particular, composed within a TeX group and therefore,
% they can't be used to change the formatting of other lexical units.
%
% In the langages where the character \verb|$| does not play a important role,
% it's possible to activate that mechanism ``|escape-math|'' with the character
% \verb|$|:
% \begin{Verbatim}
% \PitonOptions{~emphase#begin-escape-math=$,end-escape-math=$@}
% \end{Verbatim}
% Remark that the character \verb|$| must \emph{not} be protected by a backslash.
%
% \bigskip
% However, it's probably more prudent to use |\(| et |\)|.
% \begin{Verbatim}
% \PitonOptions{~emphase#begin-escape-math=\(,end-escape-math=\)@}
% \end{Verbatim}
% 
% \bigskip
% Here is an example of utilisation.
%
% \medskip
% \begin{Verbatim}
% \begin{Piton}[line-numbers]
% def arctan(x,n=10):
%     if ~emphase#\(x < 0\)@ :
%         return ~emphase#\(-\arctan(-x)\)@ 
%     elif ~emphase#\(x > 1\)@ : 
%         return ~emphase#\(\pi/2 - \arctan(1/x)\)@ 
%     else: 
%         s = ~emphase#\(0\)@
%         for ~emphase#\(k\)@ in range(~emphase#\(n\)@): s += ~emphase#\(\smash{\frac{(-1)^k}{2k+1} x^{2k+1}}\)@
%         return s
% \end{Piton}
% \end{Verbatim}
%
%
% \bigskip
%
% \begin{Piton}[line-numbers]
% def arctan(x,n=10):
%     if \(x < 0\) :
%         return \(-\arctan(-x)\) 
%     elif \(x > 1\) : 
%         return \(\pi/2 - \arctan(1/x)\) 
%     else: 
%         s = \(0\)
%         for \(k\) in range(\(n\)): s += \(\smash{\frac{(-1)^k}{2k+1} x^{2k+1}}\)
%         return s
% \end{Piton}
% 
%
% \subsection{Behaviour in the class Beamer}
%
% \label{beamer}
% \index{Beamer@\cls{Beamer} (class)}
%
% \emph{First remark}\par\nobreak
% Since the environment |{Piton}| catches its body with a verbatim mode, it's
% necessary to use the environments |{Piton}| within environments |{frame}| of
% Beamer protected by the key |fragile|, i.e. beginning with
% |\begin{frame}[fragile]|.\footnote{Remind that for an environment
% \texttt{\{frame\}} of Beamer using the key |fragile|, the instruction
% \texttt{\textbackslash end\{frame\}} must be alone on a single line (except
% for any leading whitespace).}
%
%
% \bigskip
% When the package \pkg{piton} is used within the class
% \cls{beamer}\footnote{The extension \pkg{piton} detects the class \cls{beamer}
% and the package \pkg{beamerarticle} if it is loaded previously
% but, if needed, it's also possible to activate that mechanism with the key
% |beamer| provided by \pkg{piton} at load-time: |\textbackslash
% usepackage[beamer]\{piton\}|}, the behaviour of \pkg{piton} is slightly
% modified, as described now.
%
% \subsubsection{\{Piton\} et \textbackslash PitonInputFile are
% ``overlay-aware''}
%
% When \pkg{piton} is used in the class \cls{beamer}, the environment |{Piton}|
% and the command |\PitonInputFile| accept the optional argument |<...>| of
% Beamer for the overlays which are involved.
%
% For example, it's possible to write:
%
% \begin{Verbatim}
% \begin{Piton}~emphase#<2-5>@
% ...
% \end{Piton}
% \end{Verbatim}
%
% and 
%
% \begin{Verbatim}
% \PitonInputFile~emphase#<2-5>@{my_file.py}
% \end{Verbatim}
% 
% \subsubsection{Commands of Beamer allowed in \{Piton\} and \textbackslash PitonInputFile}
%
% When \pkg{piton} is used in the class \cls{beamer} , the following commands of
% \cls{beamer} (classified upon their number of arguments) are automatically
% detected in the environments |{Piton}| (and in the listings processed by
% |\PitonInputFile|):
% \begin{itemize}
% \item no mandatory argument : |\pause|\footnote{One should remark that it's
% also  possible to use the command \texttt{\textbackslash pause} in a ``LaTeX
% comment'', that is to say by writing \texttt{\#> \textbackslash pause}. By
% this way, if the Python code is copied, it's still executable by Python}.  ;
% \item one mandatory argument : |\action|, |\alert|, |\invisible|, |\only|, |\uncover| and |\visible| ;
% \item two mandatory arguments : |\alt| ; 
% \item three mandatory arguments  : |\temporal|.
% \end{itemize}

% \medskip
% In the mandatory arguments of these commands, the braces must be balanced.
% However, the braces included in short strings\footnote{The short strings of
% Python are the strings delimited by characters \texttt{'} or the characters
% \texttt{"} and not \texttt{'''} nor \texttt{"""}. In Python, the short strings
% can't extend on several lines.} of Python are not considered. 
%
% \medskip
% Regarding the fonctions |\alt| and |\temporal| there should be no carriage
% returns in the mandatory arguments of these functions.
%
% \medskip
% Here is a complete example of file:
%
% \begin{Verbatim}[formatcom = \small\color{gray}]
% \documentclass{beamer}
% \usepackage{piton}
% \begin{document}
% \begin{frame}[fragile]
% \begin{Piton}
% def string_of_list(l):
%     """Convert a list of numbers in string"""
% ~emphase#    \only<2->{s = "{" + str(l[0])}@
% ~emphase#    \only<3->{for x in l[1:]: s = s + "," + str(x)}@
% ~emphase#    \only<4->{s = s + "}"}@
%     return s
% \end{Piton}
% \end{frame}
% \end{document}
% \end{Verbatim}
%
% In the previous example, the braces in the Python strings |"{"| and |"}"| are
% correctly interpreted (without any escape character).
% 
% 
%
%
% \bigskip
% \subsubsection{Environments of Beamer allowed in \{Piton\} and \textbackslash PitonInputFile}
%
% When \pkg{piton} is used in the class \pkg{beamer}, the following environments
% of Beamer are directly detected in the environments |{Piton}| (and in the
% listings processed by |\PitonInputFile|): |{actionenv}|, |{alertenv}|,
% |{invisibleenv}|, |{onlyenv}|, |{uncoverenv}| and |{visibleenv}|.
%
% However, there is a restriction: these environments must contain only \emph{whole
% lines of Python code} in their body.
%
%\medskip
% Here is an example:
%
% \begin{Verbatim}[formatcom = \small\color{gray}]
% \documentclass{beamer}
% \usepackage{piton}
% \begin{document}
% \begin{frame}[fragile]
% \begin{Piton}
% def square(x):
%     """Compure the square of its argument"""
%     ~emphase#\begin{uncoverenv}<2>@
%     return x*x
%     ~emphase#\end{uncoverenv}@
% \end{Piton}
% \end{frame}
% \end{document}
% \end{Verbatim}
%
%
% \vspace{1cm}
% \textbf{Remark concerning the command \textbackslash alert and the environment
% \{alertenv\} of Beamer}\par\nobreak
%
% \smallskip
% Beamer provides an easy way to change the color used by the environment
% |{alertenv}| (and by the command |\alert| which relies upon it) to highlight
% its argument. Here is an example:
%
% \begin{Verbatim}
% \setbeamercolor{~emphase#alerted text@}{fg=blue} 
% \end{Verbatim}
%
% However, when used inside an environment |{Piton}|, such tuning will probably
% not be the best choice because \pkg{piton} will, by design, change (most of
% the time) the color the different elements of text. One may prefer an environment
% |{alertenv}| that will change the background color for the elements to be
% hightlighted. 
%
% \smallskip
% Here is a code that will do that job and add a yellow background. That code
% uses the command |\@highLight| of \pkg{lua-ul} (that extension requires also
% the package \pkg{luacolor}).
%
% \begingroup
% \fvset{commandchars=\~\#\+,formatcom=\color{gray}}
% \begin{Verbatim}
% \setbeamercolor{alerted text}{bg=yellow!50}
% \makeatletter
% \AddToHook{env/Piton/begin}
%   {\renewenvironment<>{alertenv}{\only~#1{~emphase#\@highLight+[alerted text.bg]}}{}}
% \makeatother
% \end{Verbatim}
% \endgroup
%
% That code redefines locally the environment |{alertenv}| within the
% environments |{Piton}| (we recall that the command |\alert| relies upon that
% environment |{alertenv}|).
%
% 
% \subsection{Footnotes in the environments of piton}
%
%  \index{footnote@\pkg{footnote} (extension)}
% \index{footnote (key)}
% \index{footnotehyper@\pkg{footnotehyper} (extension)}
% \index{footnotehyper (key)}
%
% \label{footnote}
% If you want to put footnotes in an environment |{Piton}| or
% (or, more unlikely, in a listing produced by |\PitonInputFile|), you can use a
% pair |\footnotemark|--|\footnotetext|. 
%
% \smallskip
% However, it's also possible to extract the footnotes with the help of the
% package \pkg{footnote} or the package \pkg{footnotehyper}.
%
% \smallskip
% If \pkg{piton} is loaded with the option |footnote| (with
% |\usepackage[footnote]{piton}| or with |\PassOptionsToPackage|), the
% package \pkg{footnote} is loaded (if it is not yet loaded) and it is used to
% extract the footnotes.
%
% \smallskip
% If \pkg{piton} is loaded with the option |footnotehyper|, the package
% \pkg{footnotehyper} is loaded (if it is not yet loaded) ant it is used to
% extract footnotes.
%
% \smallskip
% Caution: The packages \pkg{footnote} and \pkg{footnotehyper} are incompatible.
% The package \pkg{footnotehyper} is the successor of the package \pkg{footnote}
% and should be used preferently. The package \pkg{footnote} has some drawbacks,
% in particular: it must be loaded after the package \pkg{xcolor} and it is not
% perfectly compatible with \pkg{hyperref}.
%
% \medskip 
% In this document, the package \pkg{piton} has been loaded with the
% option |footnotehyper|. For examples of notes, cf. \ref{notes-examples},
% p.~\pageref{notes-examples}.
%
% \subsection{Tabulations}
%
% \index{tabulations}
% \index{tab-size}
%
% \smallskip 
% Even though it's recommended to indent the Python listings with spaces (see
% PEP~8), \pkg{piton} accepts the characters of tabulation (that is to say the
% characters U+0009) at the beginning of the lines. Each character U+0009 is
% replaced by $n$~spaces. The initial value of $n$ is $4$ but it's possible to
% change it with the key |tab-size| of |\PitonOptions|.
%
% \smallskip
% There exists also a key |tabs-auto-gobble| which computes the minimal value
% $n$ of the number of consecutive characters U+0009 beginning each (non empty)
% line of the environment |{Piton}| and applies |gobble| with that value of~$n$
% (before replacement of the tabulations by spaces, of course). Hence, that key
% is similar to the key |auto-gobble| but acts on U+0009 instead of U+0020
% (spaces).
%
%
% \bigskip
% \section{API for the developpers}
%
% \label{API}
% 
% The L3 variable |\l_piton_language_str| contains the name of the current
% language of \pkg{piton} (in lower case).
%
% \bigskip
% \colorbox{yellow!50}{\textbf{New 2.6}}\par\nobreak
%
% The extension \pkg{piton} provides a Lua function |piton.get_last_code|
% without argument which returns the code in the latest environment of
% \pkg{piton}.
% \begin{itemize}
% \item The carriage returns (which are present in the initial environment)
% appears as characters |\r| (i.e. U+000D).
%
% \item The code returned by |piton.get_last_code()| takes into account the
% potential application of a key |gobble|, |auto-gobble| or |env-gobble|
% (cf.~p.~\pageref{gobble}). 
%
% \item The extra formatting elements added in the code are deleted in the code
% returned by |piton.get_last_code()|. That concerns the LaTeX commands declared
% by the key |detected-commands| (cf. part~\ref{detected-commands}) and the
% elements inserted by the mechanism ``|escape|'' (cf. part~\ref{escape}).
%
% \item |piton.get_last_code| is a Lua function and not a Lua string: the
% treatments outlined above are executed when the function is called. Therefore,
% it might be judicious to store the value returned by |piton.get_last_code()|
% in a variable of Lua if it will be used serveral times.
% \end{itemize}
% 
% \medskip
% For an example of use, see the part concerning |pyluatex|, part~\ref{pyluatex},
% p.~\pageref{pyluatex}. 
%
%
% \section{Examples}
%
% \subsection{Line numbering}
%
% \label{example-numbering}
% \index{numbers of the lines de code|emph}
%
% We remind that it's possible to have an automatic numbering of the lines in
% the Python listings by using the key |line-numbers|.
%
% By default, the numbers of the lines are composed by \pkg{piton} in an
% overlapping position on the left (by using internally the command |\llap| of LaTeX).
%
% In order to avoid that overlapping, it's possible to use the option |left-margin=auto|
% which will insert automatically a margin adapted to the numbers of lines that
% will be written (that margin is larger when the numbers are greater than~10).
%
%
% \begingroup
% \fvset{commandchars=\~\&\@,formatcom=\small\color{gray}}
% \begin{Verbatim}
% ~emphase&\PitonOptions{background-color=gray!10, left-margin = auto, line-numbers}@
% \begin{Piton}
% def arctan(x,n=10):
%     if x < 0:
%         return -arctan(-x)        #> (recursive call)
%     elif x > 1: 
%         return pi/2 - arctan(1/x) #> (other recursive call) 
%     else: 
%         return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) 
% \end{Piton}
% \end{Verbatim}
% \endgroup
%
%
%
% \begingroup
% \PitonOptions{background-color=gray!10,left-margin = auto, line-numbers}
% \begin{Piton}
% def arctan(x,n=10):
%     if x < 0:
%         return -arctan(-x)        #> (recursive call)
%     elif x > 1: 
%         return pi/2 - arctan(1/x) #> (other recursive call) 
%     else: 
%         return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) 
% \end{Piton}
% \endgroup
%
%
%
% \bigskip
% \subsection{Formatting of the LaTeX comments}
%
% \label{example-comments}
%
% It's possible to modify the style |Comment.LaTeX| (with |\SetPitonStyle|) in
% order to display the LaTeX comments (which begin with |#>|) aligned on the
% right margin.
%
%
% \begingroup
% \fvset{commandchars=\~\&\@,formatcom=\small\color{gray}}
% \begin{Verbatim}
% \PitonOptions{background-color=gray!10}
% ~emphase&\SetPitonStyle{Comment.LaTeX = \hfill \normalfont\color{gray}}@
% \begin{Piton}
% def arctan(x,n=10):
%     if x < 0:
%         return -arctan(-x)        #> recursive call
%     elif x > 1: 
%         return pi/2 - arctan(1/x) #> other recursive call 
%     else: 
%         return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) 
% \end{Piton}
% \end{Verbatim}
% \endgroup
%
% \begingroup
% \PitonOptions{background-color=gray!10}
% \SetPitonStyle{Comment.LaTeX = \hfill \normalfont\color{gray}}
% \begin{Piton}
% def arctan(x,n=10):
%     if x < 0:
%         return -arctan(-x)        #> recursive call
%     elif x > 1: 
%         return pi/2 - arctan(1/x) #> another recursive call 
%     else: 
%         return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) 
% \end{Piton}
% \endgroup
%
%
% \vspace{1cm}
% It's also possible to display these LaTeX comments in a kind of second column
% by limiting the width of the Python code with the key |width|. In the
% following example, we use the key |width| with the special value~|min|.
%
%
% \begingroup
% \fvset{commandchars=\~\&\@,formatcom=\small\color{gray}}
% \begin{Verbatim}
% \PitonOptions{background-color=gray!10, width=min}
% ~emphase&\NewDocumentCommand{\MyLaTeXCommand}{m}{\hfill \normalfont\itshape\rlap{\quad #1}}@
% ~emphase&\SetPitonStyle{Comment.LaTeX = \MyLaTeXCommand}@
% \begin{Piton}
% def arctan(x,n=10):
%     if x < 0:
%         return -arctan(-x) #> recursive call
%     elif x > 1: 
%         return pi/2 - arctan(1/x) #> another recursive call 
%     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{background-color=gray!10, width=min}
% \NewDocumentCommand{\MyLaTeXCommand}{m}{\hfill \normalfont\itshape\rlap{\quad #1}}
% \SetPitonStyle{Comment.LaTeX = \MyLaTeXCommand}
% \begin{Piton}
% def arctan(x,n=10):
%     if x < 0:
%         return -arctan(-x) #> recursive call
%     elif x > 1: 
%         return pi/2 - arctan(1/x) #> another recursive call 
%     else: 
%         s = 0
%         for k in range(n):
%              s += (-1)**k/(2*k+1)*x**(2*k+1)
%         return s 
% \end{Piton}
% \endgroup
%
%
% \bigskip
% \subsection{Notes in the listings}
%
% \label{notes-examples}
% \index{notes in the listings}
% 
% In order to be able to extract the notes (which are typeset with the command
% |\footnote|), the extension \pkg{piton} must be loaded with the key |footnote|
% or the key |footenotehyper| as explained in the section \ref{footnote}
% p.~\pageref{footnote}. In this document, the extension \pkg{piton} has been
% loaded with the key |footnotehyper|.
%
% Of course, in an environment |{Piton}|, a command |\footnote| may appear only
% within a LaTeX comment (which begins with |#>|). It's possible to have comments
% which contain only that command |\footnote|. That's the case in the following example.
%
%
%
% \begingroup
% \fvset{commandchars=\~\&\@,formatcom=\small\color{gray}}
% \begin{Verbatim}
% \PitonOptions{background-color=gray!10}
% \begin{Piton}
% def arctan(x,n=10):
%     if x < 0:
%         return -arctan(-x)~emphase&#>\footnote{First recursive call.}]@
%     elif x > 1: 
%         return pi/2 - arctan(1/x)~emphase&#>\footnote{Second recursive call.}@
%     else: 
%         return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) 
% \end{Piton}
% \end{Verbatim}
% \endgroup
%
% \begingroup
% \PitonOptions{background-color=gray!10}
% \begin{Piton}
% def arctan(x,n=10):
%     if x < 0:
%         return -arctan(-x)#>\footnote{First recursive call.}
%     elif x > 1: 
%         return pi/2 - arctan(1/x)#>\footnote{Second recursive call.}
%     else: 
%         return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) 
% \end{Piton}
% \endgroup
%
%
% \vspace{1cm}
%
% If an environment |{Piton}| is used in an environment |{minipage}| of LaTeX,
% the notes are composed, of course, at the foot of the environment
% |{minipage}|. Recall that such |{minipage}| can't be broken by a page break.
%
%
% \begingroup
% \fvset{commandchars=\~\&\@,formatcom=\small\color{gray}}
% \begin{Verbatim}
% \PitonOptions{background-color=gray!10}
% \emphase\begin{minipage}{\linewidth}
% \begin{Piton}
% def arctan(x,n=10):
%     if x < 0:
%         return -arctan(-x)~emphase&#>\footnote{First recursive call.}@
%     elif x > 1: 
%         return pi/2 - arctan(1/x)~emphase&#>\footnote{Second recursive call.}@
%     else: 
%         return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) 
% \end{Piton}
% \end{minipage}
% \end{Verbatim}
% \endgroup
%
% \begingroup
% \PitonOptions{background-color=gray!10}
% \begin{minipage}{\linewidth}
% \begin{Piton}
% def arctan(x,n=10):
%     if x < 0:
%         return -arctan(-x)#>\footnote{First recursive call.}
%     elif x > 1: 
%         return pi/2 - arctan(1/x)#>\footnote{Second recursive call.}
%     else: 
%         return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) 
% \end{Piton}
% \end{minipage}
% \endgroup
%
%
%
% \bigskip
%
% \subsection{An example of tuning of the styles}
%
% The graphical styles have been presented in the section \ref{styles},
% p.~\pageref{styles}.
%
% \smallskip
% We present now an example of tuning of these styles adapted to the documents
% in black and white. We use the font \emph{DejaVu Sans Mono}\footnote{See:
% \url{https://dejavu-fonts.github.io}} specified by the command |\setmonofont| of 
% \pkg{fontspec}. 
%
% That tuning uses the command |\highLight| of \pkg{lua-ul} (that package
% requires itself the package \pkg{luacolor}).
%
% \begin{Verbatim}
% \setmonofont[Scale=0.85]{DejaVu Sans Mono}
%
% \SetPitonStyle
%   {
%     Number = ,
%     String = \itshape , 
%     String.Doc = \color{gray} \slshape ,
%     Operator = , 
%     Operator.Word = \bfseries ,
%     Name.Builtin = ,
%     Name.Function = \bfseries \highLight[gray!20] ,
%     Comment = \color{gray} ,
%     Comment.LaTeX = \normalfont \color{gray},
%     Keyword = \bfseries ,
%     Name.Namespace = ,
%     Name.Class = , 
%     Name.Type = ,
%     InitialValues = \color{gray}
%   }
% \end{Verbatim}
%
% In that tuning, many values given to the keys are empty: that means that the
% corresponding style won't insert any formating instruction (the element will
% be composed in the standard color, usually in black, etc.). Nevertheless,
% those entries are mandatory because the initial value of those keys in
% \pkg{piton} is \emph{not} empty.
%
% \begingroup
%
% \setmonofont[Scale=0.85]{DejaVu Sans Mono}
%
%  \PitonOptions{splittable}
%
% \SetPitonStyle
%   {
%     Number = ,
%     String = \itshape , 
%     String.Doc = \color{gray} \slshape ,
%     Operator.Word = \bfseries ,
%     Operator = , 
%     Name.Builtin = ,
%     Name.Function = \bfseries \highLight[gray!20] ,
%     Comment = \color{gray} ,
%     Comment.LaTeX = \normalfont \color{gray} ,
%     Keyword = \bfseries ,
%     Name.Namespace = ,
%     Name.Class = , 
%     Name.Type = ,
%     InitialValues = \color{gray}
%   }
%
%
% \bigskip
%
% \begin{Piton}
% from math import pi
%
% def arctan(x,n=10):
%     """Compute the mathematical value of arctan(x)
%                                               
%     n is the number of terms in 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)=\pi/2$ for $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{Use with pyluatex}
%
% \index{pyluatex@{\pkg{pyluatex}} (extension)}
% \label{pyluatex}
%
% The package \pkg{pyluatex} is an extension which allows the execution of some
% Python code from |lualatex| (provided that Python is installed on the machine
% and that the compilation is done with |lualatex| and |--shell-escape|).
%
% Here is, for example, an environment |{PitonExecute}| which formats a Python
% listing (with \pkg{piton}) but also displays the output of the execution of the
% code with Python.
% 
% \medskip
% \begin{Verbatim}
% \NewPitonEnvironment{~emphase#PitonExecute@}{!O{}}
%   {\PitonOptions{~#1}}
%   {\begin{center}
%    \directlua{pyluatex.execute(piton.get_last_code(), false, true, false, true)}%
%    \end{center}
%    \ignorespacesafterend}
% \end{Verbatim}
%
% \medskip
% We have used the Lua function |piton.get_last_code| provided in the API of
% \pkg{piton} : cf.~part~\ref{API}, p.~\pageref{API}.
%
% \medskip
% This environment |{PitonExecute}| takes in as optional argument (between
% square brackets) the options of the command |\PitonOptions|.
%
%
%
% \clearpage
% \section{The styles for the different computer languages}
%
% \label{Semantic}
%
%
% \subsection{The language Python}
%
% In \pkg{piton}, the default language is Python. If necessary, it's possible to
% come back to the language Python with |\PitonOptions{language=Python}|.
%
% \bigskip
%
% The initial settings
% done by \pkg{piton} in |piton.sty| are inspired by the style \pkg{manni} de
% Pygments, as applied by Pygments to the language Python.\footnote{See:
% \url{https://pygments.org/styles/}. Remark that, by default, Pygments provides
% for its style \pkg{manni} a colored background whose color is the HTML color
% \texttt{\#F0F3F3}. It's possible to have the same color in \texttt{\{Piton\}}
% with the instruction \texttt{\textbackslash PitonOptions\{background-color =
% [HTML]\{F0F3F3\}\}}.}
%
% \vspace{1cm}
%
% \begin{center}
% \begin{tabularx}{0.9\textwidth}{@{}>{\ttfamily}l>{\raggedright\arraybackslash}X@{}}
%   \toprule
%   \normalfont Style  & Use \\
%   \midrule
%   Number & the numbers \\
%   String.Short & the short strings (entre \texttt{'} ou \texttt{"}) \\
%   String.Long & the long strings (entre \texttt{'''} ou \texttt{"""}) excepted
%                 the doc-strings (governed by |String.Doc|)\\
%   String & that key fixes both |String.Short| et |String.Long| \\
%   String.Doc & the doc-strings (only with |"""| following PEP~257) \\
%   String.Interpol & the syntactic elements of the fields of the f-strings
%   (that is to say the characters \texttt{\{} et \texttt{\}}); that style
%   inherits for the styles |String.Short| and |String.Long| (according the kind
%   of string where the interpolation appears) \\
%   Interpol.Inside & the content of the interpolations in the f-strings (that
%   is to say the elements between \texttt{\{} and~\texttt{\}}); if the final
%   user has not set that key, those elements will be formatted by \pkg{piton}
%   as done for any Python code. \\
%   Operator & the following operators: \texttt{!= == << >> - \~{} + / * \% = < > \& .} \verb+|+ \verb|@| \\
%   Operator.Word & the following operators: |in|, |is|, |and|, |or| et |not| \\
%   Name.Builtin & almost all the functions predefined by Python \\
%   Name.Decorator & the decorators (instructions beginning by \verb|@|) \\
%   Name.Namespace & the name of the modules \\
%   Name.Class & the name of the Python classes defined by the user \emph{at their point of definition} (with the keyword |class|) \\ 
%   Name.Function & the name of the Python functions defined by the user \emph{at their
%   point of definition} (with the keyword |def|) \\ 
%   UserFunction & the name of the Python functions previously defined by the user
%                  (the initial value of that parameter is empty and, hence, these
%                  elements are drawn, by default, in the current color, usually black) \\
%   Exception & les exceptions prédéfinies (ex.: \texttt{SyntaxError}) \\
%   InitialValues & the initial values (and the preceding symbol |=|) of the
%   optional arguments in the definitions of functions; if the final
%   user has not set that key, those elements will be formatted by \pkg{piton}
%   as done for any Python code. \\
%   Comment & the comments beginning with \texttt{\#} \\
%   Comment.LaTeX & the comments beginning with \texttt{\#>}, which are composed by
%   \pkg{piton} as LaTeX code (merely named ``LaTeX comments'' in this document) \\
%   Keyword.Constant & |True|, |False| et |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 et yield from.\\
%   \bottomrule
% \end{tabularx}
% \end{center}
%
%
% \newpage
%
% \subsection{The language OCaml}
%
% It's possible to switch to the language |OCaml| with |\PitonOptions{language = OCaml}|.
%
% \bigskip
% It's also possible to set the language OCaml for an individual environment |{Piton}|. 
% %
% \begin{Verbatim}
% \begin{Piton}~emphase#[language=OCaml]@
% ...
% \end{Piton}
% \end{Verbatim}
%
% \bigskip
% The option exists also for |\PitonInputFile| : |\PitonInputFile[language=OCaml]{...}|
%
% \vspace{1cm}
%
%
% \begin{center}
% \begin{tabularx}{0.9\textwidth}{@{}>{\ttfamily}l>{\raggedright\arraybackslash}X@{}}
%   \toprule
%   \normalfont Style  & Use \\
%   \midrule
%   Number & the numbers \\
%   String.Short & the characters (between \texttt{'}) \\
%   String.Long & the strings, between |"| but also the \emph{quoted-strings} \\
%   String & that key fixes both |String.Short| and |String.Long| \\
%   Operator & les opérateurs, en particulier |+|, |-|, |/|, |*|, |@|, |!=|, |==|, |&&| \\
%   Operator.Word & les opérateurs suivants : |and|, |asr|, |land|, |lor|, |lsl|, |lxor|, |mod| et |or| \\
%   Name.Builtin & les fonctions |not|, |incr|, |decr|, |fst| et |snd| \\
%   Name.Type & the name of a type of OCaml \\
%   Name.Field & the name of a field of a module \\
%   Name.Constructor & the name of the constructors of types (which begins by a capital) \\
%   Name.Module & the name of the modules \\
%   Name.Function & the name of the Python functions defined by the user \emph{at their
%   point of definition} (with the keyword |let|) \\ 
%   UserFunction & the name of the OCaml functions previously defined by the user
%                  (the initial value of that parameter is empty and these
%                  elements are drawn in the current color, usually black) \\
%   Exception & the predefined exceptions (eg : |End_of_File|) \\
%   TypeParameter &  the parameters of the types \\
%   Comment & the comments, between |(*| et |*)|; these comments may be nested \\
%   Keyword.Constant & |true| et |false| \\
%   Keyword & the following keywords:
%             |assert|, |as|, |begin|, |class|, |constraint|, |done|,
%             |downto|, |do|, |else|, |end|, |exception|, |external|,
%             |for|, |function|, |functor|, |fun| , |if| 
%             |include|, |inherit|, |initializer|, |in| , |lazy|, |let|,
%             |match|, |method|, |module|, |mutable|, |new|, |object|,
%             |of|, |open|, |private|, |raise|, |rec|, |sig|,
%             |struct|, |then|, |to|, |try|, |type|, 
%             |value|, |val|, |virtual|, |when|, |while| and |with| \\
%   \bottomrule
% \end{tabularx}
% \end{center}
%
% \newpage
%
% \subsection[The language C (and C++)]{The language C (and \CC)}
%
% 
% It's possible to switch to the language |C| with |\PitonOptions{language = C}|.
%
% \bigskip
% It's also possible to set the language C for an individual environment |{Piton}|. 
% %
% \begin{Verbatim}
% \begin{Piton}~emphase#[language=C]@
% ...
% \end{Piton}
% \end{Verbatim}
%
% \bigskip
% The option exists also for |\PitonInputFile| : |\PitonInputFile[language=C]{...}|
%
% \vspace{1cm}
%
% \begin{center}
% \begin{tabularx}{0.9\textwidth}{@{}>{\ttfamily}l>{\raggedright\arraybackslash}X@{}}
% \toprule
% \normalfont Style  & Use \\
% \midrule
% Number & the numbers \\
% String.Long & the strings (between \texttt{"}) \\
% String.Interpol &  the elements \texttt{\%d}, \texttt{\%i}, \texttt{\%f},
% \texttt{\%c}, etc. in the strings; that style inherits from the style |String.Long| \\
% Operator & the following operators : \texttt{!= == << >> - \~{} + / * \% = < > \& .} \verb+|+ \verb|@| \\
% Name.Type & the following predefined types:
%   |bool|, |char|, |char16_t|, |char32_t|, |double|, |float|, |int|, |int8_t|, |int16_t|, |int32_t|, 
%   |int64_t|, |long|, |short|, |signed|, |unsigned|, |void| et |wchar_t| \\ 
% Name.Builtin & the following predefined functions: |printf|, |scanf|, |malloc|, |sizeof| and |alignof|  \\
%   Name.Class & le nom des classes au moment de leur définition, c'est-à-dire
%   après le mot-clé \verb|class| \\
%   Name.Function & the name of the Python functions defined by the user \emph{at their
%   point of definition} (with the keyword |let|) \\ 
%   UserFunction & the name of the Python functions previously defined by the user
%                  (the initial value of that parameter is empty and these
%                  elements are drawn in the current color, usually black) \\
% Preproc & the instructions of the preprocessor (beginning par |#|) \\
% Comment & the comments (beginning by \texttt{//} or between |/*| and |*/|) \\
% Comment.LaTeX & the comments beginning by  \texttt{//>} which are composed by
% \pkg{piton} as LaTeX code (merely named ``LaTeX comments'' in this document) \\
% Keyword.Constant & |default|, |false|, |NULL|, |nullptr| and |true| \\
% Keyword & the following keywords:
% |alignas|, |asm|, |auto|, |break|, |case|, |catch|, |class|, 
% |constexpr|, |const|, |continue|, |decltype|, |do|, |else|, |enum|,
% |extern|, |for|, |goto|, |if|, |nexcept|, |private|, |public|, |register|, |restricted|, |try|, 
% |return|, |static|, |static_assert|, |struct|, |switch|, |thread_local|, |throw|, 
% |typedef|, |union|, |using|, |virtual|, |volatile| and |while|
% \\
% \bottomrule
% \end{tabularx}
% \end{center}
%
% \newpage
%
% \subsection{The language SQL}
%
% 
% It's possible to switch to the language |SQL| with |\PitonOptions{language = SQL}|.
%
% \bigskip
% It's also possible to set the language SQL for an individual environment |{Piton}|. 
% %
% \begin{Verbatim}
% \begin{Piton}~emphase#[language=SQL]@
% ...
% \end{Piton}
% \end{Verbatim}
%
% \bigskip
% The option exists also for |\PitonInputFile| : |\PitonInputFile[language=SQL]{...}|
%
%
% \vspace{1cm}
%
% \begin{center}
% \begin{tabularx}{0.9\textwidth}{@{}>{\ttfamily}l>{\raggedright\arraybackslash}X@{}}
% \toprule
% \normalfont Style  & Use \\
% \midrule
% Number & the numbers \\
% String.Long & the strings (between \texttt{'} and not \texttt{"} because the
% elements between \texttt{"} are names of fields and formatted with |Name.Field|) \\
% Operator & the following operators : \texttt{= != <> >= > < <= * + / } \\
% Name.Table & the names of the tables \\
% Name.Field & the names of the fields of the tables \\
% Name.Builtin & the following built-in functions (their names are \emph{not} case-sensitive): 
%    |avg|, |count|, |char_lenght|, |concat|, |curdate|, |current_date|,
%    |date_format|, |day|, |lower|, |ltrim|, |max|, |min|, |month|, |now|,
%    |rank|, |round|, |rtrim|, |substring|, |sum|, |upper| and |year|. \\
% Comment & the comments (beginning by \texttt{--} or between |/*| and |*/|) \\
% Comment.LaTeX & the comments beginning by  \texttt{-->} which are composed by
% \pkg{piton} as LaTeX code (merely named ``LaTeX comments'' in this document) \\
% Keyword & the following keywords (their names are \emph{not} case-sensitive):
% |add|, |after|, |all|, |alter|, |and|, |as|, |asc|, |between|, |by|,
% |change|, |column|, |create|, |cross join|, |delete|, |desc|, |distinct|, 
% |drop|, |from|, |group|, |having|, |in|, |inner|, |insert|, |into|, |is|, 
% |join|, |left|, |like|, |limit|, |merge|, |not|, |null|, |on|, |or|, 
% |order|, |over|, |right|, |select|, |set|, |table|, |then|, |truncate|, 
% |union|, |update|, |values|, |when|, |where| and |with|. \\
% \bottomrule
% \end{tabularx}
% \end{center}
%
%
% \bigskip
% It's possible to automatically capitalize the keywords by modifiying locally
% for the language SQL the style |Keywords|.
% \begin{Verbatim}
% \SetPitonStyle~emphase#[SQL]@{Keywords = \bfseries \MakeUppercase}
% \end{Verbatim}
%
% \newpage
%
% \subsection{The language ``minimal''}
%
% It's possible to switch to the language ``|minimal|'' with |\PitonOptions{language = minimal}|.
%
% \bigskip
% It's also possible to set the language ``|minimal|'' for an individual environment |{Piton}|. 
% %
% \begin{Verbatim}
% \begin{Piton}~emphase#[language=minimal]@
% ...
% \end{Piton}
% \end{Verbatim}
%
% \bigskip
% The option exists also for |\PitonInputFile| : |\PitonInputFile[language=minimal]{...}|
%
%
% \label{minimal}
%
% \vspace{1cm}
%
% \begin{center}
% \begin{tabularx}{0.9\textwidth}{@{}>{\ttfamily}l>{\raggedright\arraybackslash}X@{}}
% \toprule
% \normalfont Style  & Usage \\
% \midrule
% Number & the numbers \\
% String & the strings (between \texttt{"}) \\
% Comment & les comments (which begins with |#|) \\
% Comment.LaTeX &  the comments beginning with \texttt{\#>}, which are composed by
%   \pkg{piton} as LaTeX code (merely named ``LaTeX comments'' in this document) \\
% \bottomrule
% \end{tabularx}
% \end{center}
%
% \bigskip
% That language is provided for the final user who might wish to add keywords in
% that language (with the command |\SetPitonIdentifier|: cf. \ref{SetPitonIdentifier},
% p.~\pageref{SetPitonIdentifier}) in order to create, for example, a language
% for pseudo-code.
%
% \newpage
%
% \section{Implementation}
%
% \medskip
% The development of the extension \pkg{piton} is done on the following GitHub
% depot:
%
% \verb|https://github.com/fpantigny/piton|
%
% \subsection{Introduction}
% 
% The main job of the package \pkg{piton} is to take in as input a Python
% listing and to send back to LaTeX as output that code \emph{with interlaced LaTeX
% instructions of formatting}.
%
% In fact, all that job is done by a \textsc{lpeg} called |python|. That
% \textsc{lpeg}, when matched against the string of a Python listing,
% returns as capture a Lua table containing data to send to LaTeX. 
% The only thing to do after will be to apply |tex.tprint| to each element of
% that table.\footnote{Recall that |tex.tprint| takes in as argument a Lua table whose
% first component is a ``catcode table'' and the second element a string. The
% string will be sent to LaTeX with the regime of catcodes specified by the
% catcode table. If no catcode table is provided, the standard catcodes of LaTeX
% will be used.}
% 
% \bigskip
% Consider, for example, the following Python code:
%
% \begin{Piton}
% def parity(x):
%     return x%2
% \end{Piton}
%
% The capture returned by the \pkg{lpeg} |python| against that code is the
% Lua table containing the following elements :
%
% \bigskip
% \begin{minipage}{\linewidth}
% \color{gray}
% 
% |{ "\\__piton_begin_line:" }|\footnote{Each line of the Python listings will
% be encapsulated in a pair: \texttt{\textbackslash_@@_begin_line:} --
% \texttt{\textbackslash@@_end_line:}. The token
% \texttt{\textbackslash@@_end_line:} must be explicit because it will be used as
% marker in order to delimit the argument of the command \texttt{\textbackslash
% @@\_begin\_line:}. Both tokens \texttt{\textbackslash_@@_begin_line:} and
% \texttt{\textbackslash@@_end_line:} will be nullified in the command
% \texttt{\textbackslash piton} (since there can't be lines breaks in the
% argument of a command \texttt{\textbackslash piton}).}  
% 
% \texttt{\{ "\{\textbackslash PitonStyle\{Keyword\}\{" \}}\footnote{The
% lexical elements of Python for which we have a \pkg{piton} style will be
% formatted via the use of the command \texttt{\textbackslash PitonStyle}.
% Such an element is typeset in LaTeX via the syntax \texttt{\{\textbackslash
% PitonStyle\{\textsl{style}\}\{...\}\}} because the instructions inside an \texttt{\textbackslash
% PitonStyle} may be both semi-global declarations like
% \texttt{\textbackslash bfseries} and commands with one argument like
% \texttt{\textbackslash fbox}.}
%
% \texttt{\{
% luatexbase.catcodetables.CatcodeTableOther\footnote{\texttt{luatexbase.catcodetables.CatcodeTableOther} is a mere number which corresponds to the ``catcode table'' whose all characters have the catcode ``other'' (which means that they will be typeset by LaTeX verbatim).}, "def" \} }
%
% |{ "}}" }|
%
% |{ luatexbase.catcodetables.CatcodeTableOther, " " }|
%
% |{ "{\PitonStyle{Name.Function}{" }|
%
% |{ luatexbase.catcodetables.CatcodeTableOther, "parity" }|
%
% |{ "}}" }|
% 
% |{ luatexbase.catcodetables.CatcodeTableOther, "(" }|
%
% |{ luatexbase.catcodetables.CatcodeTableOther, "x" }|
%
% |{ luatexbase.catcodetables.CatcodeTableOther, ")" }|
%
% |{ luatexbase.catcodetables.CatcodeTableOther, ":" }|
% 
% |{ "\\__piton_end_line: \\__piton_newline: \\__piton_begin_line:" }|
%
% |{ luatexbase.catcodetables.CatcodeTableOther, "    " }|
%
% |{ "{\PitonStyle{Keyword}{" }|
%
% |{ luatexbase.catcodetables.CatcodeTableOther, "return" }|
%
% |{ "}}" }|
%
% |{ luatexbase.catcodetables.CatcodeTableOther, " " }|
%
% |{ luatexbase.catcodetables.CatcodeTableOther, "x" }|
%
% |{ "{\PitonStyle{Operator}{" }|
%
% |{ luatexbase.catcodetables.CatcodeTableOther, "&" }|
%
% |{ "}}" }|
%
% |{ "{\PitonStyle{Number}{" }|
%
% |{ luatexbase.catcodetables.CatcodeTableOther, "2" }|
%
% |{ "}}" }|
% 
% |{ "\\__piton_end_line:" }|
% 
% \end{minipage}
%
% \bigskip
% We give now the LaTeX code which is sent back by Lua to TeX (we have written
% on several lines for legibility but no character |\r| will be sent to LaTeX). The
% characters which are greyed-out are sent to LaTeX with the catcode ``other''
% (=12). All the others characters are sent with the regime of catcodes of L3
% (as set by |\ExplSyntaxOn|)
%
% 
% \begingroup
% \def\gbox#1{\colorbox{gray!20}{\strut #1}}
% \setlength{\fboxsep}{1pt}
% 
% \begin{Verbatim*}[formatcom = \color{black}]
% \__piton_begin_line:{\PitonStyle{Keyword}{~gbox#def@}}
% ~gbox# @{\PitonStyle{Name.Function}{~gbox#parity@}}~gbox#(x):@\__piton_end_line:\__piton_newline:
% \__piton_begin_line:~gbox#    @{\PitonStyle{Keyword}{~gbox#return@}}
% ~gbox# x@{\PitonStyle{Operator}{~gbox#%@}}{\PitonStyle{Number}{~gbox#2@}}\__piton_end_line:
% \end{Verbatim*}
% \endgroup
%
%
% 
%
% \subsection{The L3 part of the implementation}
%
% \subsubsection{Declaration of the package}
%    \begin{macrocode}
%<*STY>
\NeedsTeXFormat{LaTeX2e}
\RequirePackage{l3keys2e}
\ProvidesExplPackage
  {piton}
  {\PitonFileDate}
  {\PitonFileVersion}
  {Highlight informatic listings with LPEG on LuaLaTeX}
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\cs_new_protected:Npn \@@_error:n { \msg_error:nn { piton } }
\cs_new_protected:Npn \@@_warning:n { \msg_warning:nn { piton } }
\cs_new_protected:Npn \@@_error:nn { \msg_error:nnn { piton } }
\cs_new_protected:Npn \@@_error:nnn { \msg_error:nnnn { piton } }
\cs_new_protected:Npn \@@_fatal:n { \msg_fatal:nn { piton } }
\cs_new_protected:Npn \@@_fatal:nn { \msg_fatal:nnn { piton } }
\cs_new_protected:Npn \@@_msg_new:nn { \msg_new:nnn { piton } }
\cs_new_protected:Npn \@@_msg_new:nnn { \msg_new:nnnn { piton } }
\cs_new_protected:Npn \@@_gredirect_none:n #1 
  {
    \group_begin:
    \globaldefs = 1
    \msg_redirect_name:nnn { piton } { #1 } { none }
    \group_end:
  }
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\@@_msg_new:nn { LuaLaTeX~mandatory }
  { 
    LuaLaTeX~is~mandatory.\\
    The~package~'piton'~requires~the~engine~LuaLaTeX.\\
    \str_if_eq:onT \c_sys_jobname_str { output }
      { If~you~use~Overleaf,~you~can~switch~to~LuaLaTeX~in~the~"Menu". \\}
    If~you~go~on,~the~package~'piton'~won't~be~loaded.
  }
\sys_if_engine_luatex:F { \msg_critical:nn { piton } { LuaLaTeX~mandatory } }
%    \end{macrocode}
% 
% \bigskip
%    \begin{macrocode}
\RequirePackage { luatexbase } 
\RequirePackage { luacode }
%    \end{macrocode}
% 
% \bigskip
%    \begin{macrocode}
\@@_msg_new:nnn { piton.lua~not~found }
  { 
    The~file~'piton.lua'~can't~be~found.\\ 
    The~package~'piton'~won't~be~loaded.\\
    If~you~want~to~know~how~to~retrieve~the~file~'piton.lua',~type~H~<return>.
  }
  {
    On~the~site~CTAN,~go~to~the~page~of~'piton':~https://ctan.org/pkg/piton.~
    The~file~'README.md'~explains~how~to~retrieve~the~files~'piton.sty'~and~
    'piton.lua'.
  }
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\file_if_exist:nF { piton.lua }
  { \msg_critical:nn { piton } { piton.lua~not~found } }
%    \end{macrocode}
%
%
% \bigskip
% The boolean |\g_@@_footnotehyper_bool| will indicate if the option
% |footnotehyper| is used.
%    \begin{macrocode}
\bool_new:N \g_@@_footnotehyper_bool
%    \end{macrocode}
%
% \medskip
% The boolean |\g_@@_footnote_bool| will indicate if the option |footnote| is
% used, but quicky, it will also be set to |true| if the option |footnotehyper|
% is used.
%    \begin{macrocode}
\bool_new:N \g_@@_footnote_bool
%    \end{macrocode}
%
% \medskip
% The following boolean corresponds to the key |math-comments| (available only at load-time).
%    \begin{macrocode}
\bool_new:N \g_@@_math_comments_bool
%    \end{macrocode}
%
% \medskip
%    \begin{macrocode}
\bool_new:N \g_@@_beamer_bool
\tl_new:N \g_@@_escape_inside_tl 
%    \end{macrocode}
% 
% \bigskip
% We define a set of keys for the options at load-time.
%    \begin{macrocode}
\keys_define:nn { piton / package }
  { 
    footnote .bool_gset:N = \g_@@_footnote_bool ,
    footnotehyper .bool_gset:N = \g_@@_footnotehyper_bool ,

    beamer .bool_gset:N = \g_@@_beamer_bool ,
    beamer .default:n = true , 
  
    math-comments .code:n = \@@_error:n { moved~to~preamble } , 
    comment-latex .code:n = \@@_error:n { moved~to~preamble } , 

    unknown .code:n = \@@_error:n { Unknown~key~for~package }
  }
%    \end{macrocode}
%
%
% \bigskip
%    \begin{macrocode}
\@@_msg_new:nn { moved~to~preamble }
  {
    The~key~'\l_keys_key_str'~*must*~now~be~used~with~
    \token_to_str:N \PitonOptions`in~the~preamble~of~your~
    document.\\
    That~key~will~be~ignored.
  }
%    \end{macrocode}
% 
%    \begin{macrocode}
\@@_msg_new:nn { Unknown~key~for~package }
  {
    Unknown~key.\\
    You~have~used~the~key~'\l_keys_key_str'~but~the~only~keys~available~here~
    are~'beamer',~'footnote',~'footnotehyper'.~Other~keys~are~available~in~
    \token_to_str:N \PitonOptions.\\ 
    That~key~will~be~ignored.
  }
%    \end{macrocode}
%
%
% \bigskip
% We process the options provided by the user at load-time.
%    \begin{macrocode}
\ProcessKeysOptions { piton / package }
%    \end{macrocode}
%
% 
% \bigskip
%    \begin{macrocode}
\@ifclassloaded { beamer } { \bool_gset_true:N \g_@@_beamer_bool } { }
\@ifpackageloaded { beamerarticle } { \bool_gset_true:N \g_@@_beamer_bool } { }
\bool_if:NT \g_@@_beamer_bool { \lua_now:n { piton_beamer = true } } 
%    \end{macrocode}
% 
% \bigskip
%    \begin{macrocode}
\hook_gput_code:nnn { begindocument } { . }
  {
    \@ifpackageloaded { xcolor }
      { }
      { \msg_fatal:nn { piton } { xcolor~not~loaded } }
  }
%    \end{macrocode}
%
%    \begin{macrocode}     
\@@_msg_new:nn { xcolor~not~loaded }
  {
    xcolor~not~loaded \\
    The~package~'xcolor'~is~required~by~'piton'.\\
    This~error~is~fatal.
  }
%    \end{macrocode}
% 
%
%    \begin{macrocode}
\@@_msg_new:nn { footnote~with~footnotehyper~package }
  { 
    Footnote~forbidden.\\
    You~can't~use~the~option~'footnote'~because~the~package~
    footnotehyper~has~already~been~loaded.~
    If~you~want,~you~can~use~the~option~'footnotehyper'~and~the~footnotes~  
    within~the~environments~of~piton~will~be~extracted~with~the~tools~
    of~the~package~footnotehyper.\\
    If~you~go~on,~the~package~footnote~won't~be~loaded.
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_msg_new:nn { footnotehyper~with~footnote~package }
  { 
    You~can't~use~the~option~'footnotehyper'~because~the~package~
    footnote~has~already~been~loaded.~
    If~you~want,~you~can~use~the~option~'footnote'~and~the~footnotes~  
    within~the~environments~of~piton~will~be~extracted~with~the~tools~
    of~the~package~footnote.\\ 
    If~you~go~on,~the~package~footnotehyper~won't~be~loaded.
  }
%    \end{macrocode}
%
% \medskip
%    \begin{macrocode}
\bool_if:NT \g_@@_footnote_bool 
  { 
%    \end{macrocode}
% The class \cls{beamer} has its own system to extract footnotes and that's why
% we have nothing to do if \cls{beamer} is used. 
%    \begin{macrocode}
    \@ifclassloaded { beamer }
      { \bool_gset_false:N \g_@@_footnote_bool }
      { 
        \@ifpackageloaded { footnotehyper }
          { \@@_error:n { footnote~with~footnotehyper~package } }
          { \usepackage { footnote } }
      }
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\bool_if:NT \g_@@_footnotehyper_bool 
  { 
%    \end{macrocode}
% The class \cls{beamer} has its own system to extract footnotes and that's why
% we have nothing to do if \cls{beamer} is used. 
%    \begin{macrocode}
    \@ifclassloaded { beamer }
      { \bool_gset_false:N \g_@@_footnote_bool }
      { 
        \@ifpackageloaded { footnote }
          { \@@_error:n { footnotehyper~with~footnote~package } }
          { \usepackage { footnotehyper } }
        \bool_gset_true:N \g_@@_footnote_bool 
      }
  }
%    \end{macrocode}
% The flag |\g_@@_footnote_bool| is raised and so, we will only have to test
% |\g_@@_footnote_bool| in order to know if we have to insert an environment
% |{savenotes}|.
%
% \bigskip
%    \begin{macrocode}
\lua_now:n 
  { 
    piton = piton~or { } 
    piton.ListCommands = lpeg.P ( false ) 
    piton.last_code = ''
    piton.last_language = ''
  }
%    \end{macrocode}
% 
% \bigskip
% \subsubsection{Parameters and technical definitions}
%
% The following string will contain the name of the informatic language
% considered (the initial value is |python|).
%
%    \begin{macrocode}
\str_new:N \l_piton_language_str
\str_set:Nn \l_piton_language_str { python }
%    \end{macrocode}
% 
% \medskip
% Each time the command |\PitonInputFile| or an environment of \pkg{piton} is
% used, the code of that environment will be stored in the following global string.
%    \begin{macrocode}
\tl_new:N \g_piton_last_code_tl
%    \end{macrocode}
%
% \medskip
% The following parameter corresponds to the key |path| (which is the path used
% to include files by |\PitonInputFile|).
%    \begin{macrocode}
\str_new:N \l_@@_path_str
%    \end{macrocode}
%
% \medskip
% The following parameter corresponds to the key |path-write| (which is the path
% used when writing files from listings inserted in the environments of
% \pkg{piton} by use of the key |write|).
%    \begin{macrocode}
\str_new:N \l_@@_path_write_str
%    \end{macrocode}
% 
% \medskip
% In order to have a better control over the keys.
%    \begin{macrocode}
\bool_new:N \l_@@_in_PitonOptions_bool 
\bool_new:N \l_@@_in_PitonInputFile_bool 
%    \end{macrocode}
%
% 
% \medskip
% We will compute (with Lua) the numbers of lines of the Python code and store
% it in the following counter.
%    \begin{macrocode}
\int_new:N \l_@@_nb_lines_int
%    \end{macrocode}
% 
% The same for the number of non-empty lines of the Python codes.
%    \begin{macrocode}
\int_new:N \l_@@_nb_non_empty_lines_int
%    \end{macrocode}
% 
% The following counter will be used to count the lines during the composition.
% It will count all the lines, empty or not empty. It won't be used to print the
% numbers of the lines.
%    \begin{macrocode}
\int_new:N \g_@@_line_int
%    \end{macrocode}
% 
% \medskip
% The following token list will contain the (potential) informations to write
% on the |aux| (to be used in the next compilation).
%    \begin{macrocode}
\tl_new:N \g_@@_aux_tl
%    \end{macrocode}
% 
% \medskip
% The following counter corresponds to the key |splittable| of |\PitonOptions|.
% If the value of |\l_@@_splittable_int| is equal to $n$, then no line break can
% occur within the first $n$~lines or the last $n$~lines of the listings.
%    \begin{macrocode}
\int_new:N \l_@@_splittable_int
%    \end{macrocode}
%
% \medskip
% An initial value of |splittable| equal to 100 is equivalent to say that the
% environments |{Piton}| are unbreakable.
%    \begin{macrocode}
\int_set:Nn \l_@@_splittable_int { 100 }
%    \end{macrocode}
%
% \medskip
% The following string corresponds to the key |background-color| of |\PitonOptions|.
%    \begin{macrocode}
\clist_new:N \l_@@_bg_color_clist
%    \end{macrocode}
%
% \medskip
% The package \pkg{piton} will also detect the lines of code which correspond to
% the user input in a Python console, that is to say the lines of code beginning
% with |>>>| and |...|. It's possible, with the key |prompt-background-color|,
% to require a background for these lines of code (and the other lines of code
% will have the standard background color specified by |background-color|).
%    \begin{macrocode}
\tl_new:N \l_@@_prompt_bg_color_tl
%    \end{macrocode}
%
% \medskip
% The following parameters correspond to the keys |begin-range| and |end-range| of
% the command |\PitonInputFile|.
%    \begin{macrocode}
\str_new:N \l_@@_begin_range_str
\str_new:N \l_@@_end_range_str
%    \end{macrocode}
%
% \medskip
% The argument of |\PitonInputFile|.
%    \begin{macrocode}
\str_new:N \l_@@_file_name_str 
%    \end{macrocode}
%
% \medskip
% We will count the environments |{Piton}| (and, in fact, also the commands
% |\PitonInputFile|, despite the name |\g_@@_env_int|).
%    \begin{macrocode}
\int_new:N \g_@@_env_int 
%    \end{macrocode}
%
% \medskip
% The parameter |\l_@@_writer_str| corresponds to the key |write|. We will store
% the list of the files already used in |\g_@@_write_seq| (we must not erase a
% file which has been still been used).
%    \begin{macrocode}
\str_new:N \l_@@_write_str
\seq_new:N \g_@@_write_seq
%    \end{macrocode}
%
% \medskip
% The following boolean corresponds to the key |show-spaces|.
%    \begin{macrocode}
\bool_new:N \l_@@_show_spaces_bool
%    \end{macrocode}
%
% \medskip
% The following booleans correspond to the keys |break-lines| and
% |indent-broken-lines|.
%    \begin{macrocode}
\bool_new:N \l_@@_break_lines_in_Piton_bool
\bool_new:N \l_@@_indent_broken_lines_bool
%    \end{macrocode}
%
% \medskip
% The following token list corresponds to the key |continuation-symbol|.
%    \begin{macrocode}
\tl_new:N \l_@@_continuation_symbol_tl
\tl_set:Nn \l_@@_continuation_symbol_tl { + }
%    \end{macrocode}
%
% \medskip
% The following token list corresponds to the key
% |continuation-symbol-on-indentation|. The name has been shorten to |csoi|.
%    \begin{macrocode}
\tl_new:N \l_@@_csoi_tl 
\tl_set:Nn \l_@@_csoi_tl { $ \hookrightarrow \; $  }
%    \end{macrocode}
%
% \medskip
% The following token list corresponds to the key |end-of-broken-line|.
%    \begin{macrocode}
\tl_new:N \l_@@_end_of_broken_line_tl 
\tl_set:Nn \l_@@_end_of_broken_line_tl { \hspace*{0.5em} \textbackslash }
%    \end{macrocode}
%
% \medskip
% The following boolean corresponds to the key |break-lines-in-piton|.
%    \begin{macrocode}
\bool_new:N \l_@@_break_lines_in_piton_bool
%    \end{macrocode}
% 
% \bigskip
% The following dimension will be the width of the listing constructed by
% |{Piton}| or |\PitonInputFile|.
% \begin{itemize}
% \item If the user uses the key |width| of |\PitonOptions| with a numerical
% value, that value will be stored in |\l_@@_width_dim|.
% \item If the user uses the key |width| with the special value~|min|, the
% dimension |\l_@@_width_dim| will, \emph{in the second run}, be computed from
% the value of |\l_@@_line_width_dim| stored in the |aux| file
% (computed during the first run the maximal width of the lines of the listing).
% During the first run, |\l_@@_width_line_dim| will be set equal to |\linewidth|.
% \item Elsewhere, |\l_@@_width_dim| will be set at the beginning of the listing
% (in |\@@_pre_env:|) equal to the current value of |\linewidth|.
% \end{itemize}
% 
%    \begin{macrocode} 
\dim_new:N \l_@@_width_dim 
%    \end{macrocode}
% 
% \medskip
% We will also use another dimension called |\l_@@_line_width_dim|. That
% will the width of the actual lines of code. That dimension may be lower than
% the whole |\l_@@_width_dim| because we have to take into account the value of
% |\l_@@_left_margin_dim| (for the numbers of lines when |line-numbers| is in
% force) and another small margin when a background color is used (with the key
% |background-color|). 
%    \begin{macrocode}
\dim_new:N \l_@@_line_width_dim
%    \end{macrocode}
% 
% \medskip
% The following flag will be raised with the key |width| is used with the
% special value |min|.
%    \begin{macrocode}
\bool_new:N \l_@@_width_min_bool
%    \end{macrocode}
%
% \medskip
% If the key |width| is used with the special value~|min|, we will compute the
% maximal width of the lines of an environment |{Piton}| in |\g_@@_tmp_width_dim|
% because we need it for the case of the key |width| is used with the spacial
% value |min|. We need a global variable because, when the key |footnote| is in
% force, each line when be composed in an environment |{savenotes}| and we need
% to exit our |\g_@@_tmp_width_dim| from that environment.
%    \begin{macrocode}
\dim_new:N \g_@@_tmp_width_dim 
%    \end{macrocode}
%
% \medskip
% The following dimension corresponds to the key |left-margin| of |\PitonOptions|. 
%    \begin{macrocode}
\dim_new:N \l_@@_left_margin_dim
%    \end{macrocode}
%
% \medskip
% The following boolean will be set when the key |left-margin=auto|
% is used.
%    \begin{macrocode}
\bool_new:N \l_@@_left_margin_auto_bool
%    \end{macrocode}
%
% \medskip
% The following dimension corresponds to the key |numbers-sep| of
% |\PitonOptions|.
%    \begin{macrocode}
\dim_new:N \l_@@_numbers_sep_dim 
\dim_set:Nn \l_@@_numbers_sep_dim { 0.7 em }
%    \end{macrocode}
% 
% \medskip
% The tabulators will be replaced by the content of the following token list.
%    \begin{macrocode}
\tl_new:N \l_@@_tab_tl
%    \end{macrocode}
%
% \medskip
% Be careful. The following sequence |\g_@@_languages_seq| is not the list of
% the languages supported by \pkg{piton}. It's the list of the languages for
% which at least a user function has been defined. We need that sequence only
% for the command |\PitonClearUserFunctions| when it is used without its
% optional argument: it must clear all the list of languages for which at least
% a user function has been defined.
%    \begin{macrocode}
\seq_new:N \g_@@_languages_seq 
%    \end{macrocode}
% 
%
% \medskip
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_tab_tl:n #1
  { 
    \tl_clear:N \l_@@_tab_tl
    \prg_replicate:nn { #1 } 
      { \tl_put_right:Nn \l_@@_tab_tl { ~ } }
  }
\@@_set_tab_tl:n { 4 }
%    \end{macrocode}
% 
% \medskip
% The following integer corresponds to the key |gobble|.
%    \begin{macrocode}
\int_new:N \l_@@_gobble_int 
%    \end{macrocode}
%
% \medskip
%    \begin{macrocode}
\tl_new:N \l_@@_space_tl
\tl_set:Nn \l_@@_space_tl { ~ } 
%    \end{macrocode}
% 
%
% \medskip
% At each line, the following counter will count the spaces at the beginning.
%    \begin{macrocode}
\int_new:N \g_@@_indentation_int
%    \end{macrocode}
% 
% \medskip
%    \begin{macrocode}
\cs_new_protected:Npn \@@_an_indentation_space:
  { \int_gincr:N \g_@@_indentation_int }
%    \end{macrocode}
%
% \medskip
% The following command |\@@_beamer_command:n| executes the argument
% corresponding to its argument but also stores it in |\l_@@_beamer_command_str|.
% That string is used only in the error message ``|cr~not~allowed|'' raised when
% there is a carriage return in the mandatory argument of that command.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_beamer_command:n #1 
  { 
    \str_set:Nn \l_@@_beamer_command_str { #1 } 
    \use:c { #1 } 
  }
%    \end{macrocode}
% 
% \bigskip
% In the environment |{Piton}|, the command |\label| will be linked to the
% following command.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_label:n #1
  {
    \bool_if:NTF \l_@@_line_numbers_bool
      {
        \@bsphack 
        \protected@write \@auxout { }
          { 
            \string \newlabel { #1 } 
            { 
%    \end{macrocode}
% Remember that the content of a line is typeset in a box \emph{before} the
% composition of the potential number of line.
%    \begin{macrocode}
              { \int_eval:n { \g_@@_visual_line_int + 1 } } 
              { \thepage } 
            } 
          } 
        \@esphack
     }
     { \@@_error:n { label~with~lines~numbers } }
  }
%    \end{macrocode}
%
% \bigskip
% The following commands corresponds to the keys |marker/beginning| and
% |marker/end|. The values of that keys are functions that will be applied to
% the ``\emph{range}'' specified by the final user in an individual
% |\PitonInputFile|. They will construct the markers used to find textually in
% the external file loaded by \pkg{piton} the part which must be included (and
% formatted). 
%    \begin{macrocode}
\cs_new_protected:Npn \@@_marker_beginning:n #1 { }
\cs_new_protected:Npn \@@_marker_end:n #1 { }
%    \end{macrocode}
% 
% 
% \bigskip
% The following commands are a easy way to insert safely braces (|{| and |}|) in
% the TeX flow.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_open_brace: { \lua_now:n { piton.open_brace() } }
\cs_new_protected:Npn \@@_close_brace: { \lua_now:n { piton.close_brace() } }
%    \end{macrocode}
% 
% \bigskip
% The following token list will be evaluated at the beginning of
% |\@@_begin_line:|... |\@@_end_line:| and cleared at the end. It will be used
% by LPEG acting between the lines of the Python code in order to add
% instructions to be executed at the beginning of the line.
%    \begin{macrocode} 
\tl_new:N \g_@@_begin_line_hook_tl
%    \end{macrocode}
%
% \smallskip
% For example, the LPEG |Prompt| will trigger the following command which will
% insert an instruction in the hook |\g_@@_begin_line_hook| to specify that a
% background must be inserted to the current line of code.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_prompt: 
  { 
    \tl_gset:Nn \g_@@_begin_line_hook_tl
      { 
        \tl_if_empty:NF \l_@@_prompt_bg_color_tl 
          { \clist_set:NV \l_@@_bg_color_clist \l_@@_prompt_bg_color_tl }
      } 
  }
%    \end{macrocode}
%
% 
% \bigskip
% \subsubsection{Treatment of a line of code}
% 
%    \begin{macrocode}
\cs_new_protected:Npn \@@_replace_spaces:n #1 
  {
    \tl_set:Nn \l_tmpa_tl { #1 } 
    \bool_if:NTF \l_@@_show_spaces_bool
      { 
        \tl_set:Nn \l_@@_space_tl { ␣ }
        \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl % U+2423
      } 
      {
%    \end{macrocode}
% If the key |break-lines-in-Piton| is in force, we replace all the characters
% U+0020 (that is to say the spaces) by |\@@_breakable_space:|. Remark that,
% except the spaces inserted in the LaTeX comments (and maybe in the math
% comments), all these spaces are of catcode ``other'' (=12) and are
% unbreakable.
%    \begin{macrocode}
        \bool_if:NT \l_@@_break_lines_in_Piton_bool
          { 
            \regex_replace_all:nnN 
              { \x20 } 
              { \c { @@_breakable_space: } }
              \l_tmpa_tl 
          } 
      }
    \l_tmpa_tl 
  }
%    \end{macrocode}
% 
% \bigskip
% In the contents provided by Lua, each line of the Python code will be
% surrounded by |\@@_begin_line:| and |\@@_end_line:|. |\@@_begin_line:| is a
% LaTeX command that we will define now but |\@@_end_line:| is only a syntactic
% marker that has no definition.
%
%    \begin{macrocode}
\cs_set_protected:Npn \@@_begin_line: #1 \@@_end_line:
  { 
    \group_begin:
    \g_@@_begin_line_hook_tl
    \int_gzero:N \g_@@_indentation_int
%    \end{macrocode}
%
% \medskip
% First, we will put in the coffin |\l_tmpa_coffin| the actual content of a line
% of the code (without the potential number of line).
%
% Be careful: There is curryfication in the following code.
%    \begin{macrocode}
    \bool_if:NTF \l_@@_width_min_bool
      \@@_put_in_coffin_ii:n 
      \@@_put_in_coffin_i:n 
      { 
        \language = -1
        \raggedright 
        \strut 
        \@@_replace_spaces:n { #1 }
        \strut \hfil 
      } 
%    \end{macrocode}
% Now, we add the potential number of line, the potential left margin and the
% potential background.
%    \begin{macrocode}
    \hbox_set:Nn \l_tmpa_box 
      { 
        \skip_horizontal:N \l_@@_left_margin_dim
        \bool_if:NT \l_@@_line_numbers_bool
          {
            \bool_if:nF
              { 
                \str_if_eq_p:nn { #1 } { \PitonStyle {Prompt}{} } 
                && 
                \l_@@_skip_empty_lines_bool 
              }
              { \int_gincr:N \g_@@_visual_line_int}

            \bool_if:nT
              { 
                ! \str_if_eq_p:nn { #1 } { \PitonStyle {Prompt}{} } 
                ||
                ( ! \l_@@_skip_empty_lines_bool && \l_@@_label_empty_lines_bool ) 
              }
              \@@_print_number: 

          }
%    \end{macrocode}
% If there is a background, we must remind that there is a left margin of 0.5~em
% for the background...
%    \begin{macrocode}
        \clist_if_empty:NF \l_@@_bg_color_clist 
          { 
%    \end{macrocode}
% ... but if only if the key |left-margin| is not used !
%    \begin{macrocode}
            \dim_compare:nNnT \l_@@_left_margin_dim = \c_zero_dim 
               { \skip_horizontal:n { 0.5 em } }
          }
        \coffin_typeset:Nnnnn \l_tmpa_coffin T l \c_zero_dim \c_zero_dim 
      }  
    \box_set_dp:Nn \l_tmpa_box { \box_dp:N \l_tmpa_box + 1.25 pt } 
    \box_set_ht:Nn \l_tmpa_box { \box_ht:N \l_tmpa_box + 1.25 pt } 
    \clist_if_empty:NTF \l_@@_bg_color_clist
      { \box_use_drop:N \l_tmpa_box }
      {
        \vtop 
          { 
            \hbox:n
              { 
                \@@_color:N \l_@@_bg_color_clist
                \vrule height \box_ht:N \l_tmpa_box 
                       depth \box_dp:N \l_tmpa_box 
                       width \l_@@_width_dim
              } 
            \skip_vertical:n { - \box_ht_plus_dp:N \l_tmpa_box }
            \box_use_drop:N \l_tmpa_box
          }
      }   
    \vspace { - 2.5 pt }
    \group_end:
    \tl_gclear:N \g_@@_begin_line_hook_tl
  }
%    \end{macrocode}
%
% \bigskip
% In the general case (which is also the simpler), the key |width| is not used,
% or (if used) it is not used with the special value~|min|.
% In that case, the content of a line of code is composed in a vertical coffin
% with a width equal to |\l_@@_line_width_dim|. That coffin may,
% eventually, contains several lines when the key |broken-lines-in-Piton| (or
% |broken-lines|) is used.
% 
% That commands takes in its argument by curryfication.
%    \begin{macrocode}
\cs_set_protected:Npn \@@_put_in_coffin_i:n 
  { \vcoffin_set:Nnn \l_tmpa_coffin \l_@@_line_width_dim }
%    \end{macrocode}
%
% \bigskip
% The second case is the case when the key |width| is used with the special
% value~|min|. 
%    \begin{macrocode}
\cs_set_protected:Npn \@@_put_in_coffin_ii:n #1
  {
%    \end{macrocode}
% First, we compute the natural width of the line of code because we have to
% compute the natural width of the whole listing (and it will be written on the
% |aux| file in the variable |\l_@@_width_dim|).
%    \begin{macrocode}
    \hbox_set:Nn \l_tmpa_box { #1 }
%    \end{macrocode}
% Now, you can actualize the value of |\g_@@_tmp_width_dim| (it will be used to 
% write on the |aux| file the natural width of the environment).
%    \begin{macrocode}
    \dim_compare:nNnT { \box_wd:N \l_tmpa_box } > \g_@@_tmp_width_dim
      { \dim_gset:Nn \g_@@_tmp_width_dim { \box_wd:N \l_tmpa_box } }
%    \end{macrocode}
% 
%    \begin{macrocode}
    \hcoffin_set:Nn \l_tmpa_coffin 
      { 
        \hbox_to_wd:nn \l_@@_line_width_dim 
%    \end{macrocode}
% We unpack the block in order to free the potential |\hfill| springs present in
% the LaTeX comments (cf. section~\ref{example-comments}, p.~\pageref{example-comments}).
%    \begin{macrocode}
          { \hbox_unpack:N \l_tmpa_box \hfil } 
      } 
  }
%    \end{macrocode}
%
% 
% \bigskip
% The command |\@@_color:N| will take in as argument a reference to a
% comma-separated list of colors. A color will be picked by using the value of
% |\g_@@_line_int| (modulo the number of colors in the list).
%    \begin{macrocode}
\cs_set_protected:Npn \@@_color:N #1 
  {
    \int_set:Nn \l_tmpa_int { \clist_count:N #1 }
    \int_set:Nn \l_tmpb_int { \int_mod:nn \g_@@_line_int \l_tmpa_int + 1 }
    \tl_set:Nx \l_tmpa_tl { \clist_item:Nn #1 \l_tmpb_int }
    \tl_if_eq:NnTF \l_tmpa_tl { none }
%    \end{macrocode}
% By setting |\l_@@_width_dim| to zero, the colored rectangle will be
% drawn with zero width and, thus, it will be a mere strut (and we need that strut).
%    \begin{macrocode}
      { \dim_zero:N \l_@@_width_dim }
      { \exp_args:NV \@@_color_i:n \l_tmpa_tl }
  }
%    \end{macrocode}
%
% The following command |\@@_color:n| will accept both the instruction
% |\@@_color:n { red!15 }| and the instruction |\@@_color:n { [rgb]{0.9,0.9,0} }|.
%    \begin{macrocode}
\cs_set_protected:Npn \@@_color_i:n #1
  {
    \tl_if_head_eq_meaning:nNTF { #1 } [ 
      { 
        \tl_set:Nn \l_tmpa_tl { #1 }
        \tl_set_rescan:Nno \l_tmpa_tl { } \l_tmpa_tl 
        \exp_last_unbraced:No \color \l_tmpa_tl
      }
      { \color { #1 } }
  }
%    \end{macrocode}
% 
% \bigskip
%    \begin{macrocode}
\cs_new_protected:Npn \@@_newline: 
  { 
    \int_gincr:N \g_@@_line_int
    \int_compare:nNnT \g_@@_line_int > { \l_@@_splittable_int - 1 }
      {
        \int_compare:nNnT 
          { \l_@@_nb_lines_int - \g_@@_line_int } > \l_@@_splittable_int 
          {
            \egroup
            \bool_if:NT \g_@@_footnote_bool { \end { savenotes } } 
            \par \mode_leave_vertical: 
            \bool_if:NT \g_@@_footnote_bool { \begin { savenotes } } 
            \vtop \bgroup
          }
     }
  } 
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\cs_set_protected:Npn \@@_breakable_space:
  { 
    \discretionary 
      { \hbox:n { \color { gray } \l_@@_end_of_broken_line_tl } } 
      { 
        \hbox_overlap_left:n 
          { 
            { 
              \normalfont \footnotesize \color { gray } 
              \l_@@_continuation_symbol_tl 
            } 
            \skip_horizontal:n { 0.3 em }  
            \clist_if_empty:NF \l_@@_bg_color_clist 
              { \skip_horizontal:n { 0.5 em } }
          }  
        \bool_if:NT \l_@@_indent_broken_lines_bool
          { 
            \hbox:n
              { 
                \prg_replicate:nn { \g_@@_indentation_int } { ~ } 
                { \color { gray } \l_@@_csoi_tl }
              } 
          } 
      } 
      { \hbox { ~ } }
  }
%    \end{macrocode}
% 
% \bigskip
% \subsubsection{PitonOptions}
%
% \medskip
%    \begin{macrocode}
\bool_new:N \l_@@_line_numbers_bool 
\bool_new:N \l_@@_skip_empty_lines_bool 
\bool_set_true:N \l_@@_skip_empty_lines_bool 
\bool_new:N \l_@@_line_numbers_absolute_bool
\bool_new:N \l_@@_label_empty_lines_bool
\bool_set_true:N \l_@@_label_empty_lines_bool 
\int_new:N \l_@@_number_lines_start_int
\bool_new:N \l_@@_resume_bool 
%    \end{macrocode}
% 
%
%  \bigskip
%    \begin{macrocode}
\keys_define:nn { PitonOptions / marker }
  {
    beginning .code:n = \cs_set:Nn \@@_marker_beginning:n { #1 } ,   
    beginning .value_required:n = true , 
    end .code:n = \cs_set:Nn \@@_marker_end:n { #1 } ,   
    end .value_required:n = true ,
    include-lines .bool_set:N = \l_@@_marker_include_lines_bool ,
    include-lines .default:n = true ,
    unknown .code:n = \@@_error:n { Unknown~key~for~marker } 
  }
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\keys_define:nn { PitonOptions / line-numbers }
  {
    true .code:n = \bool_set_true:N \l_@@_line_numbers_bool , 
    false .code:n = \bool_set_false:N \l_@@_line_numbers_bool , 

    start .code:n = 
      \bool_if:NTF \l_@@_in_PitonOptions_bool
        { Invalid~key }
        {
          \bool_set_true:N \l_@@_line_numbers_bool 
          \int_set:Nn \l_@@_number_lines_start_int { #1 }  
        } ,
    start .value_required:n = true ,

    skip-empty-lines .code:n = 
      \bool_if:NF \l_@@_in_PitonOptions_bool
        { \bool_set_true:N \l_@@_line_numbers_bool }
      \str_if_eq:nnTF { #1 } { false }
        { \bool_set_false:N \l_@@_skip_empty_lines_bool } 
        { \bool_set_true:N \l_@@_skip_empty_lines_bool } ,
    skip-empty-lines .default:n = true , 

    label-empty-lines .code:n = 
      \bool_if:NF \l_@@_in_PitonOptions_bool
        { \bool_set_true:N \l_@@_line_numbers_bool }
      \str_if_eq:nnTF { #1 } { false }
        { \bool_set_false:N \l_@@_label_empty_lines_bool } 
        { \bool_set_true:N \l_@@_label_empty_lines_bool } ,
    label-empty-lines .default:n = true ,

    absolute .code:n = 
      \bool_if:NTF \l_@@_in_PitonOptions_bool
        { \bool_set_true:N \l_@@_line_numbers_absolute_bool }
        { \bool_set_true:N \l_@@_line_numbers_bool }
      \bool_if:NT \l_@@_in_PitonInputFile_bool 
        { 
          \bool_set_true:N \l_@@_line_numbers_absolute_bool 
          \bool_set_false:N \l_@@_skip_empty_lines_bool 
        }
      \bool_lazy_or:nnF
        \l_@@_in_PitonInputFile_bool 
        \l_@@_in_PitonOptions_bool 
        { \@@_error:n { Invalid~key } } ,
    absolute .value_forbidden:n = true ,

    resume .code:n = 
      \bool_set_true:N \l_@@_resume_bool 
      \bool_if:NF \l_@@_in_PitonOptions_bool 
        { \bool_set_true:N \l_@@_line_numbers_bool } , 
    resume .value_forbidden:n = true ,

    sep .dim_set:N = \l_@@_numbers_sep_dim ,
    sep .value_required:n = true , 

    unknown .code:n = \@@_error:n { Unknown~key~for~line-numbers } 
  }
%    \end{macrocode}
% 
% \bigskip
% Be careful! The name of the following set of keys must be considered as
% public! Hence, it should \emph{not} be changed.
% 
%    \begin{macrocode}
\keys_define:nn { PitonOptions }
  {
    detected-commands .code:n =  
       \lua_now:n { piton.addListCommands('#1') } ,
    detected-commands .value_required:n = true , 
    detected-commands .usage:n = preamble , 
%    \end{macrocode}
% First, we put keys that should be avalaible only in the preamble.
%
% Remark that the command |\lua_escape:n| is fully expandable. That's why we use
% |\lua_now:e|.
%    \begin{macrocode}
    begin-escape .code:n = 
      \lua_now:e { piton.begin_escape = "\lua_escape:n{#1}" } ,
    begin-escape .value_required:n = true , 
    begin-escape .usage:n = preamble , 

    end-escape   .code:n = 
      \lua_now:e { piton.end_escape = "\lua_escape:n{#1}" } ,
    end-escape   .value_required:n = true ,
    end-escape .usage:n = preamble ,

    begin-escape-math .code:n = 
      \lua_now:e { piton.begin_escape_math = "\lua_escape:n{#1}" } ,
    begin-escape-math .value_required:n = true , 
    begin-escape-math .usage:n = preamble ,

    end-escape-math .code:n = 
      \lua_now:e { piton.end_escape_math = "\lua_escape:n{#1}" } ,
    end-escape-math .value_required:n = true ,
    end-escape-math .usage:n = preamble ,

    comment-latex .code:n = \lua_now:n { comment_latex = "#1" } ,   
    comment-latex .value_required:n = true ,
    comment-latex .usage:n = preamble ,

    math-comments .bool_gset:N = \g_@@_math_comments_bool ,
    math-comments .default:n  = true ,
    math-comments .usage:n = preamble , 
%    \end{macrocode}
% 
% \bigskip
% Now, general keys.
%    \begin{macrocode}
    language         .code:n = 
      \str_set:Nx \l_piton_language_str { \str_lowercase:n { #1 } } , 
    language         .value_required:n  = true ,
    path             .str_set:N         = \l_@@_path_str ,
    path             .value_required:n  = true , 
    path-write       .str_set:N         = \l_@@_path_write_str ,
    path-write       .value_required:n  = true , 
    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 ,
    env-gobble       .code:n            = \int_set:Nn \l_@@_gobble_int { -2 } , 
    env-gobble       .value_forbidden:n = true ,
    tabs-auto-gobble .code:n            = \int_set:Nn \l_@@_gobble_int { -3 } , 
    tabs-auto-gobble .value_forbidden:n = true ,
 
    marker .code:n = 
      \bool_lazy_or:nnTF
        \l_@@_in_PitonInputFile_bool 
        \l_@@_in_PitonOptions_bool 
        { \keys_set:nn { PitonOptions / marker } { #1 } } 
        { \@@_error:n { Invalid~key } } , 
    marker .value_required:n = true , 

    line-numbers .code:n = 
      \keys_set:nn { PitonOptions / line-numbers } { #1 } ,
    line-numbers .default:n = true , 

    splittable       .int_set:N         = \l_@@_splittable_int ,
    splittable       .default:n         = 1 , 
    background-color .clist_set:N       = \l_@@_bg_color_clist ,
    background-color .value_required:n  = true ,
    prompt-background-color .tl_set:N         = \l_@@_prompt_bg_color_tl ,
    prompt-background-color .value_required:n = true ,

    width .code:n = 
      \str_if_eq:nnTF  { #1 } { min } 
        { 
          \bool_set_true:N \l_@@_width_min_bool 
          \dim_zero:N \l_@@_width_dim 
        }
        { 
          \bool_set_false:N \l_@@_width_min_bool
          \dim_set:Nn \l_@@_width_dim { #1 } 
        } , 
    width .value_required:n  = true ,

    write .str_set:N = \l_@@_write_str ,
    write .value_required:n = true ,

    left-margin      .code:n =
      \str_if_eq:nnTF { #1 } { auto }
        { 
          \dim_zero:N \l_@@_left_margin_dim 
          \bool_set_true:N \l_@@_left_margin_auto_bool
        }
        { 
          \dim_set:Nn \l_@@_left_margin_dim { #1 } 
          \bool_set_false:N \l_@@_left_margin_auto_bool
        } ,
    left-margin      .value_required:n  = true ,

    tab-size         .code:n            = \@@_set_tab_tl:n { #1 } ,
    tab-size         .value_required:n  = true , 
    show-spaces      .bool_set:N        = \l_@@_show_spaces_bool , 
    show-spaces      .default:n         = true , 
    show-spaces-in-strings .code:n      = \tl_set:Nn \l_@@_space_tl { ␣ } , % U+2423
    show-spaces-in-strings .value_forbidden:n = true ,
    break-lines-in-Piton .bool_set:N    = \l_@@_break_lines_in_Piton_bool ,
    break-lines-in-Piton .default:n     = true ,
    break-lines-in-piton .bool_set:N    = \l_@@_break_lines_in_piton_bool ,
    break-lines-in-piton .default:n     = true ,
    break-lines .meta:n = { break-lines-in-piton , break-lines-in-Piton } , 
    break-lines .value_forbidden:n      = true ,
    indent-broken-lines .bool_set:N     = \l_@@_indent_broken_lines_bool ,
    indent-broken-lines .default:n      = true ,
    end-of-broken-line  .tl_set:N       = \l_@@_end_of_broken_line_tl ,
    end-of-broken-line  .value_required:n = true , 
    continuation-symbol .tl_set:N       = \l_@@_continuation_symbol_tl ,
    continuation-symbol .value_required:n = true , 
    continuation-symbol-on-indentation .tl_set:N = \l_@@_csoi_tl ,
    continuation-symbol-on-indentation .value_required:n = true , 

    first-line .code:n = \@@_in_PitonInputFile:n 
      { \int_set:Nn \l_@@_first_line_int { #1 } } ,
    first-line .value_required:n = true ,

    last-line .code:n = \@@_in_PitonInputFile:n 
      { \int_set:Nn \l_@@_last_line_int { #1 } } ,
    last-line .value_required:n = true , 

    begin-range .code:n = \@@_in_PitonInputFile:n 
      { \str_set:Nn \l_@@_begin_range_str { #1 } } ,
    begin-range .value_required:n = true ,

    end-range .code:n = \@@_in_PitonInputFile:n 
      { \str_set:Nn \l_@@_end_range_str { #1 } } ,
    end-range .value_required:n = true ,

    range .code:n = \@@_in_PitonInputFile:n 
      { 
        \str_set:Nn \l_@@_begin_range_str { #1 } 
        \str_set:Nn \l_@@_end_range_str { #1 } 
      } ,
    range .value_required:n = true ,

    resume .meta:n = line-numbers/resume , 

    unknown .code:n = \@@_error:n { Unknown~key~for~PitonOptions } ,

    % deprecated
    all-line-numbers .code:n = 
      \bool_set_true:N \l_@@_line_numbers_bool 
      \bool_set_false:N \l_@@_skip_empty_lines_bool ,
    all-line-numbers .value_forbidden:n = true ,

    % deprecated
    numbers-sep .dim_set:N = \l_@@_numbers_sep_dim ,
    numbers-sep .value_required:n = true 
  }
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\cs_new_protected:Npn \@@_in_PitonInputFile:n #1
  {
    \bool_if:NTF \l_@@_in_PitonInputFile_bool 
      { #1 }
      { \@@_error:n { Invalid~key } } 
  }
%    \end{macrocode}
% 
%
% \bigskip
%    \begin{macrocode}
\NewDocumentCommand \PitonOptions { m } 
  { 
    \bool_set_true:N \l_@@_in_PitonOptions_bool
    \keys_set:nn { PitonOptions } { #1 }
    \bool_set_false:N \l_@@_in_PitonOptions_bool
  }
%    \end{macrocode}
%
% \bigskip
% When using |\NewPitonEnvironment| a user may use |\PitonOptions| inside.
% However, the set of keys available should be different that in standard
% |\PitonOptions|. That's why we define a version of |\PitonOptions| with no
% restrection on the set of available keys and we will link that version to
% |\PitonOptions| in such environment.
%    \begin{macrocode}
\NewDocumentCommand \@@_fake_PitonOptions { } 
  { \keys_set:nn { PitonOptions } }
%    \end{macrocode}
% 
%
% 
%
% \bigskip
% \subsubsection{The numbers of the lines}
%
% \medskip
% 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 (with |line-numbers|).
%
%    \begin{macrocode}
\int_new:N \g_@@_visual_line_int 
%    \end{macrocode}
% 
% 
%    \begin{macrocode}
\cs_new_protected:Npn \@@_print_number:
  {
    \hbox_overlap_left:n
      { 
        { 
          \color { gray } 
          \footnotesize 
          \int_to_arabic:n \g_@@_visual_line_int 
        } 
        \skip_horizontal:N \l_@@_numbers_sep_dim  
      }
  }
%    \end{macrocode}
% 
%
% \bigskip
% \subsubsection{The command to write on the aux file}
%
%   
%    \begin{macrocode}
\cs_new_protected:Npn \@@_write_aux:
  {
    \tl_if_empty:NF \g_@@_aux_tl 
      {
        \iow_now:Nn \@mainaux { \ExplSyntaxOn }
        \iow_now:Nx \@mainaux 
          {
            \tl_gset:cn { c_@@_ \int_use:N \g_@@_env_int _ tl } 
              { \exp_not:o \g_@@_aux_tl } 
          }
        \iow_now:Nn \@mainaux { \ExplSyntaxOff }
      }
    \tl_gclear:N \g_@@_aux_tl 
  }
%    \end{macrocode}
%
% \bigskip
% The following macro with be used only when the key |width| is used with the
% special value~|min|.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_width_to_aux:
  {
    \tl_gput_right:Nx \g_@@_aux_tl
      { 
        \dim_set:Nn \l_@@_line_width_dim 
          { \dim_eval:n { \g_@@_tmp_width_dim } }
      } 
  }
%    \end{macrocode}
% 
% \bigskip
% \subsubsection{The main commands and environments for the final user}
%
% \bigskip
%    \begin{macrocode}
\NewDocumentCommand { \piton } { }
  { \peek_meaning:NTF \bgroup \@@_piton_standard \@@_piton_verbatim }
%    \end{macrocode}
%
%    \begin{macrocode}
\NewDocumentCommand { \@@_piton_standard } { m }
  {
    \group_begin:
    \ttfamily
%    \end{macrocode}
% The following tuning of LuaTeX in order to avoid all break of lines on the
% hyphens. 
%    \begin{macrocode}
    \automatichyphenmode = 1
    \cs_set_eq:NN \\ \c_backslash_str
    \cs_set_eq:NN \% \c_percent_str  
    \cs_set_eq:NN \{ \c_left_brace_str
    \cs_set_eq:NN \} \c_right_brace_str
    \cs_set_eq:NN \$ \c_dollar_str
    \cs_set_eq:cN { ~ } \space 
    \cs_set_protected:Npn \@@_begin_line: { }
    \cs_set_protected:Npn \@@_end_line: { }
    \tl_set:Nx \l_tmpa_tl 
      { 
        \lua_now:e 
          { piton.ParseBis('\l_piton_language_str',token.scan_string()) }
          { #1 } 
      }
    \bool_if:NTF \l_@@_show_spaces_bool
      { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
%    \end{macrocode}
% The following code replaces the characters U+0020 (spaces) by characters
% U+0020 of catcode~10: thus, they become breakable by an end of line.
%    \begin{macrocode}
      {
        \bool_if:NT \l_@@_break_lines_in_piton_bool
          { \regex_replace_all:nnN { \x20 } { \x20 } \l_tmpa_tl }
      }
    \l_tmpa_tl 
    \group_end:
  }
%    \end{macrocode}
%
% 
%    \begin{macrocode}
\NewDocumentCommand { \@@_piton_verbatim } { v }
  {
    \group_begin:
    \ttfamily
    \automatichyphenmode = 1
    \cs_set_protected:Npn \@@_begin_line: { }
    \cs_set_protected:Npn \@@_end_line: { }
    \tl_set:Nx \l_tmpa_tl 
      { 
        \lua_now:e 
          { piton.Parse('\l_piton_language_str',token.scan_string()) } 
          { #1 } 
      }
    \bool_if:NT \l_@@_show_spaces_bool
      { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
    \l_tmpa_tl 
    \group_end:
  }
%    \end{macrocode}
%

%  \bigskip
%
%
% \bigskip
% The following command is not a user command. It will be used when we will
% have to ``rescan'' some chunks of Python code. For example, it will be the
% initial value of the Piton style |InitialValues| (the default values of the
% arguments of a Python function).
%    \begin{macrocode}
\cs_new_protected:Npn \@@_piton:n #1
  { 
    \group_begin:
    \cs_set_protected:Npn \@@_begin_line: { }
    \cs_set_protected:Npn \@@_end_line: { }
    \bool_lazy_or:nnTF 
      \l_@@_break_lines_in_piton_bool
      \l_@@_break_lines_in_Piton_bool
      {
        \tl_set:Nx \l_tmpa_tl 
          { 
            \lua_now:e 
              { piton.ParseTer('\l_piton_language_str',token.scan_string()) } 
              { #1 } 
          }
      }
      {
        \tl_set:Nx \l_tmpa_tl 
          { 
            \lua_now:e 
              { piton.Parse('\l_piton_language_str',token.scan_string()) }
              { #1 } 
          }
      }
    \bool_if:NT \l_@@_show_spaces_bool
      { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
    \l_tmpa_tl 
    \group_end:
  }
%    \end{macrocode}
%
% \bigskip
% The following command is similar to the previous one but raise a fatal error if
% its argument contains a carriage return.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_piton_no_cr:n #1
  { 
    \group_begin:
    \cs_set_protected:Npn \@@_begin_line: { }
    \cs_set_protected:Npn \@@_end_line: { }
    \cs_set_protected:Npn \@@_newline:
      { \msg_fatal:nn { piton } { cr~not~allowed } }
    \bool_lazy_or:nnTF 
      \l_@@_break_lines_in_piton_bool
      \l_@@_break_lines_in_Piton_bool
      {
        \tl_set:Nx \l_tmpa_tl 
          { 
            \lua_now:e 
              { piton.ParseTer('\l_piton_language_str',token.scan_string()) } 
              { #1 }
          } 
      }
      {
        \tl_set:Nx \l_tmpa_tl 
          { 
            \lua_now:e 
              { piton.Parse('\l_piton_language_str',token.scan_string()) }
              { #1 } 
          }
      }
    \bool_if:NT \l_@@_show_spaces_bool
      { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
    \l_tmpa_tl 
    \group_end:
  }
%    \end{macrocode}
% 
% \bigskip
% Despite its name, |\@@_pre_env:| will be used both in |\PitonInputFile| and
% in the environments such as |{Piton}|.
%    \begin{macrocode}
\cs_new:Npn \@@_pre_env:
  {
    \automatichyphenmode = 1
    \int_gincr:N \g_@@_env_int 
    \tl_gclear:N \g_@@_aux_tl
    \dim_compare:nNnT \l_@@_width_dim = \c_zero_dim 
      { \dim_set_eq:NN \l_@@_width_dim \linewidth }
%    \end{macrocode}
% We read the information written on the |aux| file by a previous run (when the
% key |width| is used with the special value~|min|). At this time, the only
% potential information written on the |aux| file is the value of
% |\l_@@_line_width_dim| when the key |width| has been used with the special
% value~|min|).
%    \begin{macrocode}
    \cs_if_exist_use:c { c_@@ _ \int_use:N \g_@@_env_int _ tl }
    \bool_if:NF \l_@@_resume_bool { \int_gzero:N \g_@@_visual_line_int }
    \dim_gzero:N \g_@@_tmp_width_dim
    \int_gzero:N \g_@@_line_int
    \dim_zero:N \parindent 
    \dim_zero:N \lineskip 
    \cs_set_eq:NN \label \@@_label:n
  }
%    \end{macrocode}
% 
%
% \bigskip
% If the final user has used both |left-margin=auto| and |line-numbers|, we have
% to compute the width of the maximal number of lines at the end of the
% environment to fix the correct value to |left-margin|. The first argument of
% the following function is the name of the Lua function that will be applied to
% the second argument in order to count the number of lines.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_compute_left_margin:nn #1 #2
  {
    \bool_lazy_and:nnT \l_@@_left_margin_auto_bool \l_@@_line_numbers_bool
       {
        \hbox_set:Nn \l_tmpa_box
          {
            \footnotesize
            \bool_if:NTF \l_@@_skip_empty_lines_bool
              {
                \lua_now:n 
                  { piton.#1(token.scan_argument()) }
                  { #2 }
                \int_to_arabic:n 
                  { \g_@@_visual_line_int + \l_@@_nb_non_empty_lines_int }   
               }
              {
                \int_to_arabic:n 
                  { \g_@@_visual_line_int + \l_@@_nb_lines_int }  
              }
           }
         \dim_set:Nn \l_@@_left_margin_dim 
           { \box_wd:N \l_tmpa_box + \l_@@_numbers_sep_dim + 0.1 em }
       }
  }
\cs_generate_variant:Nn \@@_compute_left_margin:nn { n o }
%    \end{macrocode}
% 
%
%
% \bigskip
% Whereas |\l_@@_with_dim| is the width of the environment,
% |\l_@@_line_width_dim| is the width of the lines of code without the
% potential margins for the numbers of lines and the background. Depending on
% the case, you have to compute |\l_@@_line_width_dim| from |\l_@@_width_dim| or
% we have to do the opposite.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_compute_width:
  {
    \dim_compare:nNnTF \l_@@_line_width_dim = \c_zero_dim
      {
        \dim_set_eq:NN \l_@@_line_width_dim \l_@@_width_dim
        \clist_if_empty:NTF \l_@@_bg_color_clist
%    \end{macrocode}
% If there is no background, we only subtract the left margin. 
%    \begin{macrocode}
          { \dim_sub:Nn \l_@@_line_width_dim \l_@@_left_margin_dim }
%    \end{macrocode}
% If there is a background, we subtract 0.5~em for the margin on the right.
%    \begin{macrocode}
          { 
            \dim_sub:Nn \l_@@_line_width_dim { 0.5 em }
%    \end{macrocode}
% And we subtract also for the left margin. If the key |left-margin| has been
% used (with a numerical value or with the special value~|min|),
% |\l_@@_left_margin_dim| has a non-zero value\footnote{If the key
% \texttt{left-margin} has been used with the special value \texttt{min}, the
% actual value of \texttt{\textbackslash l_\@\@_left_margin_dim} has yet been
% computed when we use the current command.} and we use that value. Elsewhere,
% we use a value of 0.5~em.
%    \begin{macrocode}
            \dim_compare:nNnTF \l_@@_left_margin_dim = \c_zero_dim 
              { \dim_sub:Nn \l_@@_line_width_dim { 0.5 em } }
              { \dim_sub:Nn \l_@@_line_width_dim \l_@@_left_margin_dim }
          }
      }
%    \end{macrocode}
% If |\l_@@_line_width_dim| has yet a non-zero value, that means that it has
% been read in the |aux| file: it has been written by a previous run because the
% key |width| is used with the special value~|min|). We compute now the width of
% the environment by computations opposite to the preceding ones.
%    \begin{macrocode}
      {
        \dim_set_eq:NN \l_@@_width_dim \l_@@_line_width_dim
        \clist_if_empty:NTF \l_@@_bg_color_clist
          { \dim_add:Nn \l_@@_width_dim \l_@@_left_margin_dim }
          { 
            \dim_add:Nn \l_@@_width_dim { 0.5 em }
            \dim_compare:nNnTF \l_@@_left_margin_dim = \c_zero_dim 
              { \dim_add:Nn \l_@@_width_dim { 0.5 em } }
              { \dim_add:Nn \l_@@_width_dim \l_@@_left_margin_dim }
          }
      }
  }
%    \end{macrocode}
% 
%
% 
% \bigskip 
%    \begin{macrocode}
\NewDocumentCommand { \NewPitonEnvironment } { m m m m }
  { 
%    \end{macrocode}
% We construct a TeX macro which will catch as argument all the tokens until
% |\end{|\texttt{\textsl{name_env}}|}| with, in that
% |\end{|\texttt{\textsl{name_env}}|}|, the catcodes of |\|, |{| 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 { _@@_collect_ #1 :w } 
          ####1 
          \c_backslash_str end \c_left_brace_str #1 \c_right_brace_str
      }
         { 
            \group_end:
            \mode_if_vertical:TF \mode_leave_vertical: \newline 
%    \end{macrocode}
% We count with Lua the number of lines of the argument. The result will be
% stored by Lua in |\l_@@_nb_lines_int|. That information will be used to allow
% or disallow page breaks.
%    \begin{macrocode}
            \lua_now:n { piton.CountLines(token.scan_argument()) } { ##1 }  
%    \end{macrocode}
% The first argument of the following function is the name of the Lua function
% that will be applied to the second argument in order to count the number of lines.
%    \begin{macrocode}
            \@@_compute_left_margin:nn { CountNonEmptyLines } { ##1 }
            \@@_compute_width:
            \ttfamily
            \dim_zero:N \parskip 
%    \end{macrocode}
% |\g_@@_footnote_bool| is raised when the package \pkg{piton} has been loaded
% with the key |footnote| \emph{or} the key |footnotehyper|.
%    \begin{macrocode}
            \bool_if:NT \g_@@_footnote_bool { \begin { savenotes } } 
%    \end{macrocode}
% 
% Now, the key |write|.
%    \begin{macrocode}
            \str_if_empty:NTF \l_@@_path_write_str
              { \lua_now:e { piton.write = "\l_@@_write_str" } }
              { 
                \lua_now:e 
                  { piton.write = "\l_@@_path_write_str / \l_@@_write_str" } 
              } 
            \str_if_empty:NF \l_@@_write_str
              { 
                \seq_if_in:NVTF \g_@@_write_seq \l_@@_write_str 
                  { \lua_now:n { piton.write_mode = "a" } }
                  { 
                    \lua_now:n { piton.write_mode = "w" } 
                    \seq_gput_left:NV \g_@@_write_seq \l_@@_write_str
                  }
              }  
            \vbox \bgroup 
            \lua_now:e 
              { 
                piton.GobbleParse
                  ( 
                    '\l_piton_language_str' , 
                    \int_use:N \l_@@_gobble_int , 
                    token.scan_argument() 
                  ) 
              } 
              { ##1 }
            \vspace { 2.5 pt } 
            \egroup
            \bool_if:NT \g_@@_footnote_bool { \end { savenotes } } 
%    \end{macrocode}
% If the user has used the key |width| with the special value~|min|, we write on
% the |aux| file the value of |\l_@@_line_width_dim| (largest width of the lines
% of code of the environment).
%    \begin{macrocode}
            \bool_if:NT \l_@@_width_min_bool \@@_width_to_aux:
%    \end{macrocode}
% The following |\end{#1}| is only for the stack of environments of LaTeX.
%    \begin{macrocode}
            \end { #1 }
            \@@_write_aux:
          }   
%    \end{macrocode}
% 
% 
% \bigskip
% We can now define the new environment.
%
% We are still in the definition of the command |\NewPitonEnvironment|...
%    \begin{macrocode}
    \NewDocumentEnvironment { #1 } { #2 } 
      {
        \cs_set_eq:NN \PitonOptions \@@_fake_PitonOptions
        #3 
        \@@_pre_env:
        \int_compare:nNnT \l_@@_number_lines_start_int > \c_zero_int
          { \int_gset:Nn \g_@@_visual_line_int { \l_@@_number_lines_start_int - 1 } }
        \group_begin:
        \tl_map_function:nN 
          { \ \\ \{ \} \$ \& \# \^ \_ \% \~ \^^I } 
          \char_set_catcode_other:N 
        \use:c { _@@_collect_ #1 :w }
      }
      { #4 } 
%    \end{macrocode}
%
% \medskip
% The following code is for technical reasons. We want to change the catcode of
% |^^M| before catching the arguments of the new environment we are defining.
% Indeed, if not, we will have problems if there is a final optional argument in
% our environment (if that final argument is not used by the user in an
% instance of the environment, a spurious space is inserted, probably because
% the |^^M| is converted to space).
%    \begin{macrocode}
    \AddToHook { env / #1 / begin } { \char_set_catcode_other:N \^^M }
  }
%    \end{macrocode}
% This is the end of the definition of the command |\NewPitonEnvironment|.
%
% \bigskip
% Now, we define the environment |{Piton}|, which is the main environment
% provided by the package \pkg{piton}. Of course, you use
% |\NewPitonEnvironment|. 
%    \begin{macrocode}
\bool_if:NTF \g_@@_beamer_bool
  {
    \NewPitonEnvironment { Piton } { d < > O { } }
      { 
        \keys_set:nn { PitonOptions } { #2 } 
        \IfValueTF { #1 }
          { \begin { uncoverenv } < #1 > }
          { \begin { uncoverenv } }
      }
      { \end { uncoverenv } } 
  }
  { 
    \NewPitonEnvironment { Piton } { O { } } 
      { \keys_set:nn { PitonOptions } { #1 } } 
      { } 
  }
%    \end{macrocode}
%
%
% \bigskip
% The code of the command |\PitonInputFile| is somewhat similar to the code of
% the environment |{Piton}|. In fact, it's simpler because there isn't the
% problem of catching the content of the environment in a verbatim mode.
%    \begin{macrocode}
\NewDocumentCommand { \PitonInputFile } { d < > O { } m }
  {
    \group_begin:
    \tl_if_empty:NTF \l_@@_path_str
      { \str_set:Nn \l_@@_file_name_str { #3 } } 
      { 
        \str_set_eq:NN \l_@@_file_name_str \l_@@_path_str 
        \str_put_right:Nn \l_@@_file_name_str { / #3 }
      }
    \file_if_exist:nTF { \l_@@_file_name_str }
      { \@@_input_file:nn { #1 } { #2 } }
      { \msg_error:nnn { piton } { Unknown~file } { #3 } } 
    \group_end:
  }
%    \end{macrocode}
%
% The following command uses as implicit argument the name of the file in |\l_@@_file_name_str|.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_input_file:nn #1 #2 
  {
%    \end{macrocode}
% We recall that, if we are in Beamer, the command |\PitonInputFile| is
% ``overlay-aware'' and that's why there is an optional argument between angular
% brackets (|<| and |>|).
%    \begin{macrocode}
    \tl_if_novalue:nF { #1 }
      {
        \bool_if:NTF \g_@@_beamer_bool
          { \begin { uncoverenv } < #1 > }     
          { \@@_error:n { overlay~without~beamer } }
      }
    \group_begin:
      \int_zero_new:N \l_@@_first_line_int
      \int_zero_new:N \l_@@_last_line_int 
      \int_set_eq:NN \l_@@_last_line_int \c_max_int
      \bool_set_true:N \l_@@_in_PitonInputFile_bool
      \keys_set:nn { PitonOptions } { #2 }
      \bool_if:NT \l_@@_line_numbers_absolute_bool
        { \bool_set_false:N \l_@@_skip_empty_lines_bool }
      \bool_if:nTF
        {
          ( 
            \int_compare_p:nNn \l_@@_first_line_int > \c_zero_int
            || \int_compare_p:nNn \l_@@_last_line_int < \c_max_int 
          )
          && ! \str_if_empty_p:N \l_@@_begin_range_str
        }
        { 
          \@@_error:n { bad~range~specification } 
          \int_zero:N \l_@@_first_line_int
          \int_set_eq:NN \l_@@_last_line_int \c_max_int
        }
        { 
          \str_if_empty:NF \l_@@_begin_range_str 
            { 
              \@@_compute_range: 
              \bool_lazy_or:nnT 
                \l_@@_marker_include_lines_bool
                { ! \str_if_eq_p:NN \l_@@_begin_range_str \l_@@_end_range_str } 
                {
                  \int_decr:N \l_@@_first_line_int
                  \int_incr:N \l_@@_last_line_int
                }
            }
        }
      \@@_pre_env:
      \bool_if:NT \l_@@_line_numbers_absolute_bool
        { \int_gset:Nn \g_@@_visual_line_int { \l_@@_first_line_int - 1 } } 
      \int_compare:nNnT \l_@@_number_lines_start_int > \c_zero_int 
        { 
          \int_gset:Nn \g_@@_visual_line_int 
            { \l_@@_number_lines_start_int - 1 } 
        }
%    \end{macrocode}
% The following case arise when the code |line-numbers/absolute| is in force
% without the use of a marked range.
%    \begin{macrocode}
      \int_compare:nNnT \g_@@_visual_line_int < \c_zero_int 
        { \int_gzero:N \g_@@_visual_line_int }
      \mode_if_vertical:TF \mode_leave_vertical: \newline 
%    \end{macrocode}
% We count with Lua the number of lines of the argument. The result will be
% stored by Lua in |\l_@@_nb_lines_int|. That information will be used to allow
% or disallow page breaks.
%    \begin{macrocode}
      \lua_now:e { piton.CountLinesFile('\l_@@_file_name_str') } 
%    \end{macrocode}
% The first argument of the following function is the name of the Lua function
% that will be applied to the second argument in order to count the number of lines.
%    \begin{macrocode}
      \@@_compute_left_margin:no { CountNonEmptyLinesFile } \l_@@_file_name_str
      \@@_compute_width:
      \ttfamily
      \bool_if:NT \g_@@_footnote_bool { \begin { savenotes } } 
      \vtop \bgroup 
      \lua_now:e
        { 
          piton.ParseFile(
           '\l_piton_language_str' ,
           '\l_@@_file_name_str' ,
           \int_use:N \l_@@_first_line_int , 
           \int_use:N \l_@@_last_line_int ) 
        } 
      \egroup 
      \bool_if:NT \g_@@_footnote_bool { \end { savenotes } } 
      \bool_if:NT \l_@@_width_min_bool \@@_width_to_aux:
    \group_end:
%    \end{macrocode}
% We recall that, if we are in Beamer, the command |\PitonInputFile| is
% ``overlay-aware'' and that's why we close now an environment |{uncoverenv}|
% that we have opened at the beginning of the command.
%    \begin{macrocode}
    \tl_if_novalue:nF { #1 }
      { \bool_if:NT \g_@@_beamer_bool { \end { uncoverenv } } }
    \@@_write_aux:
  }
%    \end{macrocode}
%
% 
% \bigskip
% The following command computes the values of |\l_@@_first_line_int| and
% |\l_@@_last_line_int| when |\PitonInputFile| is used with textual markers. 
%    \begin{macrocode}
\cs_new_protected:Npn \@@_compute_range: 
  {
%    \end{macrocode}
% We store the markers in L3 strings (|str|) in order to do safely the following
% replacement of |\#|.
%    \begin{macrocode}
    \str_set:Nx \l_tmpa_str { \@@_marker_beginning:n \l_@@_begin_range_str }
    \str_set:Nx \l_tmpb_str { \@@_marker_end:n \l_@@_end_range_str }
%    \end{macrocode}
% We replace the sequences |\#| which may be present in the prefixes (and, more
% unlikely, suffixes) added to the markers by the functions
% |\@@_marker_beginning:n| and |\@@_marker_end:n|
%    \begin{macrocode}
    \exp_args:NnV \regex_replace_all:nnN { \\\# } \c_hash_str \l_tmpa_str
    \exp_args:NnV \regex_replace_all:nnN { \\\# } \c_hash_str \l_tmpb_str
    \lua_now:e
      { 
        piton.ComputeRange
          ( '\l_tmpa_str' , '\l_tmpb_str' , '\l_@@_file_name_str' ) 
      } 
  }
%    \end{macrocode}
% 
% \bigskip
% \subsubsection{The styles}
% 
% \medskip
% The following command is fundamental: it will be used by the Lua code.
%    \begin{macrocode}
\NewDocumentCommand { \PitonStyle } { m } 
  { 
    \cs_if_exist_use:cF { pitonStyle _ \l_piton_language_str  _ #1 }
      { \use:c { pitonStyle _ #1 } }
  }
%    \end{macrocode}
%
% \medskip
%    \begin{macrocode}
\NewDocumentCommand { \SetPitonStyle } { O { } m } 
  { 
    \str_clear_new:N \l_@@_SetPitonStyle_option_str
    \str_set:Nx \l_@@_SetPitonStyle_option_str { \str_lowercase:n { #1 } }
    \str_if_eq:onT \l_@@_SetPitonStyle_option_str { current-language }
      { \str_set_eq:NN \l_@@_SetPitonStyle_option_str \l_piton_language_str }
    \keys_set:nn { piton / Styles } { #2 } 
  } 
%    \end{macrocode}
% 
% \medskip
%    \begin{macrocode}
\cs_new_protected:Npn \@@_math_scantokens:n #1 
  { \normalfont \scantextokens { \begin{math} #1 \end{math} } }
%    \end{macrocode}
% 
% \medskip
%    \begin{macrocode}
\clist_new:N \g_@@_styles_clist
\clist_gset:Nn \g_@@_styles_clist 
  {
    Comment ,
    Comment.LaTeX ,
    Exception ,
    FormattingType ,    
    Identifier ,
    InitialValues ,
    Interpol.Inside ,
    Keyword ,
    Keyword.Constant ,
    Name.Builtin ,      
    Name.Class ,
    Name.Constructor ,
    Name.Decorator ,
    Name.Field ,
    Name.Function ,
    Name.Module ,
    Name.Namespace ,
    Name.Table , 
    Name.Type ,
    Number ,
    Operator ,
    Operator.Word ,
    Preproc ,
    Prompt ,
    String.Doc ,
    String.Interpol ,
    String.Long ,
    String.Short ,     
    TypeParameter ,    
    UserFunction 
  }  

\clist_map_inline:Nn \g_@@_styles_clist  
  {
    \keys_define:nn { piton / Styles }
      {
        #1 .value_required:n = true ,
        #1 .code:n = 
         \tl_set:cn 
           {
             pitonStyle _
             \str_if_empty:NF \l_@@_SetPitonStyle_option_str 
               { \l_@@_SetPitonStyle_option_str _ }
             #1
           }
           { ##1 }
      }
  }

\keys_define:nn { piton / Styles }
  {
    String          .meta:n = { String.Long = #1 , String.Short = #1 } ,
    Comment.Math    .tl_set:c = pitonStyle _ Comment.Math  ,
    ParseAgain      .tl_set:c = pitonStyle _ ParseAgain , 
    ParseAgain      .value_required:n = true ,
    ParseAgain.noCR .tl_set:c = pitonStyle _ ParseAgain.noCR , 
    ParseAgain.noCR .value_required:n = true ,
    unknown         .code:n = 
      \@@_error:n { Unknown~key~for~SetPitonStyle }
  }
%    \end{macrocode}
%
% \bigskip
% We add the word |String| to the list of the styles because we will use that
% list in the error message for an unknown key in |\SetPitonStyle|.
%
%    \begin{macrocode}
\clist_gput_left:Nn \g_@@_styles_clist { String }
%    \end{macrocode}
%
% \bigskip
% Of course, we sort that clist.
%    \begin{macrocode}
\clist_gsort:Nn \g_@@_styles_clist
  { 
    \str_compare:nNnTF { #1 } < { #2 } 
      \sort_return_same:    
      \sort_return_swapped:  
  } 
%    \end{macrocode}
% 
%
% \bigskip
% \subsubsection{The initial styles}
%
% The initial styles are inspired by the style ``manni'' of Pygments.
% 
% \medskip
%    \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} , 
    Name.Constructor   = \color[HTML]{006000} \bfseries , 
    Name.Field         = \color[HTML]{AA6600} , 
    Name.Module        = \color[HTML]{0060A0} \bfseries ,
    Name.Table         = \color[HTML]{309030} ,
    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:n ,
    Interpol.Inside    = \color{black}\@@_piton:n ,
    TypeParameter      = \color[HTML]{336666} \itshape ,
    Preproc            = \color[HTML]{AA6600} \slshape ,
    Identifier         = \@@_identifier:n , 
    UserFunction       = , 
    Prompt             = , 
    ParseAgain.noCR    = \@@_piton_no_cr:n , 
    ParseAgain         = \@@_piton:n ,
  }
%    \end{macrocode}
% The last styles |ParseAgain.noCR| and |ParseAgain| should be considered as 
% ``internal style'' (not available for the final user). However, maybe we will
% change that and document these styles for the final user (why not?).
%
% \medskip
% If the key |math-comments| has been used at load-time, we change the style
% |Comment.Math| which should be considered only at an ``internal style''.
% However, maybe we will document in a future version the possibility to write
% change the style \emph{locally} in a document)].
%    \begin{macrocode}
\AtBeginDocument 
  { 
    \bool_if:NT \g_@@_math_comments_bool 
       { \SetPitonStyle { Comment.Math = \@@_math_scantokens:n } } 
  }
%    \end{macrocode}
% 
% \bigskip
%
% \bigskip
% \subsubsection{Highlighting some identifiers}
%
%
% \medskip
%    \begin{macrocode}
\NewDocumentCommand { \SetPitonIdentifier } { o m m } 
  { 
    \clist_set:Nn \l_tmpa_clist { #2 }
    \IfNoValueTF { #1 }
      { 
        \clist_map_inline:Nn \l_tmpa_clist 
          { \cs_set:cpn { pitonIdentifier _ ##1 } { #3 } }
      }
      {
        \str_set:Nx \l_tmpa_str { \str_lowercase:n { #1 } }
        \str_if_eq:onT \l_tmpa_str { current-language }
          { \str_set_eq:NN \l_tmpa_str \l_piton_language_str }
        \clist_map_inline:Nn \l_tmpa_clist 
          { \cs_set:cpn { pitonIdentifier _ \l_tmpa_str _ ##1 } { #3 } }
      }
  } 
%    \end{macrocode}
% 
%    \begin{macrocode}
\cs_new_protected:Npn \@@_identifier:n #1
  { 
    \cs_if_exist_use:cF { pitonIdentifier _ \l_piton_language_str _ #1 } 
      { \cs_if_exist_use:c { pitonIdentifier_ #1 } }
    { #1 } 
  } 
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\keys_define:nn { PitonOptions }
  { identifiers .code:n = \@@_set_identifiers:n { #1 } }
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\keys_define:nn { Piton / identifiers }
  {
    names .clist_set:N = \l_@@_identifiers_names_tl ,
    style .tl_set:N    = \l_@@_style_tl ,
  }
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_identifiers:n #1
  {
    \@@_error:n { key~identifiers~deprecated }
    \@@_gredirect_none:n { key~identifiers~deprecated }
    \clist_clear_new:N \l_@@_identifiers_names_tl 
    \tl_clear_new:N \l_@@_style_tl 
    \keys_set:nn { Piton / identifiers } { #1 }
    \clist_map_inline:Nn \l_@@_identifiers_names_tl 
      {
        \tl_set_eq:cN 
          { PitonIdentifier _ \l_piton_language_str _ ##1 }
          \l_@@_style_tl
      }
  }
%    \end{macrocode}
%
%
% \bigskip
% In particular, we have an highlighting of the indentifiers which are the
% names of Python functions previously defined by the user. Indeed, when a
% Python function is defined, the style |Name.Function.Internal| is applied to
% that name. We define now that style (you define it directly and you short-cut
% the function |\SetPitonStyle|). 
%    \begin{macrocode}
\cs_new_protected:cpn { pitonStyle _ Name.Function.Internal } #1
  { 
%    \end{macrocode}
% First, the element is composed in the TeX flow with the style |Name.Function|
% which is provided to the final user.
%    \begin{macrocode}
    { \PitonStyle { Name.Function } { #1 } }
%    \end{macrocode}
% Now, we specify that the name of the new Python function is a known identifier
% that will be formated with the Piton style |UserFunction|. Of course,
% here the affectation is global because we have to exit many groups and even
% the environments |{Piton}|).
%    \begin{macrocode}
    \cs_gset_protected:cpn { PitonIdentifier _ \l_piton_language_str _ #1 } 
      { \PitonStyle { UserFunction } }
%    \end{macrocode}
% Now, we put the name of that new user function in the dedicated sequence
% (specific of the current language). {\bfseries That sequence will be used only
% by |\PitonClearUserFunctions|}.
%    \begin{macrocode}
    \seq_if_exist:cF { g_@@_functions _ \l_piton_language_str _ seq }
      { \seq_new:c { g_@@_functions _ \l_piton_language_str _ seq } }
    \seq_gput_right:cn { g_@@_functions _ \l_piton_language_str _ seq } { #1 }
%    \end{macrocode}
% We update |\g_@@_languages_seq| which is used only by the command
% |\PitonClearUserFunctions| when it's used without its optional argument.
%    \begin{macrocode}
    \seq_if_in:NVF \g_@@_languages_seq \l_piton_language_str 
      { \seq_gput_left:NV \g_@@_languages_seq \l_piton_language_str }
  }
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\NewDocumentCommand \PitonClearUserFunctions { ! o } 
  { 
    \tl_if_novalue:nTF { #1 }
%    \end{macrocode}
% If the command is used without its optional argument, we will deleted the
% user language for all the informatic languages.
%    \begin{macrocode}
      { \@@_clear_all_functions: }
      { \@@_clear_list_functions:n { #1 } }
  }
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\cs_new_protected:Npn \@@_clear_list_functions:n #1
  {
    \clist_set:Nn \l_tmpa_clist { #1 }
    \clist_map_function:NN \l_tmpa_clist \@@_clear_functions_i:n 
    \clist_map_inline:nn { #1 }
      { \seq_gremove_all:Nn \g_@@_languages_seq { ##1 } }
  }
%    \end{macrocode}
% 
% \bigskip
%    \begin{macrocode}
\cs_new_protected:Npn \@@_clear_functions_i:n #1
  { \exp_args:Ne \@@_clear_functions_ii:n { \str_lowercase:n { #1 } } }
%    \end{macrocode}
% 
% The following command clears the list of the user-defined functions for the
% language provided in argument (mandatory in lower case). 
%    \begin{macrocode}
\cs_new_protected:Npn \@@_clear_functions_ii:n #1 
  {
    \seq_if_exist:cT { g_@@_functions _ #1 _ seq }
      {
        \seq_map_inline:cn { g_@@_functions _ #1 _ seq }
          { \cs_undefine:c { PitonIdentifier _ #1 _ ##1} }
        \seq_gclear:c { g_@@_functions _ #1 _ seq }
      }
  }
%    \end{macrocode}
%  
% \bigskip
%    \begin{macrocode}
\cs_new_protected:Npn \@@_clear_functions:n #1 
  {
    \@@_clear_functions_i:n { #1 }
    \seq_gremove_all:Nn \g_@@_languages_seq { #1 }
  }
%    \end{macrocode}
% 
% \bigskip
% The following command clears all the user-defined functions for all the
% informatic languages.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_clear_all_functions:
  { 
    \seq_map_function:NN \g_@@_languages_seq \@@_clear_functions_i:n 
    \seq_gclear:N \g_@@_languages_seq
  }
%    \end{macrocode}
% 
% \bigskip
% \subsubsection{Security}
%
%     \begin{macrocode}
\AddToHook { env / piton / begin } 
  { \msg_fatal:nn { piton } { No~environment~piton } }

\msg_new:nnn { piton } { No~environment~piton }
  { 
    There~is~no~environment~piton!\\
    There~is~an~environment~{Piton}~and~a~command~
    \token_to_str:N \piton\ but~there~is~no~environment~
    {piton}.~This~error~is~fatal.
  }
%    \end{macrocode}
% 
% \bigskip
% \subsubsection{The error messages of the package}
% 
%    \begin{macrocode}
\@@_msg_new:nn { key~identifiers~deprecated }
  {
    The~key~'identifiers'~in~the~command~\token_to_str:N PitonOptions\ 
    is~now~deprecated:~you~should~use~the~command~
    \token_to_str:N \SetPitonIdentifier\ instead.\\
    However,~you~can~go~on.
  }
%    \end{macrocode}
% 
%    \begin{macrocode}
\@@_msg_new:nn { Unknown~key~for~SetPitonStyle } 
  {
    The~style~'\l_keys_key_str'~is~unknown.\\
    This~key~will~be~ignored.\\
    The~available~styles~are~(in~alphabetic~order):~
    \clist_use:Nnnn \g_@@_styles_clist { ~and~ } { ,~ } { ~and~ }.
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_msg_new:nn { Invalid~key }
  {
    Wrong~use~of~key.\\
    You~can't~use~the~key~'\l_keys_key_str'~here.\\
    That~key~will~be~ignored.
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_msg_new:nn { Unknown~key~for~line-numbers } 
  { 
    Unknown~key. \\
    The~key~'line-numbers / \l_keys_key_str'~is~unknown.\\
    The~available~keys~of~the~family~'line-numbers'~are~(in~
    alphabetic~order):~
    absolute,~false,~label-empty-lines,~resume,~skip-empty-lines,~
    sep,~start~and~true.\\
    That~key~will~be~ignored.
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\@@_msg_new:nn { Unknown~key~for~marker } 
  { 
    Unknown~key. \\
    The~key~'marker / \l_keys_key_str'~is~unknown.\\
    The~available~keys~of~the~family~'marker'~are~(in~
    alphabetic~order):~ beginning,~end~and~include-lines.\\
    That~key~will~be~ignored.
  }
%    \end{macrocode}
% 
%    \begin{macrocode}
\@@_msg_new:nn { bad~range~specification } 
  {
    Incompatible~keys.\\
    You~can't~specify~the~range~of~lines~to~include~by~using~both~
    markers~and~explicit~number~of~lines.\\
    Your~whole~file~'\l_@@_file_name_str'~will~be~included.
  }
%    \end{macrocode}
% 
%   \begin{macrocode}
\@@_msg_new:nn { syntax~error }
  {
    Your~code~of~the~language~"\l_piton_language_str"~is~not~syntactically~correct.\\ 
    It~won't~be~printed~in~the~PDF~file.
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\NewDocumentCommand \PitonSyntaxError { }
  { \@@_error:n { syntax~error } }
%    \end{macrocode}
%
%
%    \begin{macrocode}
\@@_msg_new:nn { begin~marker~not~found }
  {
    Marker~not~found.\\
    The~range~'\l_@@_begin_range_str'~provided~to~the~  
    command~\token_to_str:N \PitonInputFile\ has~not~been~found.~
    The~whole~file~'\l_@@_file_name_str'~will~be~inserted.
  }
%    \end{macrocode}
%
% 
%    \begin{macrocode}
\@@_msg_new:nn { end~marker~not~found }
  {
    Marker~not~found.\\
    The~marker~of~end~of~the~range~'\l_@@_end_range_str'~
    provided~to~the~command~\token_to_str:N \PitonInputFile\ 
    has~not~been~found.~The~file~'\l_@@_file_name_str'~will~
    be~inserted~till~the~end.
  }
%    \end{macrocode}
% 
%
%    \begin{macrocode}
\NewDocumentCommand \PitonBeginMarkerNotFound { } 
  { \@@_error:n { begin~marker~not~found } }
\NewDocumentCommand \PitonEndMarkerNotFound { } 
  { \@@_error:n { end~marker~not~found } }
%    \end{macrocode}
% 
%    \begin{macrocode}
\@@_msg_new:nn { Unknown~file }
  {
    Unknown~file. \\
    The~file~'#1'~is~unknown.\\
    Your~command~\token_to_str:N \PitonInputFile\ will~be~discarded.
  }
%    \end{macrocode}
% 
%    \begin{macrocode}
\msg_new:nnnn { piton } { Unknown~key~for~PitonOptions }
  { 
    Unknown~key. \\
    The~key~'\l_keys_key_str'~is~unknown~for~\token_to_str:N \PitonOptions.~
    It~will~be~ignored.\\
    For~a~list~of~the~available~keys,~type~H~<return>.
  }
  {
    The~available~keys~are~(in~alphabetic~order):~
    auto-gobble,~
    background-color,~
    break-lines,~
    break-lines-in-piton,~
    break-lines-in-Piton,~
    continuation-symbol,~ 
    continuation-symbol-on-indentation,~
    detected-commands,~
    end-of-broken-line,~
    end-range,~
    env-gobble,~
    gobble,~
    indent-broken-lines,~
    language,~
    left-margin,~
    line-numbers/,~
    marker/,~
    math-comments,~
    path,~
    path-write,~
    prompt-background-color,~
    resume,~
    show-spaces,~
    show-spaces-in-strings,~
    splittable,~
    tabs-auto-gobble,~
    tab-size,~
    width~and~write.
  }
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\@@_msg_new:nn { label~with~lines~numbers } 
  {
    You~can't~use~the~command~\token_to_str:N \label\
    because~the~key~'line-numbers'~is~not~active.\\
    If~you~go~on,~that~command~will~ignored.
  }
%    \end{macrocode}
% 
% \bigskip
%    \begin{macrocode}
\@@_msg_new:nn { cr~not~allowed }
  {
    You~can't~put~any~carriage~return~in~the~argument~
    of~a~command~\c_backslash_str
    \l_@@_beamer_command_str\ within~an~
    environment~of~'piton'.~You~should~consider~using~the~
    corresponding~environment.\\
    That~error~is~fatal.
  }
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
\@@_msg_new:nn { overlay~without~beamer }
  {
    You~can't~use~an~argument~<...>~for~your~command~
    \token_to_str:N \PitonInputFile\ because~you~are~not~
    in~Beamer.\\
    If~you~go~on,~that~argument~will~be~ignored.
  }
%    \end{macrocode}
%
%
% \bigskip
% \subsubsection{We load piton.lua}
%
% \bigskip
%    \begin{macrocode}
\hook_gput_code:nnn { begindocument } { . }
  { \lua_now:e { require("piton.lua") } }
%    \end{macrocode}
% 
% \bigskip
% \subsubsection{Detected commands}
%
% 
%    \begin{macrocode}
\ExplSyntaxOff
\begin{luacode*}
    lpeg.locale(lpeg)
    local P , alpha , C , space , S , V
      = lpeg.P , lpeg.alpha , lpeg.C , lpeg.space , lpeg.S , lpeg.V
    local function add(...)
          local s = P ( false ) 
          for _ , x in ipairs({...}) do s = s + x end  
          return s 
          end
    local my_lpeg = 
      P {  "E" ,
           E = ( V "F" * ( P "," * V "F" ) ^ 0 ) / add ,
           F = space ^ 0 * ( alpha ^ 1 ) / "\\%0" * space ^ 0 
        }
    function piton.addListCommands( key_value )
      piton.ListCommands = piton.ListCommands + my_lpeg : match ( key_value ) 
    end
\end{luacode*}
%</STY>
%    \end{macrocode}
% 
% 
% \bigskip
% \subsection{The Lua part of the implementation}
%
% \bigskip
% The Lua code will be loaded via a |{luacode*}| environment. The environment
% is by itself a Lua block and the local declarations will be local to that
% block. All the global functions (used by the L3 parts of the implementation)
% will be put in a Lua table |piton|.
%
% 
%    \begin{macrocode}
%<*LUA>
if piton.comment_latex == nil then piton.comment_latex = ">" end 
piton.comment_latex = "#" .. piton.comment_latex 
%    \end{macrocode}
%
%
% \bigskip
% The following functions are an easy way to safely insert braces (|{| and |}|)
% in the TeX flow.
%    \begin{macrocode}
function piton.open_brace () 
   tex.sprint("{") 
end 
function piton.close_brace () 
   tex.sprint("}") 
end 
%    \end{macrocode}
%
% \bigskip
% \subsubsection{Special functions dealing with LPEG}
%
% \medskip
% We will use the Lua library \pkg{lpeg} which is built in LuaTeX. That's why we
% define first aliases for several functions of that library.
%    \begin{macrocode}
local P, S, V, C, Ct, Cc = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc
local Cs , Cg , Cmt , Cb = lpeg.Cs, lpeg.Cg , lpeg.Cmt , lpeg.Cb
local R = lpeg.R
%    \end{macrocode}
%
% 
%
% \bigskip
% The function |Q| takes in as argument a pattern and returns a \textsc{lpeg}
% \emph{which does a capture} of the pattern. That capture will be sent to LaTeX
% with the catcode ``other'' for all the characters: it's suitable for elements
% of the Python listings that \pkg{piton} will typeset verbatim (thanks to the
% catcode ``other''). 
%    \begin{macrocode}
local function Q(pattern)
  return Ct ( Cc ( luatexbase.catcodetables.CatcodeTableOther ) * C ( pattern ) )
end 
%    \end{macrocode}
%
%
% \bigskip
% The function |L| takes in as argument a pattern and returns a \textsc{lpeg}
% \emph{which does a capture} of the pattern. That capture will be sent to LaTeX
% with standard LaTeX catcodes for all the characters: the elements captured
% will be formatted as normal LaTeX codes. It's suitable for the ``LaTeX
% comments'' in the environments |{Piton}| and the elements beetween 
% |begin-escape| and |end-escape|. That function won't be much used.
%    \begin{macrocode}
local function L(pattern)
  return Ct ( C ( pattern ) ) 
end
%    \end{macrocode}
%
% \bigskip
% The function |Lc| (the c is for \emph{constant}) takes in as argument a string
% and returns a \textsc{lpeg} \emph{with does a constant capture} which returns
% that string. The elements captured will be formatted as L3 code. It will be
% used to send to LaTeX all the formatting LaTeX instructions we have to insert
% in order to do the syntactic highlighting (that's the main job of
% \pkg{piton}). That function will be widely used.
%    \begin{macrocode}
local function Lc(string)
  return Cc ( { luatexbase.catcodetables.expl , string } ) 
end 
%    \end{macrocode}
% 
% \bigskip
% The function |K| creates a \textsc{lpeg} which will return as capture the
% whole LaTeX code corresponding to a Python chunk (that is to say with the
% LaTeX formatting instructions corresponding to the syntactic nature of that
% Python chunk). The first argument is a Lua string corresponding to the name of
% a \pkg{piton} style and the second element is a pattern (that is to say a
% \textsc{lpeg} without capture)
%    \begin{macrocode}
local function K(style, pattern)
  return
     Lc ( "{\\PitonStyle{" .. style .. "}{" )
     * Q ( pattern )
     * Lc ( "}}" )
end
%    \end{macrocode}
% The formatting commands in a given \pkg{piton} style (eg. the style |Keyword|)
% may be semi-global declarations (such as |\bfseries| or |\slshape|) or LaTeX
% macros with an argument (such as |\fbox| or |\colorbox{yellow}|). In order to
% deal with both syntaxes, we have used two pairs of braces: 
% |{\PitonStyle{Keyword}{|\texttt{\slshape text to format}|}}|.
% 
%
% \bigskip
% The following function |WithStyle| is similar to the function |K| but should
% be used for multi-lines elements. 
%    \begin{macrocode}
local function WithStyle(style,pattern)
  return 
       Ct ( Cc "Open" * Cc ( "{\\PitonStyle{" .. style .. "}{" ) * Cc "}}" ) 
     * pattern 
     * Ct ( Cc "Close" ) 
end
%    \end{macrocode}
% 
% \bigskip
% The following \textsc{lpeg} catches the Python chunks which are in LaTeX
% escapes (and that chunks will be considered as normal LaTeX constructions).
%    \begin{macrocode}
Escape = P ( false ) 
EscapeClean = P ( false ) 
if piton.begin_escape ~= nil
then 
  Escape = 
    P(piton.begin_escape)
    * L ( ( 1 - P(piton.end_escape) ) ^ 1 ) 
    * P(piton.end_escape)
%    \end{macrocode}
% The LPEG |EscapeClean| will be used in the LPEG Clean (and that LPEG is used
% to ``clean'' the code by removing the formatting elements).
%    \begin{macrocode}
  EscapeClean = 
    P(piton.begin_escape)
    * ( 1 - P(piton.end_escape) ) ^ 1 
    * P(piton.end_escape)
end
%    \end{macrocode}
% 
%    \begin{macrocode}
EscapeMath = P ( false ) 
if piton.begin_escape_math ~= nil
then 
  EscapeMath = 
    P(piton.begin_escape_math)
    * Lc ( "\\ensuremath{" ) 
    * L ( ( 1 - P(piton.end_escape_math) ) ^ 1 )
    * Lc ( "}" ) 
    * P(piton.end_escape_math)
end
%    \end{macrocode}
% 
% \vspace{1cm}
% The following line is mandatory.
%    \begin{macrocode}
lpeg.locale(lpeg)
%    \end{macrocode}
%
% \bigskip
% \paragraph{The basic syntactic LPEG}
%
%    \begin{macrocode}
local alpha, digit = lpeg.alpha, lpeg.digit
local space = P " " 
%    \end{macrocode}
%
% Remember that, for \textsc{lpeg}, the Unicode characters such as |à|, |â|,
% |ç|, etc. are in fact strings of length 2 (2 bytes) because \pkg{lpeg} is not
% Unicode-aware. 
%    \begin{macrocode}
local letter = alpha + P "_" 
  + P "â" + P "à" + P "ç" + P "é" + P "è" + P "ê" + P "ë" + P "ï" + P "î" 
  + P "ô" + P "û" + P "ü" + P "Â" + P "À" + P "Ç" + P "É" + P "È" + P "Ê" 
  + P "Ë" + P "Ï" + P "Î" + P "Ô" + P "Û" + P "Ü" 

local alphanum = letter + digit
%    \end{macrocode}
% 
% \bigskip
% The following \textsc{lpeg} |identifier| is a mere pattern (that is to say
% more or less a regular expression) which matches the Python identifiers (hence
% the name).
%    \begin{macrocode}
local identifier = letter * alphanum ^ 0
%    \end{macrocode}
% 
% \medskip
% On the other hand, the \textsc{lpeg} |Identifier| (with a capital) also returns
% a \emph{capture}.
%    \begin{macrocode}
local Identifier = K ( 'Identifier' , identifier )
%    \end{macrocode}
%
% \bigskip
% By convention, we will use names with an initial capital for \textsc{lpeg}
% which return captures.
%
% 
% \bigskip
% Here is the first use of our function~|K|. That function will be used to
% construct \textsc{lpeg} which capture Python chunks for which we have a
% dedicated \pkg{piton} style. For example, for the numbers, \pkg{piton}
% provides a style which is called |Number|. The name of the style is provided
% as a Lua string in the second argument of the function~|K|. By convention, we
% use single quotes for delimiting the Lua strings which are names of
% \pkg{piton} styles (but this is only a convention).
%    \begin{macrocode}
local Number =
  K ( 'Number' ,
      ( digit^1 * P "." * digit^0 + digit^0 * P "." * digit^1 + digit^1 )
      * ( S "eE" * S "+-" ^ -1 * digit^1 ) ^ -1
      + digit^1 
    ) 
%    \end{macrocode}
%
% \bigskip
% We recall that |piton.begin_espace| and |piton_end_escape| are Lua strings
% corresponding to the keys |begin-escape| and |end-escape|. 
%    \begin{macrocode}
local Word
if piton.begin_escape ~= nil 
then Word = Q ( ( ( 1 - space - P(piton.begin_escape) - P(piton.end_escape) ) 
                   - S "'\"\r[({})]" - digit ) ^ 1 )
else Word = Q ( ( ( 1 - space ) - S "'\"\r[({})]" - digit ) ^ 1 )
end
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
local Space = ( Q " " ) ^ 1

local SkipSpace = ( Q " " ) ^ 0 

local Punct = Q ( S ".,:;!" )

local Tab = P "\t" * Lc ( '\\l_@@_tab_tl' )
%    \end{macrocode}
% 
% \bigskip
%    \begin{macrocode}
local SpaceIndentation = Lc ( '\\@@_an_indentation_space:' ) * ( Q " " )
%    \end{macrocode}
%
%
% \bigskip
%    \begin{macrocode}
local Delim = Q ( S "[({})]" )
%    \end{macrocode}
% 
% \bigskip
% The following \textsc{lpeg} catches a space (U+0020) and replace it by
% |\l_@@_space_tl|. It will be used in the strings. Usually,
% |\l_@@_space_tl| will contain a space and therefore there won't be difference.
% However, when the key |show-spaces-in-strings| is in force, |\\l_@@_space_tl| will
% contain ␣ (U+2423) in order to visualize the spaces.
%    \begin{macrocode}
local VisualSpace = space * Lc "\\l_@@_space_tl" 
%    \end{macrocode}
% 
% \bigskip
% If the classe Beamer is used, some environemnts and commands of Beamer are
% automatically detected in the listings of \pkg{piton}.
%    \begin{macrocode}
local Beamer = P ( false ) 
local BeamerBeginEnvironments = P ( true ) 
local BeamerEndEnvironments = P ( true ) 
if piton_beamer 
then
% \bigskip
% The following function will return a \textsc{lpeg} which will catch an
% environment of Beamer (supported by \pkg{piton}), that is to say |{uncover}|,
% |{only}|, etc.
%    \begin{macrocode}
  local BeamerNamesEnvironments =  
    P "uncoverenv" + P "onlyenv" + P "visibleenv" + P "invisibleenv" 
    + P "alertenv" + P "actionenv"
  BeamerBeginEnvironments = 
      ( space ^ 0 * 
        L 
          ( 
            P "\\begin{" * BeamerNamesEnvironments * "}"
            * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1
          )
        * P "\r" 
      ) ^ 0 
  BeamerEndEnvironments = 
      ( space ^ 0 * 
        L ( P "\\end{" * BeamerNamesEnvironments * P "}" ) 
        * P "\r" 
      ) ^ 0 
%    \end{macrocode}
%
% 
% \bigskip
% The following function will return a \textsc{lpeg} which will catch an
% environment of Beamer (supported by \pkg{piton}), that is to say
% |{uncoverenv}|, etc. The argument |lpeg| should be |MainLoopPython|,
% |MainLoopC|, etc. 
%    \begin{macrocode}
  function OneBeamerEnvironment(name,lpeg)
    return 
        Ct ( Cc "Open" 
              * C ( 
                    P ( "\\begin{" .. name ..   "}" )
                    * ( P "<" * ( 1 - P ">") ^ 0 * P ">" ) ^ -1 
                  ) 
             * Cc ( "\\end{" .. name ..  "}" )
            ) 
       * ( 
           ( ( 1 - P ( "\\end{" .. name .. "}" ) ) ^ 0 ) 
              / ( function (s) return lpeg : match(s) end ) 
         )
       * P ( "\\end{" .. name ..  "}" ) * Ct ( Cc "Close" ) 
  end 
end
%    \end{macrocode}
% 
% 
%
% \bigskip
%    \begin{macrocode}
local languages = { }
local CleanLPEGs = { }
%    \end{macrocode}
% 
% \bigskip
% \subsubsection{The LPEG python}
% 
% \bigskip
% Some strings of length 2 are explicit because we want the corresponding
% ligatures available in some fonts such as \emph{Fira Code} to be active.
%    \begin{macrocode}
local Operator = 
  K ( 'Operator' ,
      P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" 
      + P "//" + P "**" + S "-~+/*%=<>&.@|" 
    )

local OperatorWord = 
  K ( 'Operator.Word' , P "in" + P "is" + P "and" + P "or" + P "not" )

local Keyword = 
  K ( 'Keyword' ,
      P "as" + P "assert" + P "break" + P "case" + P "class" + P "continue" 
      + P "def" + 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" )
  + K ( 'Keyword.Constant' ,P "True" + P "False" + P "None" ) 

local Builtin = 
  K ( 'Name.Builtin' ,
      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" )


local Exception =
  K ( 'Exception' ,
      P "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" )


local RaiseException = K ( 'Keyword' , P "raise" ) * SkipSpace * Exception * Q ( P "(" ) 

%    \end{macrocode}
%
% \bigskip
% In Python, a ``decorator'' is a statement whose begins by |@| which patches
% the function defined in the following statement.
%    \begin{macrocode}
local Decorator = K ( 'Name.Decorator' , P "@" * letter^1  ) 
%    \end{macrocode}
% 
% \bigskip
% The following \textsc{lpeg} |DefClass| will be used to detect the definition of a
% new class (the name of that new class will be formatted with the \pkg{piton}
% style |Name.Class|). 
%
% \smallskip
% Example:\enskip \piton{class myclass:}
%    \begin{macrocode}
local DefClass = 
  K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier ) 
%    \end{macrocode}
% 
% If the word |class| is not followed by a identifier, it will be catched as
% keyword by the \textsc{lpeg} |Keyword| (useful if we want to type a
% list of keywords).
%
%
% \bigskip
% The following \textsc{lpeg} |ImportAs| is used for the lines beginning by |import|.
% % We have to detect the potential keyword |as| because both the name of the
% module and its alias must be formatted with the \pkg{piton} style |Name.Namespace|.
%
% \smallskip
% Example:\enskip \piton{import numpy as np}
%
% \smallskip
% Moreover, after the keyword |import|, it's possible to have a comma-separated
% list of modules (if the keyword |as| is not used).
%
% \smallskip
% Example:\enskip \piton{import math, numpy}
%    \begin{macrocode}
local ImportAs = 
  K ( 'Keyword' , P "import" )
   * Space 
   * K ( 'Name.Namespace' , 
         identifier * ( P "." * identifier ) ^ 0 )
   * ( 
       ( Space * K ( 'Keyword' , P "as" ) * Space 
          * K ( 'Name.Namespace' , identifier ) )
       + 
       ( SkipSpace * Q ( P "," ) * SkipSpace 
          * K ( 'Name.Namespace' , identifier ) ) ^ 0 
     ) 
%    \end{macrocode}
% Be careful: there is no commutativity of |+| in the previous expression.
%
% \bigskip
% The \textsc{lpeg} |FromImport| is used for the lines beginning by |from|. We
% need a special treatment because the identifier following the keyword |from|
% must be formatted with the \pkg{piton} style |Name.Namespace| and the
% following keyword |import| must be formatted with the \pkg{piton} style
% |Keyword| and must \emph{not} be catched by the \textsc{lpeg} |ImportAs|.
%
% \smallskip
% Example:\enskip \piton{from math import pi}
%
% \smallskip
%    \begin{macrocode}
local FromImport =
  K ( 'Keyword' , P "from" ) 
    * Space * K ( 'Name.Namespace' , identifier )
    * Space * K ( 'Keyword' , P "import" ) 
%    \end{macrocode}
%
% \bigskip
% \paragraph{The strings of Python}
%
% For the strings in Python, there are four categories of delimiters (without
% counting the prefixes for f-strings and raw strings). We will use, in the
% names of our \textsc{lpeg}, prefixes to distinguish the \textsc{lpeg} dealing
% with that categories of strings, as presented in the following tabular.
% \begin{center}
% \begin{tabular}{@{}lcc@{}}
% \toprule
%         & |Single| & |Double| \\
% \midrule
% |Short| & |'text'|     & |"text"| \\
% |Long|  & |'''test'''| & |"""text"""| \\
% \bottomrule
% \end{tabular}
% \end{center}
%
% 
% \bigskip
% We have also to deal with the interpolations in the f-strings. Here
% is an example of a f-string with an interpolation and a format
% instruction\footnote{There is no special \pkg{piton} style for the formatting
% instruction (after the colon): the style which will be applied will be the
% style of the encompassing string, that is to say |String.Short| or
% |String.Long|.} in that interpolation:
%
% \piton{f'Total price: {total+1:.2f} €'}
%
%
% \bigskip
% The interpolations beginning by |%| (even though there is more modern
% technics now in Python).
%    \begin{macrocode}
local PercentInterpol =  
  K ( 'String.Interpol' , 
      P "%" 
      * ( P "(" * alphanum ^ 1 * P ")" ) ^ -1 
      * ( S "-#0 +" ) ^ 0 
      * ( digit ^ 1 + P "*" ) ^ -1 
      * ( P "." * ( digit ^ 1 + P "*" ) ) ^ -1 
      * ( S "HlL" ) ^ -1
      * S "sdfFeExXorgiGauc%" 
    ) 
%    \end{macrocode}
% 
% \bigskip
% We can now define the \textsc{lpeg} for the four kinds of strings. It's not
% possible to use our function~|K| because of the interpolations which must be
% formatted with another \pkg{piton} style that the rest of the
% string.\footnote{The interpolations are formatted with the \pkg{piton} style
% |Interpol.Inside|. The initial value of that style is \texttt{\textbackslash
% @@\_piton:n} wich means that the interpolations are parsed once again by \pkg{piton}.}
%    \begin{macrocode}
local SingleShortString =
  WithStyle ( 'String.Short' ,
%    \end{macrocode}
% First, we deal with the f-strings of Python, which are prefixed by |f| or |F|.
%    \begin{macrocode}
         Q ( P "f'" + P "F'" ) 
         * ( 
             K ( 'String.Interpol' , P "{" )
              * K ( 'Interpol.Inside' , ( 1 - S "}':" ) ^ 0  )
              * Q ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1
              * K ( 'String.Interpol' , P "}" )
             + 
             VisualSpace 
             + 
             Q ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 )
           ) ^ 0 
         * Q ( P "'" )
       + 
%    \end{macrocode}
% Now, we deal with the standard strings of Python, but also the ``raw strings''.
%    \begin{macrocode}
         Q ( P "'" + P "r'" + P "R'" ) 
         * ( Q ( ( P "\\'" + 1 - S " '\r%" ) ^ 1 ) 
             + VisualSpace 
             + PercentInterpol 
             + Q ( P "%" ) 
           ) ^ 0 
         * Q ( P "'" ) )


local DoubleShortString =
  WithStyle ( 'String.Short' , 
         Q ( P "f\"" + P "F\"" ) 
         * ( 
             K ( 'String.Interpol' , P "{" )
               * K ( 'Interpol.Inside' , ( 1 - S "}\":" ) ^ 0 )
               * ( K ( 'String.Interpol' , P ":" ) * Q ( (1 - S "}:\"") ^ 0 ) ) ^ -1
               * K ( 'String.Interpol' , P "}" )
             + 
             VisualSpace 
             + 
             Q ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 ) 
            ) ^ 0
         * Q ( P "\"" )
       +
         Q ( P "\"" + P "r\"" + P "R\"" ) 
         * ( Q ( ( P "\\\"" + 1 - S " \"\r%" ) ^ 1 ) 
             + VisualSpace 
             + PercentInterpol 
             + Q ( P "%" ) 
           ) ^ 0 
         * Q ( P "\"" ) )

local ShortString = SingleShortString + DoubleShortString
%    \end{macrocode}
%
% \bigskip
% \paragraph{Beamer}
%
% The following pattern |balanced_braces| will be used for the (mandatory)
% argument of the commands |\only| and \emph{al.} of Beamer. It's necessary to
% use a \emph{grammar} because that pattern mainly checks the correct nesting of
% the delimiters (and it's known in the theory of formal languages that this
% can't be done with regular expressions \emph{stricto sensu} only).
%    \begin{macrocode}
local balanced_braces =
  P { "E" ,
       E = 
           (
             P "{" * V "E" * P "}" 
             + 
             ShortString  
             + 
             ( 1 - S "{}" ) 
           ) ^ 0 
    }
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
if piton_beamer 
then
  Beamer =
      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) 
    + 
      Ct ( Cc "Open" 
            * C ( 
                  ( 
                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
                    + P "\\invisible" + P "\\action" 
                  ) 
                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 
                  * P "{" 
                ) 
            * Cc "}" 
         ) 
       * ( balanced_braces / (function (s) return MainLoopPython:match(s) end ) )
       * P "}" * Ct ( Cc "Close" ) 
    + OneBeamerEnvironment ( "uncoverenv" , MainLoopPython ) 
    + OneBeamerEnvironment ( "onlyenv" , MainLoopPython ) 
    + OneBeamerEnvironment ( "visibleenv" , MainLoopPython )
    + OneBeamerEnvironment ( "invisibleenv" , MainLoopPython ) 
    + OneBeamerEnvironment ( "alertenv" , MainLoopPython ) 
    + OneBeamerEnvironment ( "actionenv" , MainLoopPython ) 
    +
      L ( 
%    \end{macrocode}
% For |\\alt|, the specification of the overlays (between angular brackets) is mandatory.
%    \begin{macrocode}
          ( P "\\alt" )
          * P "<" * (1 - P ">") ^ 0 * P ">" 
          * P "{" 
        )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}" )
    +  
      L ( 
%    \end{macrocode}
% For |\\temporal|, the specification of the overlays (between angular brackets) is mandatory.
%    \begin{macrocode}
          ( P "\\temporal" )
          * P "<" * (1 - P ">") ^ 0 * P ">" 
          * P "{" 
        )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}" )
end
%    \end{macrocode}
%
% \bigskip
% \paragraph{Detected commands}
%
%    \begin{macrocode}
DetectedCommands = 
      Ct ( Cc "Open" 
            * C ( piton.ListCommands * P "{" ) 
            * Cc "}" 
         ) 
       * ( balanced_braces / (function (s) return MainLoopPython:match(s) end ) )
       * P "}" * Ct ( Cc "Close" ) 
%    \end{macrocode}
%
% \bigskip
%
% \paragraph{The LPEG Clean}
%
%    \begin{macrocode}
CleanLPEGs['python']
      = Ct ( ( piton.ListCommands * P "{" 
                * (  balanced_braces 
                    / ( function (s) return CleanLPEGs['python']:match(s) end ) )
                * P "}" 
               + EscapeClean
               +  C ( P ( 1 ) )
              ) ^ 0 ) / table.concat 
%    \end{macrocode}
% 
% 
% \bigskip
% \paragraph{EOL}
%
% \bigskip
% The following LPEG will detect the Python prompts when the user is typesetting
% an interactive session of Python (directly or through |{pyconsole}| of
% \pkg{pyluatex}). We have to detect that prompt twice. The first detection
% (called \emph{hasty detection}) will be before the |\@@_begin_line:| because
% you want to trigger a special background color for that row (and, after the
% |\@@_begin_line:|, it's too late to change de background).
%    \begin{macrocode}
local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\@@_prompt:' ) ) ^ -1 
%    \end{macrocode}
% We remind that the marker |#| of \textsc{lpeg} specifies that the pattern will be
% detected but won't consume any character.
%
% \medskip
% With the following \textsc{lpeg}, a style will actually be applied to the
% prompt (for instance, it's possible to decide to discard these prompts).
%    \begin{macrocode}
local Prompt = K ( 'Prompt' , ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1  ) 
%    \end{macrocode}
%    
%
%
% \bigskip
% The following \textsc{lpeg} |EOL| is for the end of lines.
%    \begin{macrocode}
local EOL = 
  P "\r" 
  *
  (
    ( space^0 * -1 )
    + 
%    \end{macrocode}
% We recall that each line in the Python code we have to parse will be sent
% back to LaTeX between a pair |\@@_begin_line:| --
% |\@@_end_line:|\footnote{Remember that the \texttt{\textbackslash
% @@\_end\_line:} must be explicit because it will be used as marker in order to
% delimit the argument of the command \texttt{\textbackslash @@\_begin\_line:}}.
%    \begin{macrocode}
    Ct ( 
         Cc "EOL"
         * 
         Ct (
              Lc "\\@@_end_line:"
              * BeamerEndEnvironments 
              * BeamerBeginEnvironments 
              * PromptHastyDetection
              * Lc "\\@@_newline: \\@@_begin_line:"
              * Prompt
            )
       )
  ) 
  *
  SpaceIndentation ^ 0
%    \end{macrocode}
%
% 
% \bigskip
% \paragraph{The long strings}
% 
% 
%    \begin{macrocode}
local SingleLongString =
  WithStyle ( 'String.Long' , 
     ( Q ( S "fF" * P "'''" )
         * (
             K ( 'String.Interpol' , P "{"  )
               * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "'''" ) ^ 0  )
               * Q ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1
               * K ( 'String.Interpol' , P "}"  )
             + 
             Q ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 )
             + 
             EOL
           ) ^ 0 
       +
         Q ( ( S "rR" ) ^ -1  * P "'''" )
         * (
             Q ( ( 1 - P "'''" - S "\r%" ) ^ 1 )  
             + 
             PercentInterpol
             +
             P "%"
             +
             EOL
           ) ^ 0 
      )
      * Q ( P "'''" ) ) 


local DoubleLongString =
  WithStyle ( 'String.Long' ,
     (
        Q ( S "fF" * P "\"\"\"" )
        * (
            K ( 'String.Interpol', P "{"  )
              * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 )
              * Q ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1
              * K ( 'String.Interpol' , P "}"  )
            + 
            Q ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 ) 
            + 
            EOL
          ) ^ 0 
      +
        Q ( ( S "rR" ) ^ -1  * P "\"\"\"" )
        * (
            Q ( ( 1 - P "\"\"\"" - S "%\r" ) ^ 1 )  
            + 
            PercentInterpol 
            + 
            P "%"
            + 
            EOL
          ) ^ 0 
     )
     * Q ( P "\"\"\"" ) 
  ) 
%    \end{macrocode}
%
%    \begin{macrocode}
local LongString = SingleLongString + DoubleLongString
%    \end{macrocode}
%
% \bigskip
% We have a \textsc{lpeg} for the Python docstrings. That \textsc{lpeg} will
% be used in the \textsc{lpeg} |DefFunction| which deals with the whole preamble
% of a function definition (which begins with |def|).
%    \begin{macrocode}
local StringDoc = 
    K ( 'String.Doc' , P "r" ^ -1 * P "\"\"\"" )
      * ( K ( 'String.Doc' , (1 - P "\"\"\"" - P "\r" ) ^ 0  ) * EOL
          * Tab ^ 0 
        ) ^ 0
      * K ( 'String.Doc' , ( 1 - P "\"\"\"" - P "\r" ) ^ 0 * P "\"\"\"" )
%    \end{macrocode}
%
% \bigskip
% \paragraph{The comments in the Python listings}
%
% We define different \textsc{lpeg} dealing with comments in the Python
% listings.
%    \begin{macrocode}
local CommentMath = 
  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$"

local Comment = 
  WithStyle ( 'Comment' ,
     Q ( P "#" ) 
     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) 
  * ( EOL + -1 )
%    \end{macrocode}
% 
%
%
% \bigskip
% The following \textsc{lpeg} |CommentLaTeX| is for what is called in that
% document the ``LaTeX comments''. Since the elements that will be catched must
% be sent to LaTeX with standard LaTeX catcodes, we put the capture (done by
% the function~|C|) in a table (by using~|Ct|, which is an alias for |lpeg.Ct|).
%    \begin{macrocode}
local CommentLaTeX =
  P(piton.comment_latex) 
  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" 
  * L ( ( 1 - P "\r" ) ^ 0 ) 
  * Lc "}}" 
  * ( EOL + -1 )  
%    \end{macrocode}
% 
% \bigskip
% \paragraph{DefFunction}
%
% The following \textsc{lpeg} |expression| will be used for the parameters in
% the \emph{argspec} of a Python function. It's necessary to use a \emph{grammar}
% because that pattern mainly checks the correct nesting of the delimiters
% (and it's known in the theory of formal languages that this can't be done with
% regular expressions \emph{stricto sensu} only). 
%    \begin{macrocode}
local expression =
  P { "E" ,
       E = ( 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 ,
       F = ( P "{" * V "F" * P "}"
             + P "(" * V "F" * P ")"
             + P "[" * V "F" * P "]"
             + ( 1 - S "{}()[]\r\"'" ) ) ^ 0
    }
%    \end{macrocode}
%
% \bigskip 
% We will now define a \textsc{lpeg} |Params| that will catch the list of
% parameters (that is to say the \emph{argspec}) in the definition of a Python
% function. For example, in the line of code
% \begin{center}
% \piton{def MyFunction(a,b,x=10,n:int): return n}
% \end{center}
% the \textsc{lpeg} |Params| will be used to catch the chunk\enskip |a,b,x=10,n:int|.
% 
% Or course, a |Params| is simply a comma-separated list of |Param|, and that's
% why we define first the \textsc{lpeg} |Param|.
%
% \medskip
%    \begin{macrocode}
local Param = 
  SkipSpace * ( Identifier + Q "*args" + Q "**kwargs" ) * SkipSpace
   * ( 
         K ( 'InitialValues' , P "=" * expression )
       + Q ( P ":" ) * SkipSpace * K ( 'Name.Type' , letter ^ 1  ) 
     ) ^ -1
%    \end{macrocode}
% 
% \medskip
%    \begin{macrocode}
local Params = ( Param * ( Q "," * Param ) ^ 0 ) ^ -1
%    \end{macrocode}
% 
% \bigskip
% The following \textsc{lpeg} |DefFunction| catches a keyword |def| and the
% following name of function \emph{but also everything else until a potential
% docstring}. That's why this definition of \textsc{lpeg} must occur (in the file
% |piton.sty|) after the definition of several other \textsc{lpeg} such as
% |Comment|, |CommentLaTeX|, |Params|, |StringDoc|...
%    \begin{macrocode}
local DefFunction =
  K ( 'Keyword' , P "def" )
  * Space
  * K ( 'Name.Function.Internal' , identifier ) 
  * SkipSpace 
  * Q ( P "(" ) * Params * Q ( P ")" ) 
  * SkipSpace
  * ( Q ( P "->" ) * SkipSpace * K ( 'Name.Type' , identifier  ) ) ^ -1
%    \end{macrocode}
% Here, we need a \pkg{piton} style |ParseAgain| which will be linked to
% |\@@_piton:n| (that means that the capture will be parsed once again by
% \pkg{piton}). We could avoid that kind of trick by using a non-terminal of a
% grammar but we have probably here a better legibility.
%    \begin{macrocode}
  * K ( 'ParseAgain' , ( 1 - S ":\r" )^0  ) 
  * Q ( P ":" )
  * ( SkipSpace
      * ( EOL + CommentLaTeX + Comment ) -- in all cases, that contains an EOL
      * Tab ^ 0 
      * SkipSpace
      * StringDoc ^ 0 -- there may be additionnal docstrings 
    ) ^ -1
%    \end{macrocode}
% Remark that, in the previous code, |CommentLaTeX| \emph{must} appear
% before |Comment|: there is no commutativity of the addition for the
% \emph{parsing expression grammars} (\textsc{peg}).
% 
% \smallskip 
% If the word |def| is not followed by an identifier and parenthesis, it will be
% catched as keyword by the \textsc{lpeg} |Keyword| (useful if, for example, the
% final user wants to speak of the keyword \piton{def}).
%
%
% \paragraph{Miscellaneous}
% 
%    \begin{macrocode}
local ExceptionInConsole = Exception *  Q ( ( 1 - P "\r" ) ^ 0 ) * EOL 
%    \end{macrocode}
% 
% 
% \bigskip
% \paragraph{The main LPEG for the language Python}
%
% First, the main loop :
%    \begin{macrocode}
local MainPython = 
       EOL
     + Space 
     + Tab
     + Escape + EscapeMath
     + CommentLaTeX
     + Beamer
     + DetectedCommands 
     + LongString 
     + Comment
     + ExceptionInConsole
     + Delim
     + Operator
     + OperatorWord * ( Space + Punct + Delim + EOL + -1 ) 
     + ShortString
     + Punct
     + FromImport
     + RaiseException 
     + DefFunction
     + DefClass 
     + Keyword * ( Space + Punct + Delim + EOL + -1 ) 
     + Decorator
     + Builtin * ( Space + Punct + Delim + EOL + -1 ) 
     + Identifier 
     + Number
     + Word
%    \end{macrocode}
%
% Here, we must not put |local|!
%    \begin{macrocode}
MainLoopPython = 
  (  ( space^1 * -1 ) 
     + MainPython
  ) ^ 0 
%    \end{macrocode}
%
% \bigskip
% We recall that each line in the Python code to parse will be sent back to
% LaTeX between a pair |\@@_begin_line:| -- |\@@_end_line:|\footnote{Remember
% that the \texttt{\textbackslash @@\_end\_line:} must be explicit because it
% will be used as marker in order to delimit the argument of the command
% \texttt{\textbackslash @@\_begin\_line:}}.
%    \begin{macrocode}
local python = P ( true ) 

python =
  Ct (
       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 
       * BeamerBeginEnvironments 
       * PromptHastyDetection
       * Lc '\\@@_begin_line:'
       * Prompt 
       * SpaceIndentation ^ 0 
       * MainLoopPython
       * -1 
       * Lc '\\@@_end_line:' 
     )
%    \end{macrocode}
%
%    \begin{macrocode}
languages['python'] = python
%    \end{macrocode}
%
% \bigskip
% \subsubsection{The LPEG ocaml}
% 
%    \begin{macrocode}
local Delim = Q ( P "[|" + P "|]" + S "[()]" )
%    \end{macrocode}
%
%    \begin{macrocode}
local Punct = Q ( S ",:;!" )
%    \end{macrocode}
% 
% The identifiers catched by |cap_identifier| begin with a cap. In OCaml, it's
% used for the constructors of types and for the modules.
%    \begin{macrocode}
local cap_identifier = R "AZ" * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 
%    \end{macrocode}
%
%    \begin{macrocode}
local Constructor = K ( 'Name.Constructor' , cap_identifier )
local ModuleType = K ( 'Name.Type' , cap_identifier ) 
%    \end{macrocode}
%
% The identifiers which begin with a lower case letter or an underscore are used 
% elsewhere in OCaml.
%    \begin{macrocode}
local identifier = 
  ( R "az" + P "_") * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 
local Identifier = K ( 'Identifier' , identifier )
%    \end{macrocode}
%
%
% Now, we deal with the records because we want to catch the names of the fields
% of those records in all circunstancies.
%    \begin{macrocode}
local expression_for_fields =
  P { "E" ,
       E = ( P "{" * V "F" * P "}"
             + P "(" * V "F" * P ")"
             + P "[" * V "F" * P "]" 
             + P "\"" * (P "\\\"" + 1 - S "\"\r" ) ^ 0 * P "\""
             + P "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * P "'"
             + ( 1 - S "{}()[]\r;" ) ) ^ 0 ,
       F = ( P "{" * V "F" * P "}"
             + P "(" * V "F" * P ")"
             + P "[" * V "F" * P "]"
             + ( 1 - S "{}()[]\r\"'" ) ) ^ 0
    }
%    \end{macrocode}
% 
%    \begin{macrocode}
local OneFieldDefinition = 
    ( K ( 'KeyWord' , P "mutable" ) * SkipSpace ) ^ -1
  * K ( 'Name.Field' , identifier ) * SkipSpace
  * Q ":" * SkipSpace
  * K ( 'Name.Type' , expression_for_fields ) 
  * SkipSpace

local OneField = 
    K ( 'Name.Field' , identifier ) * SkipSpace
  * Q "=" * SkipSpace
  * ( expression_for_fields / ( function (s) return LoopOCaml:match(s) end ) )
  * SkipSpace

local Record = 
  Q "{" * SkipSpace
  * 
    (
      OneFieldDefinition * ( Q ";" * SkipSpace * OneFieldDefinition ) ^ 0 
      + 
      OneField * ( Q ";" * SkipSpace * OneField ) ^ 0 
    )
  *
  Q "}"
%    \end{macrocode}
%
% \bigskip
% Now, we deal with the notations with points (eg: |List.length|). In OCaml,
% such notation is used for the fields of the records and for the modules.
%    \begin{macrocode}
local DotNotation = 
  (
      K ( 'Name.Module' , cap_identifier ) 
        * Q "." 
        * ( Identifier + Constructor + Q "(" + Q "[" + Q "{" ) 

      + 
      Identifier 
        * Q "."
        * K ( 'Name.Field' , identifier ) 
  )
  * ( Q "." * K ( 'Name.Field' , identifier ) ) ^ 0 
%    \end{macrocode}
%
%    \begin{macrocode}
local Operator = 
  K ( 'Operator' ,
      P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" 
      + P "||" + P "&&" + P "//" + P "**" + P ";;" + P "::" + P "->" 
      + P "+." + P "-." + P "*." + P "/." 
      + S "-~+/*%=<>&@|" 
    )

local OperatorWord = 
  K ( 'Operator.Word' ,
      P "and" + P "asr" + P "land" + P "lor" + P "lsl" + P "lxor" 
      + P "mod" + P "or" )

local Keyword = 
  K ( 'Keyword' ,
      P "assert" + P "and" + P "as" + P "begin" + P "class" + P "constraint" + P "done" 
  + P "downto" + P "do" + P "else" + P "end" + P "exception" + P "external" 
  + P "for" + P "function" + P "functor" + P "fun" + P "if" 
  + P "include" + P "inherit" + P "initializer" + P "in"  + P "lazy" + P "let" 
  + P "match" + P "method" + P "module" + P "mutable" + P "new" + P "object" 
  + P "of" + P "open" + P "private" + P "raise" + P "rec" + P "sig" 
  + P "struct" + P "then" + P "to" + P "try" + P "type" 
  + P "value" + P "val" + P "virtual" + P "when" + P "while" + P "with" )
  + K ( 'Keyword.Constant' , P "true" + P "false" )  


local Builtin = 
  K ( 'Name.Builtin' , P "not" + P "incr" + P "decr" + P "fst" + P "snd" )
%    \end{macrocode}
% 
% \bigskip
% The following exceptions are exceptions in the standard library of OCaml (Stdlib).
%    \begin{macrocode}
local Exception =
  K (   'Exception' ,
       P "Division_by_zero" + P "End_of_File" + P "Failure" 
     + P "Invalid_argument" + P "Match_failure" + P "Not_found" 
     + P "Out_of_memory" + P "Stack_overflow" + P "Sys_blocked_io" 
     + P "Sys_error" + P "Undefined_recursive_module" )
%    \end{macrocode}
%
% \bigskip
% \paragraph{The characters in OCaml}
%
%    \begin{macrocode}
local Char = 
  K ( 'String.Short' , P "'" * ( ( 1 - P "'" ) ^ 0 + P "\\'" ) * P "'" ) 
%    \end{macrocode}
% 
%
% \bigskip
% \paragraph{Beamer}
%
%    \begin{macrocode}
local balanced_braces =
  P { "E" ,
       E = 
           (
             P "{" * V "E" * P "}" 
             + 
             P "\"" * ( 1 - S "\"" ) ^ 0 * P "\""  -- OCaml strings
             + 
             ( 1 - S "{}" ) 
           ) ^ 0 
    }
%    \end{macrocode}
%
%
% \bigskip
%    \begin{macrocode}
if piton_beamer 
then
  Beamer =
      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) 
    + 
      Ct ( Cc "Open" 
            * C ( 
                  ( 
                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
                    + P "\\invisible" + P "\\action" 
                  ) 
                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 
                  * P "{" 
                ) 
            * Cc "}" 
         ) 
       * ( balanced_braces / (function (s) return MainLoopOCaml:match(s) end ) )
       * P "}" * Ct ( Cc "Close" ) 
    + OneBeamerEnvironment ( "uncoverenv" , MainLoopOCaml ) 
    + OneBeamerEnvironment ( "onlyenv" , MainLoopOCaml ) 
    + OneBeamerEnvironment ( "visibleenv" , MainLoopOCaml )
    + OneBeamerEnvironment ( "invisibleenv" , MainLoopOCaml ) 
    + OneBeamerEnvironment ( "alertenv" , MainLoopOCaml ) 
    + OneBeamerEnvironment ( "actionenv" , MainLoopOCaml ) 
    +
      L ( 
%    \end{macrocode}
% For |\\alt|, the specification of the overlays (between angular brackets) is mandatory.
%    \begin{macrocode}
          ( P "\\alt" )
          * P "<" * (1 - P ">") ^ 0 * P ">" 
          * P "{" 
        )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}" )
    +  
      L ( 
%    \end{macrocode}
% For |\\temporal|, the specification of the overlays (between angular brackets) is mandatory.
%    \begin{macrocode}
          ( P "\\temporal" )
          * P "<" * (1 - P ">") ^ 0 * P ">" 
          * P "{" 
        )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}" )
end
%    \end{macrocode}
%
%    \begin{macrocode}
DetectedCommands = 
      Ct ( Cc "Open" 
            * C ( piton.ListCommands * P "{" ) * Cc "}" 
         ) 
       * ( balanced_braces / (function (s) return MainLoopOCaml:match(s) end ) )
       * P "}" * Ct ( Cc "Close" ) 
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
CleanLPEGs['ocaml']
      = Ct ( ( piton.ListCommands * P "{" 
                * ( balanced_braces 
                    / ( function (s) return CleanLPEGs['ocaml']:match(s) end ) )
                * P "}" 
               + EscapeClean
               +  C ( P ( 1 ) )
              ) ^ 0 ) / table.concat 
%    \end{macrocode}
% 

% 
%
% \bigskip
% \paragraph{EOL}
%    \begin{macrocode}
local EOL = 
  P "\r" 
  *
  (
    ( space^0 * -1 )
    + 
    Ct ( 
         Cc "EOL"
         * 
         Ct (
              Lc "\\@@_end_line:"
              * BeamerEndEnvironments 
              * BeamerBeginEnvironments 
              * PromptHastyDetection
              * Lc "\\@@_newline: \\@@_begin_line:"
              * Prompt
            )
       )
  ) 
  *
  SpaceIndentation ^ 0
%    \end{macrocode}
%
% 
% \paragraph{The strings en OCaml}
% 
% We need a pattern |ocaml_string| without captures because it will be used
% within the comments of OCaml.
%    \begin{macrocode}
local ocaml_string =
       Q ( P "\"" )
     * ( 
         VisualSpace
         + 
         Q ( ( 1 - S " \"\r" ) ^ 1 ) 
         +  
         EOL
       ) ^ 0 
     * Q ( P "\"" ) 
%    \end{macrocode}
% 
%    \begin{macrocode}
local String = WithStyle ( 'String.Long' , ocaml_string ) 
%    \end{macrocode}
%
% 
% \bigskip
% Now, the ``quoted strings'' of OCaml (for example \verb+{ext|Essai|ext}+). 
%
% For those strings, we will do two consecutive analysis. First an analysis to
% determine the whole string and, then, an analysis for the potential visual
% spaces and the EOL in the string.
% 
% The first analysis require a match-time capture. For explanations about that
% programmation, see the paragraphe \emph{Lua's long % strings} in
% |www.inf.puc-rio.br/~roberto/lpeg|. 
%    \begin{macrocode}
local ext = ( R "az" + P "_" ) ^ 0
local open = "{" * Cg(ext, 'init') * "|" 
local close = "|" * C(ext) * "}"
local closeeq = 
  Cmt ( close * Cb('init'), 
        function (s, i, a, b) return a == b end ) 
%    \end{macrocode}
%
% \medskip
% The \textsc{lpeg} |QuotedStringBis| will do the second analysis. 
%    \begin{macrocode}
local QuotedStringBis = 
  WithStyle ( 'String.Long' ,
      (  
        Space
        +
        Q ( ( 1 - S " \r" ) ^ 1 ) 
        +  
        EOL
      ) ^ 0  ) 

%    \end{macrocode}
% 
% \medskip
% We use a ``function capture'' (as called in the official documentation of the
% \textsc{lpeg}) in order to do the second analysis on the result of the first one.
%    \begin{macrocode}
local QuotedString = 
   C ( open * ( 1 - closeeq ) ^ 0  * close ) /
  ( function (s) return QuotedStringBis : match(s) end ) 
%    \end{macrocode}
% 
%
% \bigskip
% \paragraph{The comments in the OCaml listings}
%
% In OCaml, the delimiters for the comments are |(*| and |*)|. There are
% unsymmetrical and OCaml allow those comments to be nested. That's why we need a
% grammar.
% 
% In these comments, we embed the math comments (between |$| and |$|) and we
% embed also a treatment for the end of lines (since the comments may be multi-lines).
% 
%    \begin{macrocode}
local Comment =
  WithStyle ( 'Comment' ,
     P {
         "A" ,
         A = Q "(*"
             * ( V "A" 
                 + Q ( ( 1 - P "(*" - P "*)" - S "\r$\"" ) ^ 1 ) -- $
                 + ocaml_string 
                 + P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" -- $
                 + EOL
               ) ^ 0 
             * Q "*)" 
       }   )
%    \end{macrocode}
% 
% \bigskip
% \paragraph{The DefFunction}
%
%    \begin{macrocode}
local balanced_parens =
  P { "E" ,
       E = 
           (
             P "(" * V "E" * P ")" 
             + 
             ( 1 - S "()" ) 
           ) ^ 0 
    }
%    \end{macrocode}
% 
%    \begin{macrocode}
local Argument = 
  K ( 'Identifier' , identifier ) 
  + Q "(" * SkipSpace 
    * K ( 'Identifier' , identifier ) * SkipSpace 
    * Q ":" * SkipSpace  
    * K ( 'Name.Type' , balanced_parens ) * SkipSpace
    * Q ")"
%    \end{macrocode}
%
% Despite its name, then \textsc{lpeg} |DefFunction| deals also with |let open|
% which opens locally a module.
%    \begin{macrocode}
local DefFunction = 
  K ( 'Keyword' , P "let open" ) 
   * Space
   * K ( 'Name.Module' , cap_identifier ) 
  + 
  K ( 'Keyword' , P "let rec" + P "let" + P "and" ) 
    * Space
    * K ( 'Name.Function.Internal' , identifier ) 
    * Space 
    * (
        Q "=" * SkipSpace * K ( 'Keyword' , P "function" ) 
        + 
        Argument 
         * ( SkipSpace * Argument ) ^ 0 
         * ( 
             SkipSpace 
             * Q ":" 
             * K ( 'Name.Type' , ( 1 - P "=" ) ^ 0 ) 
           ) ^ -1 
      ) 
%    \end{macrocode}
%
% 
% \bigskip
% \paragraph{The DefModule}\par
%
% The following LPEG will be used in the definitions of modules but also in the
% definitions of \emph{types} of modules.
%    \begin{macrocode}
local DefModule = 
  K ( 'Keyword' , P "module" ) * Space
  *
    (
          K ( 'Keyword' , P "type" ) * Space
        * K ( 'Name.Type' , cap_identifier ) 
      + 
        K ( 'Name.Module' , cap_identifier ) * SkipSpace 
        * 
          (
            Q "(" * SkipSpace 
              * K ( 'Name.Module' , cap_identifier ) * SkipSpace 
              * Q ":" * SkipSpace 
              * K ( 'Name.Type' , cap_identifier ) * SkipSpace 
              *
                (
                  Q "," * SkipSpace 
                    * K ( 'Name.Module' , cap_identifier ) * SkipSpace 
                    * Q ":" * SkipSpace 
                    * K ( 'Name.Type' , cap_identifier ) * SkipSpace 
                ) ^ 0 
              * Q ")"
          ) ^ -1
        *
          (
            Q "=" * SkipSpace
            * K ( 'Name.Module' , cap_identifier )  * SkipSpace 
            * Q "("
            * K ( 'Name.Module' , cap_identifier ) * SkipSpace 
              * 
              (
                Q ","
                * 
                K ( 'Name.Module' , cap_identifier ) * SkipSpace 
              ) ^ 0 
            * Q ")"
          ) ^ -1
    )
  + 
  K ( 'Keyword' , P "include" + P "open" )
  * Space * K ( 'Name.Module' , cap_identifier ) 
%    \end{macrocode}
% 
% \bigskip
% \paragraph{The parameters of the types}
% 
%    \begin{macrocode}
local TypeParameter = K ( 'TypeParameter' , P "'" * alpha * # ( 1 - P "'" ) ) 
%    \end{macrocode}
% 
% \bigskip
% \paragraph{The main LPEG for the language OCaml}
%
% First, the main loop :
%    \begin{macrocode}
MainOCaml = 
       EOL
     + Space 
     + Tab
     + Escape + EscapeMath
     + Beamer 
     + DetectedCommands
     + TypeParameter
     + String + QuotedString + Char
     + Comment
     + Delim
     + Operator
     + Punct
     + FromImport
     + Exception 
     + DefFunction
     + DefModule
     + Record 
     + Keyword * ( Space + Punct + Delim + EOL + -1 ) 
     + OperatorWord * ( Space + Punct + Delim + EOL + -1 ) 
     + Builtin * ( Space + Punct + Delim + EOL + -1 ) 
     + DotNotation
     + Constructor
     + Identifier 
     + Number
     + Word

LoopOCaml = MainOCaml ^ 0 

MainLoopOCaml = 
  (  ( space^1 * -1 ) 
     + MainOCaml
  ) ^ 0 
%    \end{macrocode}
%
% \bigskip
% We recall that each line in the Python code to parse will be sent back to
% LaTeX between a pair |\@@_begin_line:| -- |\@@_end_line:|\footnote{Remember
% that the \texttt{\textbackslash @@\_end\_line:} must be explicit because it
% will be used as marker in order to delimit the argument of the command
% \texttt{\textbackslash @@\_begin\_line:}}.
%    \begin{macrocode}
local ocaml = P ( true ) 

ocaml =
  Ct (
       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 
       * BeamerBeginEnvironments 
       * Lc ( '\\@@_begin_line:' ) 
       * SpaceIndentation ^ 0 
       * MainLoopOCaml
       * -1 
       * Lc ( '\\@@_end_line:' )
     )
%    \end{macrocode}
%
%    \begin{macrocode}
languages['ocaml'] = ocaml
%    \end{macrocode}
%
% \bigskip
% \subsubsection{The LPEG for the language C}
% 
%    \begin{macrocode}
local Delim = Q ( S "{[()]}" )
%    \end{macrocode}
%
%    \begin{macrocode}
local Punct = Q ( S ",:;!" )
%    \end{macrocode}
%
% \bigskip
% Some strings of length 2 are explicit because we want the corresponding
% ligatures available in some fonts such as \emph{Fira Code} to be active.
%    \begin{macrocode}
local identifier = letter * alphanum ^ 0

local Operator = 
  K ( 'Operator' ,
      P "!=" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" 
      + P "||" + P "&&" + S "-~+/*%=<>&.@|!" 
    )

local Keyword = 
  K ( 'Keyword' ,
      P "alignas" + P "asm" + P "auto" + P "break" + P "case" + P "catch"
      + P "class" + P "const" + P "constexpr" + P "continue" 
      + P "decltype" + P "do" + P "else" + P "enum" + P "extern" 
      + P "for" + P "goto" + P "if" + P "nexcept" + P "private" + P "public" 
      + P "register" + P "restricted" + P "return" + P "static" + P "static_assert" 
      + P "struct" + P "switch" + P "thread_local" + P "throw" + P "try" 
      + P "typedef" + P "union" + P "using" + P "virtual" + P "volatile" 
      + P "while" 
    )
  + K ( 'Keyword.Constant' , 
        P "default" + P "false" + P "NULL" + P "nullptr" + P "true" 
      ) 

local Builtin = 
  K ( 'Name.Builtin' ,
      P "alignof" + P "malloc" + P "printf" + P "scanf" + P "sizeof" 
    )

local Type = 
  K ( 'Name.Type' ,
      P "bool" + P "char" + P "char16_t" + P "char32_t" + P "double" 
      + P "float" + P "int" + P "int8_t" + P "int16_t" + P "int32_t" 
      + P "int64_t" + P "long" + P "short" + P "signed" + P "unsigned" 
      + P "void" + P "wchar_t" 
    )

local DefFunction = 
  Type 
  * Space 
  * Q ( "*" ) ^ -1 
  * K ( 'Name.Function.Internal' , identifier ) 
  * SkipSpace 
  * # P "("
%    \end{macrocode}
% We remind that the marker |#| of \textsc{lpeg} specifies that the pattern will be
% detected but won't consume any character.
%
% \bigskip
% The following \textsc{lpeg} |DefClass| will be used to detect the definition of a
% new class (the name of that new class will be formatted with the \pkg{piton}
% style |Name.Class|). 
%
% \smallskip
% Example:\enskip \piton{class myclass:}
%    \begin{macrocode}
local DefClass = 
  K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier ) 
%    \end{macrocode}
% 
% If the word |class| is not followed by a identifier, it will be catched as
% keyword by the \textsc{lpeg} |Keyword| (useful if we want to type a
% list of keywords).
%
% \bigskip
% \paragraph{The strings of C}
%
%    \begin{macrocode}
local String = 
  WithStyle ( 'String.Long' ,
      Q "\"" 
      * ( VisualSpace 
          + K ( 'String.Interpol' , 
                P "%" * ( S "difcspxXou" + P "ld" + P "li" + P "hd" + P "hi" )
              ) 
          + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 ) 
        ) ^ 0 
      * Q "\""
    )
%    \end{macrocode}
% 
% \bigskip
% \paragraph{Beamer}
%
% The following \textsc{lpeg} |balanced_braces| will be used for the (mandatory)
% argument of the commands |\only| and \emph{al.} of Beamer. It's necessary to
% use a \emph{grammar} because that pattern mainly checks the correct nesting of
% the delimiters (and it's known in the theory of formal languages that this
% can't be done with regular expressions \emph{stricto sensu} only).
%    \begin{macrocode}
local balanced_braces =
  P { "E" ,
       E = 
           (
             P "{" * V "E" * P "}" 
             + 
             String  
             + 
             ( 1 - S "{}" ) 
           ) ^ 0 
    }
%    \end{macrocode}
%
%
% \bigskip
%    \begin{macrocode}
if piton_beamer 
then
  Beamer =
      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) 
    + 
      Ct ( Cc "Open" 
            * C ( 
                  ( 
                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
                    + P "\\invisible" + P "\\action" 
                  ) 
                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 
                  * P "{" 
                ) 
            * Cc "}" 
         ) 
       * ( balanced_braces / (function (s) return MainLoopC:match(s) end ) )
       * P "}" * Ct ( Cc "Close" ) 
    + OneBeamerEnvironment ( "uncoverenv" , MainLoopC ) 
    + OneBeamerEnvironment ( "onlyenv" , MainLoopC ) 
    + OneBeamerEnvironment ( "visibleenv" , MainLoopC )
    + OneBeamerEnvironment ( "invisibleenv" , MainLoopC ) 
    + OneBeamerEnvironment ( "alertenv" , MainLoopC ) 
    + OneBeamerEnvironment ( "actionenv" , MainLoopC ) 
    +
      L ( 
%    \end{macrocode}
% For |\\alt|, the specification of the overlays (between angular brackets) is mandatory.
%    \begin{macrocode}
          ( P "\\alt" )
          * P "<" * (1 - P ">") ^ 0 * P ">" 
          * P "{" 
        )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}" )
    +  
      L ( 
%    \end{macrocode}
% For |\\temporal|, the specification of the overlays (between angular brackets) is mandatory.
%    \begin{macrocode}
          ( P "\\temporal" )
          * P "<" * (1 - P ">") ^ 0 * P ">" 
          * P "{" 
        )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}" )
end
%    \end{macrocode}
%
%    \begin{macrocode}
DetectedCommands = 
      Ct ( Cc "Open" 
            * C ( piton.ListCommands * P "{" ) * Cc "}" 
         ) 
       * ( balanced_braces / (function (s) return MainLoopC:match(s) end ) )
       * P "}" * Ct ( Cc "Close" ) 
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
CleanLPEGs['c']
      = Ct ( ( piton.ListCommands * P "{" 
                * ( balanced_braces 
                    / ( function (s) return CleanLPEGs['c']:match(s) end ) )
                * P "}" 
               + EscapeClean
               +  C ( P ( 1 ) )
              ) ^ 0 ) / table.concat 
%    \end{macrocode}
% 
% \bigskip
% \paragraph{EOL}
%
%
% The following \textsc{lpeg} |EOL| is for the end of lines.
%    \begin{macrocode}
local EOL = 
  P "\r" 
  *
  (
    ( space^0 * -1 )
    + 
%    \end{macrocode}
% We recall that each line in the Python code we have to parse will be sent
% back to LaTeX between a pair |\@@_begin_line:| --
% |\@@_end_line:|\footnote{Remember that the \texttt{\textbackslash
% @@\_end\_line:} must be explicit because it will be used as marker in order to
% delimit the argument of the command \texttt{\textbackslash @@\_begin\_line:}}.
%    \begin{macrocode}
    Ct ( 
         Cc "EOL"
         * 
         Ct (
              Lc "\\@@_end_line:"
              * BeamerEndEnvironments 
              * BeamerBeginEnvironments 
              * PromptHastyDetection
              * Lc "\\@@_newline: \\@@_begin_line:"
              * Prompt
            )
       )
  ) 
  *
  SpaceIndentation ^ 0
%    \end{macrocode}
%
% \bigskip
% \paragraph{The directives of the preprocessor}
%
%    \begin{macrocode}
local Preproc = 
  K ( 'Preproc' , P "#" * (1 - P "\r" ) ^ 0  ) * ( EOL + -1 )
%    \end{macrocode}
% 
%
% \bigskip
% \paragraph{The comments in the C listings}
%
% We define different \textsc{lpeg} dealing with comments in the C listings.
%    \begin{macrocode}
local CommentMath = 
  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$"

local Comment = 
  WithStyle ( 'Comment' ,
     Q ( P "//" ) 
     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) 
  * ( EOL + -1 )

local LongComment = 
  WithStyle ( 'Comment' , 
               Q ( P "/*" ) 
               * ( CommentMath + Q ( ( 1 - P "*/" - S "$\r" ) ^ 1 ) + EOL ) ^ 0 
               * Q ( P "*/" ) 
            ) -- $
%    \end{macrocode}
%
%
% \bigskip
% The following \textsc{lpeg} |CommentLaTeX| is for what is called in that
% document the ``LaTeX comments''. Since the elements that will be catched must
% be sent to LaTeX with standard LaTeX catcodes, we put the capture (done by
% the function~|C|) in a table (by using~|Ct|, which is an alias for |lpeg.Ct|).
%    \begin{macrocode}
local CommentLaTeX =
  P(piton.comment_latex) 
  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" 
  * L ( ( 1 - P "\r" ) ^ 0 ) 
  * Lc "}}" 
  * ( EOL + -1 )  
%    \end{macrocode}
% 
%
%
% 
% \bigskip
% \paragraph{The main LPEG for the language C}
%
% First, the main loop :
%    \begin{macrocode}
local MainC = 
       EOL
     + Space 
     + Tab
     + Escape + EscapeMath 
     + CommentLaTeX
     + Beamer
     + DetectedCommands
     + Preproc
     + Comment + LongComment
     + Delim
     + Operator
     + String
     + Punct
     + DefFunction
     + DefClass 
     + Type * ( Q ( "*" ) ^ -1 + Space + Punct + Delim + EOL + -1 ) 
     + Keyword * ( Space + Punct + Delim + EOL + -1 ) 
     + Builtin * ( Space + Punct + Delim + EOL + -1 ) 
     + Identifier 
     + Number
     + Word
%    \end{macrocode}
%
% Here, we must not put |local|!
%    \begin{macrocode}
MainLoopC = 
  (  ( space^1 * -1 ) 
     + MainC
  ) ^ 0 
%    \end{macrocode}
%
% \bigskip
% We recall that each line in the C code to parse will be sent back to
% LaTeX between a pair |\@@_begin_line:| -- |\@@_end_line:|\footnote{Remember
% that the \texttt{\textbackslash @@\_end\_line:} must be explicit because it
% will be used as marker in order to delimit the argument of the command
% \texttt{\textbackslash @@\_begin\_line:}}.
%    \begin{macrocode}
languageC =
  Ct (
       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 
       * BeamerBeginEnvironments 
       * Lc '\\@@_begin_line:'
       * SpaceIndentation ^ 0 
       * MainLoopC
       * -1 
       * Lc '\\@@_end_line:' 
     )
%    \end{macrocode}
%
%    \begin{macrocode}
languages['c'] = languageC
%    \end{macrocode}
%
%
% \bigskip
% \subsubsection{The LPEG language SQL}
% 
% \bigskip
% In the identifiers, we will be able to catch those contening spaces, that is
% to say like |"last name"|. 
%    \begin{macrocode}
local identifier = 
  letter * ( alphanum + P "-" ) ^ 0 
  + P '"' * ( ( alphanum + space - P '"' ) ^ 1 ) * P '"' 


local Operator = 
  K ( 'Operator' ,
      P "=" + P "!=" + P "<>" + P ">=" + P ">" + P "<=" + P "<"  + S "*+/"
    )
%    \end{macrocode}
%
% In SQL, the keywords are case-insensitive. That's why we have a little
% complication. We will catch the keywords with the identifiers and, then,
% distinguish the keywords with a Lua function. However, some keywords will be
% catched in special LPEG because we want to detect the names of the SQL tables.
%    \begin{macrocode}
local function Set (list)
  local set = {}
  for _, l in ipairs(list) do set[l] = true end
  return set
end

local set_keywords = Set
 { 
   "ADD" , "AFTER" , "ALL" , "ALTER" , "AND" , "AS" , "ASC" , "BETWEEN" , "BY" ,
   "CHANGE" , "COLUMN" , "CREATE" , "CROSS JOIN" , "DELETE" , "DESC" , "DISTINCT" , 
   "DROP" , "FROM" , "GROUP" , "HAVING" , "IN" , "INNER" , "INSERT" , "INTO" , "IS" , 
   "JOIN" , "LEFT" , "LIKE" , "LIMIT" , "MERGE" , "NOT" , "NULL" , "ON" , "OR" , 
   "ORDER" , "OVER" , "RIGHT" , "SELECT" , "SET" , "TABLE" , "THEN" , "TRUNCATE" , 
   "UNION" , "UPDATE" , "VALUES" , "WHEN" , "WHERE" , "WITH"
 }

local set_builtins = Set
 { 
   "AVG" , "COUNT" , "CHAR_LENGHT" , "CONCAT" , "CURDATE" , "CURRENT_DATE" ,
   "DATE_FORMAT" , "DAY" , "LOWER" , "LTRIM" , "MAX" , "MIN" , "MONTH" , "NOW" ,
   "RANK" , "ROUND" , "RTRIM" , "SUBSTRING" , "SUM" , "UPPER" , "YEAR" 
 }
%    \end{macrocode}
%
% The \textsc{lpeg} |Identifer| will catch the identifiers of the fields  
% but also the keywords and the built-in functions of SQL. If will \emph{not}
% catch the names of the SQL tables.
%    \begin{macrocode}
local Identifier = 
  C ( identifier ) /
  ( 
    function (s) 
        if set_keywords[string.upper(s)] -- the keywords are case-insensitive in SQL
%    \end{macrocode}
% Remind that, in Lua, it's possible to return \emph{several} values. 
%    \begin{macrocode}
        then return { "{\\PitonStyle{Keyword}{" } ,
                    { luatexbase.catcodetables.other , s } ,
                    { "}}" }
        else if set_builtins[string.upper(s)]
             then return { "{\\PitonStyle{Name.Builtin}{" } ,
                         { luatexbase.catcodetables.other , s } ,
                         { "}}" }
             else return { "{\\PitonStyle{Name.Field}{" } ,
                         { luatexbase.catcodetables.other , s } ,
                         { "}}" }
             end
        end 
    end
  ) 
%    \end{macrocode}
% 
% \bigskip
% \paragraph{The strings of SQL}
%
%    \begin{macrocode}
local String = 
  K ( 'String.Long' , P "'" * ( 1 - P "'" ) ^ 1 * P "'" ) 
%    \end{macrocode}
% 
% \bigskip
% \paragraph{Beamer}
%
% The following \textsc{lpeg} |balanced_braces| will be used for the (mandatory)
% argument of the commands |\only| and \emph{al.} of Beamer. It's necessary to
% use a \emph{grammar} because that pattern mainly checks the correct nesting of
% the delimiters (and it's known in the theory of formal languages that this
% can't be done with regular expressions \emph{stricto sensu} only).
%    \begin{macrocode}
local balanced_braces =
  P { "E" ,
       E = 
           (
             P "{" * V "E" * P "}" 
             + 
             String  
             + 
             ( 1 - S "{}" ) 
           ) ^ 0 
    }
%    \end{macrocode}
%
%
% \bigskip
%    \begin{macrocode}
if piton_beamer 
then
  Beamer =
      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) 
    + 
      Ct ( Cc "Open" 
            * C ( 
                  ( 
                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
                    + P "\\invisible" + P "\\action" 
                  ) 
                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 
                  * P "{" 
                ) 
            * Cc "}" 
         ) 
       * ( balanced_braces / (function (s) return MainLoopSQL:match(s) end ) )
       * P "}" * Ct ( Cc "Close" ) 
    + OneBeamerEnvironment ( "uncoverenv" , MainLoopSQL ) 
    + OneBeamerEnvironment ( "onlyenv" , MainLoopSQL ) 
    + OneBeamerEnvironment ( "visibleenv" , MainLoopSQL )
    + OneBeamerEnvironment ( "invisibleenv" , MainLoopSQL ) 
    + OneBeamerEnvironment ( "alertenv" , MainLoopSQL ) 
    + OneBeamerEnvironment ( "actionenv" , MainLoopSQL ) 
    +
      L ( 
%    \end{macrocode}
% For |\\alt|, the specification of the overlays (between angular brackets) is mandatory.
%    \begin{macrocode}
          ( P "\\alt" )
          * P "<" * (1 - P ">") ^ 0 * P ">" 
          * P "{" 
        )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}" )
    +  
      L ( 
%    \end{macrocode}
% For |\\temporal|, the specification of the overlays (between angular brackets) is mandatory.
%    \begin{macrocode}
          ( P "\\temporal" )
          * P "<" * (1 - P ">") ^ 0 * P ">" 
          * P "{" 
        )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}" )
end
%    \end{macrocode}
%
%    \begin{macrocode}
DetectedCommands = 
      Ct ( Cc "Open" 
            * C ( piton.ListCommands * P "{" ) * Cc "}" 
         ) 
       * ( balanced_braces / (function (s) return MainLoopSQL:match(s) end ) )
       * P "}" * Ct ( Cc "Close" ) 
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
CleanLPEGs['sql']
      = Ct ( ( piton.ListCommands * P "{" 
                * ( balanced_braces 
                    / ( function (s) return CleanLPEGs['sql']:match(s) end ) )
                * P "}" 
               + EscapeClean
               +  C ( P ( 1 ) )
              ) ^ 0 ) / table.concat 
%    \end{macrocode}
%
% \bigskip
% \paragraph{EOL}
%
% \bigskip
% The following \textsc{lpeg} |EOL| is for the end of lines.
%    \begin{macrocode}
local EOL = 
  P "\r" 
  *
  (
    ( space^0 * -1 )
    + 
%    \end{macrocode}
% We recall that each line in the SQL code we have to parse will be sent
% back to LaTeX between a pair |\@@_begin_line:| --
% |\@@_end_line:|\footnote{Remember that the \texttt{\textbackslash
% @@\_end\_line:} must be explicit because it will be used as marker in order to
% delimit the argument of the command \texttt{\textbackslash @@\_begin\_line:}}.
%    \begin{macrocode}
    Ct ( 
         Cc "EOL"
         * 
         Ct (
              Lc "\\@@_end_line:"
              * BeamerEndEnvironments 
              * BeamerBeginEnvironments 
              * Lc "\\@@_newline: \\@@_begin_line:"
            )
       )
  ) 
  *
  SpaceIndentation ^ 0
%    \end{macrocode}
%
% 
%
% \bigskip
% \paragraph{The comments in the SQL listings}
%
% We define different \textsc{lpeg} dealing with comments in the SQL listings.
%    \begin{macrocode}
local CommentMath = 
  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$"

local Comment = 
  WithStyle ( 'Comment' ,
     Q ( P "--" )  -- syntax of SQL92
     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) 
  * ( EOL + -1 )

local LongComment = 
  WithStyle ( 'Comment' , 
               Q ( P "/*" ) 
               * ( CommentMath + Q ( ( 1 - P "*/" - S "$\r" ) ^ 1 ) + EOL ) ^ 0 
               * Q ( P "*/" ) 
            ) -- $
%    \end{macrocode}
%
%
% \bigskip
% The following \textsc{lpeg} |CommentLaTeX| is for what is called in that
% document the ``LaTeX comments''. Since the elements that will be catched must
% be sent to LaTeX with standard LaTeX catcodes, we put the capture (done by
% the function~|C|) in a table (by using~|Ct|, which is an alias for |lpeg.Ct|).
%    \begin{macrocode}
local CommentLaTeX =
  P(piton.comment_latex) 
  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" 
  * L ( ( 1 - P "\r" ) ^ 0 ) 
  * Lc "}}" 
  * ( EOL + -1 )  
%    \end{macrocode}
% 
%
%
% 
% \bigskip
% \paragraph{The main LPEG for the language SQL}
%
%
%    \begin{macrocode}
local function LuaKeyword ( name ) 
return 
   Lc ( "{\\PitonStyle{Keyword}{" )
   * Q ( Cmt ( 
               C ( identifier ) , 
               function(s,i,a) return string.upper(a) == name end 
             ) 
       ) 
   * Lc ( "}}" )
end 
%    \end{macrocode}
% 
%    \begin{macrocode}
local TableField = 
     K ( 'Name.Table' , identifier ) 
     * Q ( P "." ) 
     * K ( 'Name.Field' , identifier ) 

local OneField = 
  ( 
    Q ( P "(" * ( 1 - P ")" ) ^ 0 * P ")" )
    + 
    K ( 'Name.Table' , identifier ) 
      * Q ( P "." ) 
      * K ( 'Name.Field' , identifier ) 
    + 
    K ( 'Name.Field' , identifier ) 
  )
  * ( 
      Space * LuaKeyword ( "AS" ) * Space * K ( 'Name.Field' , identifier ) 
    ) ^ -1
  * ( Space * ( LuaKeyword ( "ASC" ) + LuaKeyword ( "DESC" ) ) ) ^ -1

local OneTable = 
     K ( 'Name.Table' , identifier ) 
   * ( 
       Space 
       * LuaKeyword ( "AS" ) 
       * Space 
       * K ( 'Name.Table' , identifier ) 
     ) ^ -1 

local WeCatchTableNames = 
     LuaKeyword ( "FROM" ) 
   * ( Space + EOL ) 
   * OneTable * ( SkipSpace * Q ( P "," ) * SkipSpace * OneTable ) ^ 0 
  + ( 
      LuaKeyword ( "JOIN" ) + LuaKeyword ( "INTO" ) + LuaKeyword ( "UPDATE" ) 
      + LuaKeyword ( "TABLE" ) 
    ) 
    * ( Space + EOL ) * OneTable 
%    \end{macrocode}
% 
%
% First, the main loop :
%    \begin{macrocode}
local MainSQL = 
       EOL
     + Space 
     + Tab
     + Escape + EscapeMath 
     + CommentLaTeX
     + Beamer
     + DetectedCommands
     + Comment + LongComment
     + Delim
     + Operator
     + String
     + Punct
     + WeCatchTableNames
     + ( TableField + Identifier ) * ( Space + Operator + Punct + Delim + EOL + -1 )  
     + Number
     + Word
%    \end{macrocode}
%
% Here, we must not put |local|!
%    \begin{macrocode}
MainLoopSQL = 
  (  ( space^1 * -1 ) 
     + MainSQL
  ) ^ 0 
%    \end{macrocode}
%
% \bigskip
% We recall that each line in the C code to parse will be sent back to
% LaTeX between a pair |\@@_begin_line:| -- |\@@_end_line:|\footnote{Remember
% that the \texttt{\textbackslash @@\_end\_line:} must be explicit because it
% will be used as marker in order to delimit the argument of the command
% \texttt{\textbackslash @@\_begin\_line:}}.
%    \begin{macrocode}
languageSQL =
  Ct (
       ( ( space - P "\r" ) ^ 0 * P "\r" ) ^ -1 
       * BeamerBeginEnvironments 
       * Lc '\\@@_begin_line:'
       * SpaceIndentation ^ 0 
       * MainLoopSQL
       * -1 
       * Lc '\\@@_end_line:' 
     )
%    \end{macrocode}
%
%    \begin{macrocode}
languages['sql'] = languageSQL
%    \end{macrocode}
% 
% \subsubsection{The LPEG language Minimal}
% 
%    \begin{macrocode}
local Punct = Q ( S ",:;!\\" )

local CommentMath = 
  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$"

local Comment = 
  WithStyle ( 'Comment' ,
     Q ( P "#" ) 
     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) 
  * ( EOL + -1 )


local String = 
  WithStyle ( 'String.Short' ,
      Q "\"" 
      * ( VisualSpace 
          + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 ) 
        ) ^ 0 
      * Q "\""
    )


local balanced_braces =
  P { "E" ,
       E = 
           (
             P "{" * V "E" * P "}" 
             + 
             String  
             + 
             ( 1 - S "{}" ) 
           ) ^ 0 
    }

if piton_beamer 
then
  Beamer =
      L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) 
    + 
      Ct ( Cc "Open" 
            * C ( 
                  ( 
                    P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
                    + P "\\invisible" + P "\\action" 
                  ) 
                  * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 
                  * P "{" 
                ) 
            * Cc "}" 
         ) 
       * ( balanced_braces / (function (s) return MainLoopMinimal:match(s) end ) )
       * P "}" * Ct ( Cc "Close" ) 
    + OneBeamerEnvironment ( "uncoverenv" , MainLoopMinimal ) 
    + OneBeamerEnvironment ( "onlyenv" , MainLoopMinimal ) 
    + OneBeamerEnvironment ( "visibleenv" , MainLoopMinimal )
    + OneBeamerEnvironment ( "invisibleenv" , MainLoopMinimal ) 
    + OneBeamerEnvironment ( "alertenv" , MainLoopMinimal ) 
    + OneBeamerEnvironment ( "actionenv" , MainLoopMinimal ) 
    +
      L ( 
          ( P "\\alt" )
          * P "<" * (1 - P ">") ^ 0 * P ">" 
          * P "{" 
        )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}" )
    +  
      L ( 
          ( P "\\temporal" )
          * P "<" * (1 - P ">") ^ 0 * P ">" 
          * P "{" 
        )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , balanced_braces ) 
      * L ( P "}" )
end

DetectedCommands = 
      Ct ( Cc "Open" 
            * C ( piton.ListCommands * P "{" ) * Cc "}" 
         ) 
       * ( balanced_braces / (function (s) return MainLoopMinimal:match(s) end ) )
       * P "}" * Ct ( Cc "Close" ) 


CleanLPEGs['minimal']
      = Ct ( ( piton.ListCommands * P "{" 
                * ( balanced_braces 
                    / ( function (s) return CleanLPEGs['minimal']:match(s) end ) )
                * P "}" 
               + EscapeClean
               +  C ( P ( 1 ) )
              ) ^ 0 ) / table.concat 



local EOL = 
  P "\r" 
  *
  (
    ( space^0 * -1 )
    + 
    Ct ( 
         Cc "EOL"
         * 
         Ct (
              Lc "\\@@_end_line:"
              * BeamerEndEnvironments 
              * BeamerBeginEnvironments 
              * Lc "\\@@_newline: \\@@_begin_line:"
            )
       )
  ) 
  *
  SpaceIndentation ^ 0

local CommentMath = 
  P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1  ) * P "$" -- $

local CommentLaTeX =
  P(piton.comment_latex) 
  * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" 
  * L ( ( 1 - P "\r" ) ^ 0 ) 
  * Lc "}}" 
  * ( EOL + -1 )  

local identifier = letter * alphanum ^ 0

local Identifier = K ( 'Identifier' , identifier )

local Delim = Q ( S "{[()]}" )

local MainMinimal = 
       EOL
     + Space 
     + Tab
     + Escape + EscapeMath 
     + CommentLaTeX
     + Beamer
     + DetectedCommands
     + Comment
     + Delim
     + String
     + Punct
     + Identifier 
     + Number
     + Word

MainLoopMinimal = 
  (  ( space^1 * -1 ) 
     + MainMinimal
  ) ^ 0 

languageMinimal =
  Ct (
       ( ( space - P "\r" ) ^ 0 * P "\r" ) ^ -1 
       * BeamerBeginEnvironments 
       * Lc '\\@@_begin_line:'
       * SpaceIndentation ^ 0 
       * MainLoopMinimal
       * -1 
       * Lc '\\@@_end_line:' 
     )
languages['minimal'] = languageMinimal

% \bigskip
% \subsubsection{The function Parse}
%
% \medskip
% The function |Parse| is the main function of the package \pkg{piton}. It
% parses its argument and sends back to LaTeX the code with interlaced
% formatting LaTeX instructions. In fact, everything is done by the
% \textsc{lpeg} corresponding to the considered language (|languages[language]|)
% which returns as capture a Lua table containing data to send to LaTeX.
% 
% \bigskip
%    \begin{macrocode}
function piton.Parse(language,code)
  local t = languages[language] : match ( code ) 
  if t == nil 
  then 
    tex.sprint("\\PitonSyntaxError")
    return -- to exit in force the function
  end 
  local left_stack = {}
  local right_stack = {}
  for _ , one_item in ipairs(t) 
  do 
     if one_item[1] == "EOL"
     then 
          for _ , s in ipairs(right_stack) 
            do tex.sprint(s) 
            end
          for _ , s in ipairs(one_item[2]) 
            do tex.tprint(s)
            end
          for _ , s in ipairs(left_stack) 
            do tex.sprint(s) 
            end
     else 
%    \end{macrocode}
%
% Here is an example of an item beginning with |"Open"|.
%
% |{ "Open" , "\begin{uncover}<2>" , "\end{cover}" }|
%
% In order to deal with the ends of lines, we have to close the environment
% (|{cover}| in this example) at the end of each line and reopen it at the
% beginning of the new line. That's why we use two Lua stacks, called
% |left_stack| and |right_stack|. |left_stack| will be for the elements like
% |\begin{uncover}<2>| and |right_stack| will be for the elements like
% |\end{cover}|. 
%    \begin{macrocode}
          if one_item[1] == "Open"
          then
               tex.sprint( one_item[2] ) 
               table.insert(left_stack,one_item[2])
               table.insert(right_stack,one_item[3])
          else 
               if one_item[1] == "Close"
               then
                    tex.sprint( right_stack[#right_stack] ) 
                    left_stack[#left_stack] = nil
                    right_stack[#right_stack] = nil
               else 
                    tex.tprint(one_item)  
               end 
          end 
     end 
  end 
end
%    \end{macrocode}
%
%    
%
% \bigskip
% The function |ParseFile| will be used by the LaTeX command |\PitonInputFile|.
% That function merely reads the whole file (that is to say all its lines) and
% then apply the function~|Parse| to the resulting Lua string.
%    \begin{macrocode}
function piton.ParseFile(language,name,first_line,last_line)
  local s = ''
  local i = 0 
  for line in io.lines(name) 
  do i = i + 1 
     if i >= first_line
     then s = s .. '\r' .. line 
     end
     if i >= last_line then break end 
  end
%    \end{macrocode}
% We extract the BOM of utf-8, if present.
%    \begin{macrocode}
  if string.byte(s,1) == 13
  then if string.byte(s,2) == 239
       then if string.byte(s,3) == 187
            then if string.byte(s,4) == 191
                 then s = string.sub(s,5,-1)
                 end 
            end
       end
  end
  piton.Parse(language,s)
end
%    \end{macrocode}
% 
% \bigskip
% \subsubsection{Two variants of  the function Parse with integrated preprocessors}
%
% The following command will be used by the user command |\piton|.
% For that command, we have to undo the duplication of the symbols |#|.
%    \begin{macrocode}
function piton.ParseBis(language,code)
  local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( code )
  return piton.Parse(language,s) 
end
%    \end{macrocode}
%
% \bigskip
% The following command will be used when we have to parse some small chunks of
% code that have yet been parsed. They are re-scanned by LaTeX because it has
% been required by |\@@_piton:n| in the \pkg{piton} style of the syntaxic
% element. In that case, you have to remove the potential |\@@_breakable_space:|
% that have been inserted when the key |break-lines| is in force.
%    \begin{macrocode}
function piton.ParseTer(language,code)
  local s = ( Cs ( ( P '\\@@_breakable_space:' / ' ' + 1 ) ^ 0 ) ) 
            : match ( code )
  return piton.Parse(language,s)
end
%    \end{macrocode}
% 
%
% \bigskip
% \subsubsection{Preprocessors of the function Parse for gobble}
%
% We deal now with preprocessors of the function |Parse| which are needed when
% the ``gobble mechanism'' is used.
% 
%
% \bigskip
% The function |gobble| gobbles $n$ characters on the left of the code. It uses
% a \textsc{lpeg} that we have to compute dynamically because if depends on the
% value of~$n$.
%    \begin{macrocode}
local function gobble(n,code)
  if n==0 
  then return code
  else 
       return ( Ct ( 
                     ( 1 - P "\r" ) ^ (-n)  * C ( ( 1 - P "\r" ) ^ 0 ) 
                       * ( C ( P "\r" )
                       * ( 1 - P "\r" ) ^ (-n)
                       * C ( ( 1 - P "\r" ) ^ 0 )
                      ) ^ 0 
                   ) / table.concat ) : match ( code ) 
  end
end
%    \end{macrocode}
%
% 
% 
% \bigskip
% The following function |sum| will be used in the following \textsc{lpeg}
% |AutoGobbleLPEG|, |TabsAutoGobbleLPEG| and |EnvGobbleLPEG|. It computes the
% sum of all its arguments.
%    \begin{macrocode}
local function count_captures(...)
    local acc = 0
    for _ in ipairs({...}) do
        acc = acc + 1
    end
    return acc
end
%    \end{macrocode}
% 
% \bigskip
% The following \textsc{lpeg} returns as capture the minimal number of spaces at
% the beginning of the lines of code. 
%    begin{macrocode}
%    \begin{macrocode}
local AutoGobbleLPEG = 
  (
    (
%    \end{macrocode}
% We don't take into account the empty lines (those containing only spaces).
%    \begin{macrocode}
      P " " ^ 0 * P "\r"
      + 
      C ( P " " ) ^ 0 / count_captures * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 * P "\r"
    ) ^ 0
%    \end{macrocode}
% Now for the last line of the Python code...
%    \begin{macrocode}
    *
    ( C ( P " " ) ^ 0 / count_captures * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 
  ) / math.min
%    \end{macrocode}
%
% \bigskip
% The following \textsc{lpeg} is similar but works with the indentations.
%    \begin{macrocode}
local TabsAutoGobbleLPEG = 
  (
    (
      P "\t" ^ 0 * P "\r"
      + 
      C ( P " " ) ^ 0 / count_captures * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 * P "\r"
    ) ^ 0
    *
    ( C ( P " " ) ^ 0 / count_captures * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 
  ) / math.min
%    \end{macrocode}
% 
%
%
% \bigskip
% The following \textsc{lpeg} returns as capture the number of spaces at the
% last line, that is to say before the |\end{Piton}| (and usually it's also the
% number of spaces before the corresponding |\begin{Piton}| because that's the
% traditionnal way to indent in LaTeX). 
%    \begin{macrocode}
local EnvGobbleLPEG =
  ( ( 1 - P "\r" ) ^ 0 * P "\r" ) ^ 0 * ( C ( P " " )  ^ 0 / count_captures ) * -1
%    \end{macrocode}
% 
% \bigskip
%    \begin{macrocode}
local function remove_before_cr(input_string)
    local match_result = P("\r") : match(input_string)
    if match_result then
        return string.sub(input_string, match_result ) 
    else
        return input_string 
    end
end
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
function piton.GobbleParse(language,n,code)
  code = remove_before_cr(code)
  if n==-1 
  then n = AutoGobbleLPEG : match(code)
  else if n==-2 
       then n = EnvGobbleLPEG : match(code)
       else if n==-3
            then n = TabsAutoGobbleLPEG : match(code)
            end
       end
  end
  piton.last_code = gobble(n,code)
  piton.Parse(language,piton.last_code)
  piton.last_language = language
%    \end{macrocode}
% Now, if the final user has used the key |write| to write the code of the
% environment on an external file.
%    \begin{macrocode}
  if piton.write ~= ''
  then local file = assert(io.open(piton.write,piton.write_mode))
       file:write(piton.get_last_code()) 
       file:close()
  end
end 
%    \end{macrocode}
%
% \bigskip
% The following Lua function is provided to the developper. 
%    \begin{macrocode}
function piton.get_last_code ( ) 
  return CleanLPEGs[piton.last_language] : match(piton.last_code) 
end
%    \end{macrocode}
% 
% 
% \bigskip
% \subsubsection{To count the number of lines}
%
% \medskip
%    \begin{macrocode}
function piton.CountLines(code)
  local count = 0 
  for i in code : gmatch ( "\r" ) do count = count + 1 end 
  tex.sprint( 
      luatexbase.catcodetables.expl , 
      '\\int_set:Nn \\l_@@_nb_lines_int {' .. count .. '}' )
end 
%    \end{macrocode}
%
%    \begin{macrocode}
function piton.CountNonEmptyLines(code)
  local count = 0 
  count = 
  (  (  (  ( 
            ( P " " ) ^ 0 * P "\r"  
              + ( 1 - P "\r" ) ^ 0 * C ( P "\r" ) 
            ) ^ 0 
          * (1 - P "\r" ) ^ 0 
       ) / count_captures ) * -1 ) : match (code) 
  tex.sprint( 
      luatexbase.catcodetables.expl , 
      '\\int_set:Nn \\l_@@_nb_non_empty_lines_int {' .. count .. '}' )
end 
%    \end{macrocode}
%
% \bigskip
%    \begin{macrocode}
function piton.CountLinesFile(name)
  local count = 0 
  io.open(name) 
  for line in io.lines(name) do count = count + 1 end
  tex.sprint( 
      luatexbase.catcodetables.expl , 
      '\\int_set:Nn \\l_@@_nb_lines_int {' .. count .. '}' )
end 
%    \end{macrocode}
%
%
% \bigskip
%    \begin{macrocode}
function piton.CountNonEmptyLinesFile(name)
  local count = 0 
  for line in io.lines(name) 
  do if not ( ( ( P " " ) ^ 0 * -1 ) : match ( line ) ) 
     then count = count + 1 
     end
  end
  tex.sprint( 
      luatexbase.catcodetables.expl , 
      '\\int_set:Nn \\l_@@_nb_non_empty_lines_int {' .. count .. '}' )
end 
%    \end{macrocode}
%
% 
% \bigskip
% The following function stores in |\l_@@_first_line_int| and
% |\l_@@_last_line_int| the numbers of lines of the file |file_name|
% corresponding to the strings |marker_beginning| and |marker_end|.
%    \begin{macrocode}
function piton.ComputeRange(marker_beginning,marker_end,file_name)
  local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( marker_beginning )
  local t = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( marker_end )
  local first_line = -1
  local count = 0
  local last_found = false
  for line in io.lines(file_name)
  do if first_line == -1
     then if string.sub(line,1,#s) == s 
          then first_line = count 
          end 
     else if string.sub(line,1,#t) == t
          then last_found = true 
               break 
          end 
     end 
     count = count + 1 
  end
  if first_line == -1 
  then tex.sprint("\\PitonBeginMarkerNotFound")
  else if last_found == false
       then tex.sprint("\\PitonEndMarkerNotFound")
       end
  end
  tex.sprint( 
      luatexbase.catcodetables.expl , 
      '\\int_set:Nn \\l_@@_first_line_int {' .. first_line .. ' + 2 }' 
      .. '\\int_set:Nn \\l_@@_last_line_int {' .. count .. ' }' )
end
%</LUA>
%    \end{macrocode}
% 
%
% 
% \vspace{1cm}
% \section{History}
%
% The successive versions of the file |piton.sty| provided by TeXLive are available on the
% \textsc{svn} server of TeXLive:\par\nobreak
%
% \smallskip
% {
% \small
% \nolinkurl{https://tug.org/svn/texlive/trunk/Master/texmf-dist/tex/lualatex/piton/piton.sty}
% }
%
% \medskip
% The development of the extension \pkg{piton} is done on the following GitHub
% repository:
%
% \verb|https://github.com/fpantigny/piton|
%
% \subsection*{Changes between versions 2.5 and 2.6}
%
% API: |piton.last_code| and |\g_piton_last_code_tl| are provided.
%
% \subsection*{Changes between versions 2.4 and 2.5}
%
% New key |path-write|
%
% \subsection*{Changes between versions 2.3 and 2.4}
%
% The key |identifiers| of the command |\PitonOptions| is now deprecated and
% replaced by the new command |\SetPitonIdentifier|.
%
% A new special language called ``minimal'' has been added.
%
% New key |detected-commands|.
%
% \subsection*{Changes between versions 2.2 and 2.3}
%
% New key |detected-commands|
% 
% The variable |\l_piton_language_str| is now public.
% 
%
% New key |write|.
% 
% \subsection*{Changes between versions 2.1 and 2.2}
%
% New key |path| for |\PitonOptions|.
%
% New language SQL.
%
% It's now possible to define styles locally to a given language (with the
% optional argument of |\SetPitonStyle|). 
%
% \subsection*{Changes between versions 2.0 and 2.1}
%
% The key |line-numbers| has now subkeys |line-numbers/skip-empty-lines|,
% |line-numbers/label-empty-lines|, etc. 
%
% The key |all-line-numbers| is deprecated: use
% |line-numbers/skip-empty-lines=false|. 
%
% New system to import, with |\PitonInputFile|, only a part (of the file)
% delimited by textual markers. 
%
% New keys |begin-escape|, |end-escape|, |begin-escape-math| and |end-escape-math|.
%
% The key |escape-inside| is deprecated: use |begin-escape| and |end-escape|.
%
%
% \subsection*{Changes between versions 1.6 and 2.0}
%
% The extension \pkg{piton} nows supports the computer languages OCaml and C
% (and, of course, Python).
%
% \subsection*{Changes between versions 1.5 and 1.6}
%
% New key |width| (for the total width of the listing).
%
% New style |UserFunction| to format the names of the Python functions
% previously defined by the user. Command |\PitonClearUserFunctions| to clear
% the list of such functions names.
%
% \subsection*{Changes between versions 1.4 and 1.5}
%
% New key |numbers-sep|.
%
%
% \subsection*{Changes between versions 1.3 and 1.4}
%
% New key |identifiers| in |\PitonOptions|.
%
% New command |\PitonStyle|.
%
% |background-color| now accepts as value a \emph{list} of colors.
%
% \subsection*{Changes between versions 1.2 and 1.3}
%
% When the class Beamer is used, the environment |{Piton}| and the command 
% |\PitonInputFile| are ``overlay-aware'' (that is to say, they accept a
% specification of overlays between angular brackets).
%
% New key |prompt-background-color|
%
% It's now possible to use the command |\label| to reference a line of code in
% an environment |{Piton}|.
%
% A new command |\|␣ is available in the argument of the command |\piton{...}| to
% insert a space (otherwise, several spaces are replaced by a single space).
% 
% \subsection*{Changes between versions 1.1 and 1.2}
%
% New keys |break-lines-in-piton| and |break-lines-in-Piton|.
% 
% New key |show-spaces-in-string| and modification of the key |show-spaces|.
%
% When the class \cls{beamer} is used, the environements |{uncoverenv}|,
% |{onlyenv}|, |{visibleenv}| and |{invisibleenv}|
%
%
% \subsection*{Changes between versions 1.0 and 1.1}
%
% The extension \pkg{piton} detects the class \cls{beamer} and activates the
% commands |\action|, |\alert|, |\invisible|, |\only|, |\uncover| and |\visible|
% in the environments |{Piton}| when the class \cls{beamer} is used.
%
% \subsection*{Changes between versions 0.99 and 1.0}
%
% New key |tabs-auto-gobble|.
% 
% \subsection*{Changes between versions 0.95 and 0.99}
%
% New key |break-lines| to allow breaks of the lines of code (and other keys to
% customize the appearance).
%
% \subsection*{Changes between versions 0.9 and 0.95}
%
% New key |show-spaces|.
%
% The key |left-margin| now accepts the special value |auto|.
%
% New key |latex-comment| at load-time and replacement of |##| by |#>|
%
% New key |math-comments| at load-time.
%
% New keys |first-line| and |last-line| for the command |\InputPitonFile|.
%
% \subsection*{Changes between versions 0.8 and 0.9}
%
% New key |tab-size|.
%
% Integer value for the key |splittable|.
%
% \subsection*{Changes between versions 0.7 and 0.8}
% 
% New keys |footnote| and |footnotehyper| at load-time.
%
% New key |left-margin|.
% 
% \subsection*{Changes between versions 0.6 and 0.7}
% 
% New keys |resume|, |splittable| and |background-color| in |\PitonOptions|.
%
% The file |piton.lua| has been embedded in the file |piton.sty|. That means
% that the extension \pkg{piton} is now entirely contained in the file |piton.sty|.
% 
%
%
% \tableofcontents
%
% \end{document}
% 
%
% Local Variables:
% TeX-fold-mode: t
% TeX-fold-preserve-comments: nil
% flyspell-mode: nil
% fill-column: 80
% End:






