From 7ffc72f568b89a4914168cd6921510d226a48620 Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Thu, 10 Nov 2022 03:01:41 +0000
Subject: CTAN sync 202211100301

---
 macros/luatex/latex/piton/piton.dtx | 909 ++++++++++++++++++++++++++----------
 1 file changed, 659 insertions(+), 250 deletions(-)

(limited to 'macros/luatex/latex/piton/piton.dtx')

diff --git a/macros/luatex/latex/piton/piton.dtx b/macros/luatex/latex/piton/piton.dtx
index c381b9eb27..6bce058842 100644
--- a/macros/luatex/latex/piton/piton.dtx
+++ b/macros/luatex/latex/piton/piton.dtx
@@ -15,8 +15,8 @@
 %
 % \fi
 % \iffalse
-\def\myfileversion{0.9}
-\def\myfiledate{2022/10/31}
+\def\myfileversion{0.95}
+\def\myfiledate{2022/11/09}
 %
 %
 %<*batchfile> 
@@ -56,10 +56,8 @@ version 2005/12/01 or later.
 \fvset{commandchars=\~\#\@,formatcom=\color{gray}}
 \captionsetup{labelfont = bf}
 \usepackage{ragged2e}
-\usepackage[footnotehyper,escape-inside=$$]{piton} % $$
+\usepackage[footnotehyper,escape-inside=$$,math-comments]{piton} % $$
 
-
-\def\interitem{\vskip 7mm plus 2 mm minus 3mm}          
 \parindent 0pt
 \skip\footins = 2\bigskipamount
 
@@ -118,7 +116,7 @@ version 2005/12/01 or later.
 %         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\#\#.}
+%         #> (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):
@@ -166,13 +164,12 @@ version 2005/12/01 or later.
 % cf.~\ref{NewPitonEnvironment} p.~\pageref{NewPitonEnvironment}.
 % \item The command |\PitonInputFile| is used to insert and typeset a whole
 % external file.
+%
+% \colorbox{yellow!50}{\textbf{New 0.95}}\enskip The command |\PitonInputFile|
+% takes in as optional argument (between square brackets) two keys |first-line|
+% and |last-line|: only the part between the corresponding lines will be inserted.
 % \end{itemize}
 %
-% \bigskip
-% It's possible to compose comments in LaTeX by beginning them with |##| (it's a
-% ``LaTeX escape''). The characters |##| themselves won't be printed and the
-% spaces after |##| are removed. These comments will be called ``LaTeX
-% comments'' in this document.
 % 
 % \section{Customization}
 %
@@ -203,35 +200,40 @@ version 2005/12/01 or later.
 % gobble is set by the position of the commands |\begin{Piton}| and
 % |\end{Piton}| which delimit the current environment.
 %
-% \item With the key |line-numbers|, the \emph{non empty} lines are numbered (on
-% the left) in the environments |{Piton}| and in the listings resulting from the
-% use of |\PitonInputFile|.
+% \item With the key |line-numbers|, the \emph{non empty} lines (and all the
+% lines of the \emph{docstrings}, even the empty ones) are numbered in the
+% environments |{Piton}| and in the listings resulting from the use of
+% |\PitonInputFile|.
 % 
 % \item With the key |all-line-numbers|, \emph{all} the lines are numbered,
 % including the empty ones.
 %
 % \item With the key |resume| the counter of lines is not set to zero at the
-% beginning of each environment |{Piton}| or use |\PitonInputFile| as it is
-% otherwise. That's allows a numbering of the lines accross several
-% environments. See an example part \ref{example-numbering} on
-% page~\pageref{example-numbering}.
+% 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 |left-margin| corresponds to a margin on the left. That key may
 % be useful in conjonction with the key |line-numbers| or the key
 % |line-all-numbers| if one does not want the numbers in an overlapping position
-% on the left.
+% on the left. 
+%
+% \colorbox{yellow!50}{\textbf{New 0.95}}\enskip It's possible to use the key
+% |left-margin| with the value |auto|. With that value, if the key
+% |line-numbers| or the key |all-line-numbers| is used, 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 The key |splittable| allows pages breaks within the environments
+% \item The key |splittable| allows page breaks within the environments
 % |{Piton}| and the listings produced by 
 % |\PitonInputFile|. 
 %
 % \smallskip
-% \colorbox{yellow!50}{\textbf{New 0.9}}\enskip It's possible to give as value to
-% the key |splittable| a positive integer~$n$. With that value, the environments
-% |{Piton}| and the listings produced by |\PitonInputFile| are splittable but no
-% page break can occur within the first $n$ lines and within the last $n$ lines.
-% The default value of the key |splittable| is, in fact, $1$, which allows pages
-% breaks everywhere.
+% It's possible to give as value to the key |splittable| a positive integer~$n$.
+% With that value, the environments |{Piton}| and the listings produced by
+% |\PitonInputFile| are splittable but no page break can occur within the first
+% $n$ lines and within the last $n$ lines. The default value of the key
+% |splittable| is, in fact, $1$, which allows pages breaks everywhere.
 %
 % \item The key |background-color| sets the background color of the environments
 % |{Piton}| and the listings produced by |\PitonInputFile| (that background has
@@ -242,6 +244,19 @@ version 2005/12/01 or later.
 % \pkg{tcolorbox} included in another environment of \pkg{tcolorbox} is
 % \emph{not} breakable, even when both environments use the key |breakable| of
 % \pkg{tcolorbox}.}
+%
+% \item \colorbox{yellow!50}{\textbf{New 0.95}}\enskip When the key
+% |show-spaces| is activated, the spaces in the short strings (that is to say
+% those delimited by |'| or |"|) 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 \pkg{fontspec}.}
+%
+% \begingroup
+% \PitonOptions{show-spaces}
+% Example : \piton|my_string = 'Very good answer'|
+% \endgroup
 % \end{itemize}
 %
 % \bigskip
@@ -261,7 +276,7 @@ version 2005/12/01 or later.
 %             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}$ pour $x>0$)
+%             #> (we have used that $\arctan(x)+\arctan(1/x)=\frac{\pi}{2}$ pour $x>0$)
 %         else 
 %             s = 0
 %             for k in range(n):
@@ -285,7 +300,7 @@ version 2005/12/01 or later.
 %         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$)
+%         #> (we have used that $\arctan(x)+\arctan(1/x)=\frac{\pi}{2}$ for $x>0$)
 %     else 
 %         s = 0
 %         for k in range(n):
@@ -294,51 +309,6 @@ version 2005/12/01 or later.
 %    \end{Piton}
 % \endgroup
 % 
-% \subsection{The key escape-inside}
-%
-% The key |escape-inside| must be used when loading the package \pkg{piton}
-% (that is to say in the instruction |\usepackage|). For technical reasons, it
-% can't be used in the command |\PitonOptions|. That option takes in as value
-% two characters which will be used to delimit pieces of code which will
-% thrown directly to LaTeX (and composed by LaTeX).
-%
-% \medskip
-% In the following example, we assume that the extension \pkg{piton} has been
-% loaded by the following instruction.
-%
-% \begin{Verbatim}
-% \usepackage[~emphase#escape-inside=$$@]{piton}
-% \end{Verbatim}
-%
-% \medskip
-% In the following code, which is a recursive programmation of the mathematical
-% factorial, we decide to highlight in yellow the instruction which contains the
-% recursive call. 
-% \begin{Verbatim}
-% \begin{Piton}
-% def fact(n):
-%     if n==0:
-%         return 1
-%     else:
-%         ~emphase#$\colorbox{yellow!50}{$@return n*fact(n-1)~emphase#$}$@
-% \end{Piton}
-% \end{Verbatim}
-%
-%    \begin{Piton}
-% def fact(n):
-%     if n==0:
-%         return 1
-%     else:
-%         $\colorbox{yellow!50}{$return n*fact(n-1)$}$
-%    \end{Piton}
-%         
-% \bigskip
-%
-% \emph{Caution} : The escape to LaTeX allowed by the characters of
-% |escape-inside| is not active in the strings nor in the Python comments
-% (however, it's possible to have a whole Python comment composed in LaTeX by
-% beginning it with |##|; such comments are merely called ``LaTeX comments'' in
-% this document). 
 %
 %
 % \subsection{The styles}
@@ -420,7 +390,7 @@ version 2005/12/01 or later.
 % to say after the keyword |class|) \\
 % Exception & the names of the exceptions (eg: \texttt{SyntaxError}) \\
 % Comment & the comments beginning with \verb|#| \\
-% Comment.LaTeX & the comments beginning by \verb|##|, which are composed in LaTeX by
+% Comment.LaTeX & the comments beginning by \verb|#>|, which are composed in LaTeX by
 % \pkg{piton} (and simply called ``LaTeX comments'' in this document) \\
 % Keyword.Constant & |True|, |False| and |None| \\
 % Keyword & the following keywords :
@@ -477,6 +447,125 @@ version 2005/12/01 or later.
 %
 % \section{Advanced features}
 %
+% \subsection{Mechanisms to escape 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 also possible to insert LaTeX code almost everywhere in a Python listing.
+% \end{itemize}
+%
+% \subsubsection{The ``LaTeX comments''}
+%
+% 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 at load-time (that
+% is to say at the |\usepackage|) which allows to choice the characters which,
+% preceded by |#|, will be the syntatic marker.
+%
+% For example, with the following loading:
+% 
+% \quad \verb|\usepackage[comment-latex = LaTeX]{piton}|
+%
+% 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 \colorbox{yellow!50}{\bfseries New 0.95}\enskip 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.
+%
+% For other examples of customization of the LaTeX comments, see the part
+% \ref{example-comments} p.~\pageref{example-comments}
+% \end{itemize}
+%
+% \subsubsection{The key ``math-comments''}
+%
+% \colorbox{yellow!50}{\textbf{New 0.95}}\enskip 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 |math-comments| at load-time (that is to
+% say with the |\usepackage|).
+%
+% \medskip
+% In the following example, we assume that the key |math-comments| has been used
+% when loading \pkg{piton}.
+%
+% \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 mechanism ``escape-inside''}
+%
+% It's also possible to overwrite the Python listings to insert LaTeX code
+% almost everywhere. By default, \pkg{piton} does not fix any character for that
+% kind of escape.
+%
+% In order to use this mechanism, it's necessary to specify two characters which
+% will delimit the escape (one for the beginning and one for the end) by using
+% the key |escape-inside| at load-time (that is to say a the
+% |\begin{docuemnt}|). 
+%
+% \medskip
+% In the following example, we assume that the extension \pkg{piton} has been
+% loaded by the following instruction.
+%
+% \begin{Verbatim}
+% \usepackage[~emphase#escape-inside=$$@]{piton}
+% \end{Verbatim}
+%
+% \medskip
+% In the following code, which is a recursive programmation of the mathematical
+% factorial, we decide to highlight in yellow the instruction which contains the
+% recursive call. 
+% \begin{Verbatim}
+% \begin{Piton}
+% def fact(n):
+%     if n==0:
+%         return 1
+%     else:
+%         ~emphase#$\colorbox{yellow!50}{$@return n*fact(n-1)~emphase#$}$@
+% \end{Piton}
+% \end{Verbatim}
+%
+%    \begin{Piton}
+% def fact(n):
+%     if n==0:
+%         return 1
+%     else:
+%         $\colorbox{yellow!50}{$return n*fact(n-1)$}$
+%    \end{Piton}
+%         
+% \bigskip
+%
+% \emph{Caution} : The escape to LaTeX allowed by the characters of
+% |escape-inside| is not active in the strings nor in the Python comments
+% (however, it's possible to have a whole Python comment composed in LaTeX by
+% beginning it with |#>|; such comments are merely called ``LaTeX comments'' in
+% this document). 
+% 
 % \subsection{Footnotes in the environments of piton}
 % 
 % \label{footnote}
@@ -514,12 +603,16 @@ version 2005/12/01 or later.
 % \subsection{Tabulations}
 %
 % \smallskip 
-% \colorbox{yellow!50}{\textbf{New 0.9}}\enskip 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|.
+% 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
+% \emph{Remark}: Unlike with the package \pkg{listings}, the key |gobble| and
+% its variants (|auto-gobble| and |env-gobble|) are applied \emph{before} the
+% transformation of the characters of tabulation in spaces.
 %
 % \section{Examples}
 %
@@ -533,21 +626,21 @@ version 2005/12/01 or later.
 % 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 necessary to reserve a place for the
-% number of the lines with the key |left-margin|.
-%
+% 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 = 5mm, line-numbers}@
+% ~emphase&\PitonOptions{background-color=gray!10, left-margin = auto, line-numbers}@
 % \begin{Piton}
 % def arctan(x,n=10):
 %     if x < 0:
-%         return -arctan(-x)        ## (appel récursif)
+%         return -arctan(-x)        #> (appel récursif)
 %     elif x > 1: 
-%         return pi/2 - arctan(1/x) ## (autre appel récursif) 
+%         return pi/2 - arctan(1/x) #> (autre appel récursif) 
 %     else: 
 %         return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) 
 % \end{Piton}
@@ -557,13 +650,13 @@ version 2005/12/01 or later.
 %
 %
 % \begingroup
-% \PitonOptions{background-color=gray!10,left-margin = 5mm, line-numbers}
+% \PitonOptions{background-color=gray!10,left-margin = auto, line-numbers}
 % \begin{Piton}
 % def arctan(x,n=10):
 %     if x < 0:
-%         return -arctan(-x)        ## (appel récursif)
+%         return -arctan(-x)        #> (appel récursif)
 %     elif x > 1: 
-%         return pi/2 - arctan(1/x) ## (autre appel récursif) 
+%         return pi/2 - arctan(1/x) #> (autre appel récursif) 
 %     else: 
 %         return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) 
 % \end{Piton}
@@ -571,11 +664,13 @@ version 2005/12/01 or later.
 %
 %
 %
-%
+% \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
+% order to display the LaTeX comments (which begin with |#>|) aligned on the
 % right margin.
 %
 %
@@ -587,9 +682,9 @@ version 2005/12/01 or later.
 % \begin{Piton}
 % def arctan(x,n=10):
 %     if x < 0:
-%         return -arctan(-x)        ## appel récursif
+%         return -arctan(-x)        #> appel récursif
 %     elif x > 1: 
-%         return pi/2 - arctan(1/x) ## autre appel récursif 
+%         return pi/2 - arctan(1/x) #> autre appel récursif 
 %     else: 
 %         return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) 
 % \end{Piton}
@@ -602,9 +697,9 @@ version 2005/12/01 or later.
 % \begin{Piton}
 % def arctan(x,n=10):
 %     if x < 0:
-%         return -arctan(-x)        ## appel récursif
+%         return -arctan(-x)        #> appel récursif
 %     elif x > 1: 
-%         return pi/2 - arctan(1/x) ## autre appel récursif 
+%         return pi/2 - arctan(1/x) #> autre appel récursif 
 %     else: 
 %         return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) 
 % \end{Piton}
@@ -626,9 +721,9 @@ version 2005/12/01 or later.
 % \begin{Piton}
 % def arctan(x,n=10):
 %     if x < 0:
-%         return -arctan(-x)       ## appel récursif
+%         return -arctan(-x)       #> appel récursif
 %     elif x > 1: 
-%         return pi/2 - arctan(1/x) ## autre appel récursif 
+%         return pi/2 - arctan(1/x) #> autre appel récursif 
 %     else: 
 %         s = 0
 %         for k in range(n):
@@ -649,9 +744,9 @@ version 2005/12/01 or later.
 % \begin{Piton}
 % def arctan(x,n=10):
 %     if x < 0:
-%         return -arctan(-x)       ## appel récursif
+%         return -arctan(-x)       #> appel récursif
 %     elif x > 1: 
-%         return pi/2 - arctan(1/x) ## autre appel récursif 
+%         return pi/2 - arctan(1/x) #> autre appel récursif 
 %     else: 
 %         s = 0
 %         for k in range(n):
@@ -662,7 +757,7 @@ version 2005/12/01 or later.
 % \endgroup
 %
 %
-%
+% \bigskip
 % \subsection{Notes in the listings}
 %
 % \label{notes-examples}
@@ -674,7 +769,7 @@ version 2005/12/01 or later.
 % 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
+% 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.
 %
 %
@@ -686,9 +781,9 @@ version 2005/12/01 or later.
 % \begin{Piton}
 % def arctan(x,n=10):
 %     if x < 0:
-%         return -arctan(-x)~emphase&##\footnote{First recursive call.}]@
+%         return -arctan(-x)~emphase&#>\footnote{First recursive call.}]@
 %     elif x > 1: 
-%         return pi/2 - arctan(1/x)~emphase&##\footnote{Second recursive call.}@
+%         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}
@@ -700,9 +795,9 @@ version 2005/12/01 or later.
 % \begin{Piton}
 % def arctan(x,n=10):
 %     if x < 0:
-%         return -arctan(-x)##\footnote{First recursive call.}
+%         return -arctan(-x)#>\footnote{First recursive call.}
 %     elif x > 1: 
-%         return pi/2 - arctan(1/x)##\footnote{Second recursive call.}
+%         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}
@@ -724,9 +819,9 @@ version 2005/12/01 or later.
 % \begin{Piton}
 % def arctan(x,n=10):
 %     if x < 0:
-%         return -arctan(-x)~emphase&##\footnote{First recursive call.}@
+%         return -arctan(-x)~emphase&#>\footnote{First recursive call.}@
 %     elif x > 1: 
-%         return pi/2 - arctan(1/x)~emphase&##\footnote{Second recursive call.}@
+%         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}
@@ -740,9 +835,9 @@ version 2005/12/01 or later.
 % \begin{Piton}
 % def arctan(x,n=10):
 %     if x < 0:
-%         return -arctan(-x)##\footnote{First recursive call.}
+%         return -arctan(-x)#>\footnote{First recursive call.}
 %     elif x > 1: 
-%         return pi/2 - arctan(1/x)##\footnote{Second recursive call.}
+%         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}
@@ -766,9 +861,9 @@ version 2005/12/01 or later.
 % \begin{Piton}
 % def arctan(x,n=10):
 %     if x < 0:
-%         return -arctan(-x)~emphase&##\footnote{First recursive call.}@
+%         return -arctan(-x)~emphase&#>\footnote{First recursive call.}@
 %     elif x > 1: 
-%         return pi/2 - arctan(1/x)~emphase&##\footnote{Second recursive call.}@
+%         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}
@@ -785,15 +880,16 @@ version 2005/12/01 or later.
 % \begin{Piton}
 % def arctan(x,n=10):
 %     if x < 0:
-%         return -arctan(-x)##\footnote{First recursive call.}
+%         return -arctan(-x)#>\footnote{First recursive call.}
 %     elif x > 1: 
-%         return pi/2 - arctan(1/x)##\footnote{Second recursive call.}
+%         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}
 % \end{savenotes}
 %
+% \bigskip
 %
 % \subsection{An example of tuning of the styles}
 %
@@ -869,7 +965,7 @@ version 2005/12/01 or later.
 %         return -arctan(-x) # appel récursif
 %     elif x > 1: 
 %         return pi/2 - arctan(1/x) 
-%         ## (we have used that $\arctan(x)+\arctan(1/x)=\pi/2$ for $x>0$)
+%         #> (we have used that $\arctan(x)+\arctan(1/x)=\pi/2$ for $x>0$)
 %     else: 
 %         s = 0
 %         for k in range(n):
@@ -879,6 +975,66 @@ version 2005/12/01 or later.
 %
 % \endgroup
 % 
+% \subsection{Use with 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 display also the output of the execution of the
+% code with Python. 
+%
+%
+% \begin{Verbatim}
+% \ExplSyntaxOn
+% \NewDocumentEnvironment { ~emphase#PitonExecute@ } { ! O { } } 
+%   { 
+%     \PyLTVerbatimEnv
+%     \begin{pythonq} 
+%   }
+%   {
+%     \end{pythonq}
+%     \directlua
+%       {
+%         tex.print("\\PitonOptions{~#1}")
+%         tex.print("\\begin{Piton}")
+%         tex.print(pyluatex.get_last_code())
+%         tex.print("\\end{Piton}")
+%         tex.print("") 
+%       }
+%     \begin{center}
+%       \directlua{tex.print(pyluatex.get_last_output())}
+%     \end{center}
+%   }
+% \ExplSyntaxOff
+% \end{Verbatim}
+%
+% \ExplSyntaxOn
+% \NewDocumentEnvironment { PitonExecute } { ! O { } } 
+%   { 
+%     \PyLTVerbatimEnv
+%     \begin{pythonq} 
+%   }
+%   {
+%     \end{pythonq}
+%     \directlua
+%       {
+%         tex.print("\\PitonOptions{~#1}")
+%         tex.print("\\begin{Piton}")
+%         tex.print(pyluatex.get_last_code())
+%         tex.print("\\end{Piton}")
+%         tex.print("") 
+%       }
+%     \begin{center}
+%       \directlua{tex.print(pyluatex.get_last_output())}
+%     \end{center}
+%   }
+% \ExplSyntaxOff
+%
+% This environment |{PitonExecute}| takes in as optional argument (between
+% square brackets) the options of the command |\PitonOptions|.
+%
 %
 % \bigskip
 % \clearpage
@@ -1048,6 +1204,12 @@ version 2005/12/01 or later.
 %    \begin{macrocode}
 \bool_new:N \c_@@_footnote_bool
 %    \end{macrocode}
+%
+% \medskip
+% The following boolean corresponds to the key |math-comments| (only at load-time).
+%    \begin{macrocode}
+\bool_new:N \c_@@_math_comments_bool
+%    \end{macrocode}
 % 
 % \bigskip
 % We define a set of keys for the options at load-time.
@@ -1058,6 +1220,10 @@ version 2005/12/01 or later.
     footnotehyper .bool_set:N = \c_@@_footnotehyper_bool ,
     escape-inside .tl_set:N = \c_@@_escape_inside_tl ,
     escape-inside .initial:n = , 
+    comment-latex .code:n = { \lua_now:n { comment_latex = "#1" } } ,   
+    comment-latex .value_required:n = true ,
+    math-comments .bool_set:N = \c_@@_math_comments_bool ,
+    math-comments .default:n  = true , 
     unknown .code:n = \msg_error:nn { piton } { unknown~key~for~package }
   }
 %    \end{macrocode}
@@ -1067,12 +1233,12 @@ version 2005/12/01 or later.
   {
     Unknown~key.\\
     You~have~used~the~key~'\l_keys_key_str'~but~the~only~keys~available~here~
-    are~'escape-inside',~'footnote'~and~'footnotehyper'.~Other~keys~are~
-    available~in~\token_to_str:N \PitonOptions.\\
+    are~'comment-latex',~'escape-inside',~'footnote',~'footnotehyper'~and~
+    'math-comments'.~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}
@@ -1084,8 +1250,8 @@ version 2005/12/01 or later.
 \begingroup
 \cs_new_protected:Npn \@@_set_escape_char:nn #1 #2 
   {
-    \lua_now:n { begin_escape = "#1" }
-    \lua_now:n { end_escape = "#2" }
+    \lua_now:n { piton_begin_escape = "#1" }
+    \lua_now:n { piton_end_escape = "#2" }
   }
 \cs_generate_variant:Nn \@@_set_escape_char:nn { x x }
 \@@_set_escape_char:xx 
@@ -1188,6 +1354,11 @@ version 2005/12/01 or later.
 \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.
@@ -1252,7 +1423,9 @@ version 2005/12/01 or later.
 %    \end{macrocode}
 %
 % \medskip
-% The following dimension corresponds to the key |left-margin| of |\PitonOptions|.
+% The following dimension corresponds to the key |left-margin| of
+% |\PitonOptions|. By convention, when the final user will uses
+% |left-margin=auto|, |\l_@@_left_margin_dim| will be equal to -1~cm.
 %    \begin{macrocode}
 \dim_new:N \l_@@_left_margin_dim
 %    \end{macrocode}
@@ -1274,32 +1447,18 @@ version 2005/12/01 or later.
 \@@_set_tab_tl:n { 4 }
 %    \end{macrocode}
 % 
-% \medskip  
-%    \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 \c_@@_footnote_bool { \end { savenotes } } 
-            \newline
-            \bool_if:NT \c_@@_footnote_bool { \begin { savenotes } } 
-            \vtop \bgroup
-          }
-     }
-  } 
-%    \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}
+% 
 % \bigskip
 % \subsubsection{Treatment of a line of code}
 % 
@@ -1364,6 +1523,25 @@ version 2005/12/01 or later.
   }
 %    \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 \c_@@_footnote_bool { \end { savenotes } } 
+            \newline
+            \bool_if:NT \c_@@_footnote_bool { \begin { savenotes } } 
+            \vtop \bgroup
+          }
+     }
+  } 
+%    \end{macrocode}
 % 
 % \bigskip
 % \subsubsection{PitonOptions}
@@ -1409,10 +1587,15 @@ version 2005/12/01 or later.
     background-color .value_required:n  = true ,
     slim             .bool_set:N        = \l_@@_slim_bool ,
     slim             .default:n         = true ,
-    left-margin      .dim_set:N         = \l_@@_left_margin_dim ,
+    left-margin      .code:n =
+      \str_if_eq:nnTF { #1 } { auto }
+        { \dim_set:Nn \l_@@_left_margin_dim { -1cm } }
+        { \dim_set:Nn \l_@@_left_margin_dim { #1 } } ,
     left-margin      .value_required:n  = true ,
     tab-size         .code:n            = \@@_set_tab_tl:n { #1 } ,
     tab-size         .value_required:n  = true , 
+    show-spaces      .code:n            = \tl_set:Nn \l_@@_space_tl { ␣ } , % U+2423
+    show-spaces      .value_forbidden:n = true ,
     unknown          .code:n = 
       \msg_error:nn { piton } { Unknown~key~for~PitonOptions }
   }
@@ -1426,7 +1609,7 @@ version 2005/12/01 or later.
     Unknown~key. \\
     The~key~'\l_keys_key_str'~is~unknown~for~\token_to_str:N \PitonOptions.~The~
     available~keys~are:~all-line-numbers,~auto-gobble,~env-gobble,~gobble,~
-    left-margin,~line-numbers,~resume,~slim~splittable~and~tab-size.\\
+    left-margin,~line-numbers,~resume,~show-spaces,~slim,~splittable~and~tab-size.\\ 
     If~you~go~on,~that~key~will~be~ignored.
   }
 %    \end{macrocode}
@@ -1510,7 +1693,7 @@ version 2005/12/01 or later.
       \ttfamily
       \cs_set_protected:Npn \@@_begin_line: { }
       \cs_set_protected:Npn \@@_end_line: { }
-      \lua_now:n { Parse(token.scan_argument()) } { #1 }
+      \lua_now:n { piton.Parse(token.scan_argument()) } { #1 }
     \group_end:
   }
 %    \end{macrocode}
@@ -1523,7 +1706,7 @@ version 2005/12/01 or later.
     \group_begin:
       \cs_set_protected:Npn \@@_begin_line: { }
       \cs_set_protected:Npn \@@_end_line: { }
-      \lua_now:e { Parse(token.scan_argument()) } { #1 }
+      \lua_now:n { piton.Parse(token.scan_argument()) } { #1 }
     \group_end:
   }
 %    \end{macrocode}
@@ -1536,8 +1719,7 @@ version 2005/12/01 or later.
   {
     \int_gincr:N \g_@@_env_int 
     \tl_gclear:N \g_@@_aux_tl
-    \tl_if_exist:cT { c_@@ _ \int_use:N \g_@@_env_int _ tl }
-      { \use:c { c_@@ _ \int_use:N \g_@@_env_int _ tl } }
+    \cs_if_exist_use:c { c_@@ _ \int_use:N \g_@@_env_int _ tl }
     \dim_compare:nNnT \l_@@_width_on_aux_dim = \c_zero_dim
       { \dim_set_eq:NN \l_@@_width_on_aux_dim \linewidth }
     \bool_if:NF \l_@@_resume_bool { \int_gzero:N \g_@@_visual_line_int }
@@ -1550,9 +1732,24 @@ version 2005/12/01 or later.
 % 
 % \bigskip
 %    \begin{macrocode}
-\NewDocumentCommand { \PitonInputFile } { m }
+\keys_define:nn { PitonInputFile }
+  {
+    first-line .int_set:N = \l_@@_first_line_int ,  
+    first-line .value_required:n = true ,
+    last-line .int_set:N = \l_@@_last_line_int , 
+    last-line .value_required:n = true , 
+  }
+%    \end{macrocode}
+% 
+% \bigskip
+%    \begin{macrocode}
+\NewDocumentCommand { \PitonInputFile } { O { } m }
   {
     \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
+      \keys_set:nn { PitonInputFile } { #1 }
       \@@_pre_env:
       \mode_if_vertical:TF \mode_leave_vertical: \newline 
 %    \end{macrocode}
@@ -1560,11 +1757,51 @@ version 2005/12/01 or later.
 % stored by Lua in |\l_@@_nb_lines_int|. That information will be used to allow
 % or disallow page breaks.
 %    \begin{macrocode}
-      \lua_now:n { CountLinesFile(token.scan_argument()) } { #1 }  
+      \lua_now:n { piton.CountLinesFile(token.scan_argument()) } { #2 }  
+% If the final user has used both |left-margin=auto| and |line-numbers| or
+% |all-line-numbers|, we have to compute the width of the maximal number of
+% lines at the end of the composition of the listing to fix the correct value to
+% |left-margin|. Par convention, when |left-margin=auto|, the dimension
+% |\l_@@_left_margin_dim| is set to -1~cm.
+%    \begin{macrocode}
+      \dim_compare:nNnT \l_@@_left_margin_dim < \c_zero_dim 
+        {
+          \bool_if:NT \l_@@_line_numbers_bool
+            {
+             \hbox_set:Nn \l_tmpa_box
+               {
+                 \footnotesize
+                 \bool_if:NTF \l_@@_all_line_numbers_bool
+                   {
+                      \int_to_arabic:n 
+                        { \g_@@_visual_line_int + \l_@@_nb_lines_int }  
+                   }
+                   {
+                      \lua_now:n 
+                        { piton.CountNonEmptyLinesFile(token.scan_argument()) } 
+                        { #2 }
+                      \int_to_arabic:n 
+                        { 
+                          \g_@@_visual_line_int +
+                          \l_@@_nb_non_empty_lines_int 
+                        }   
+                    }
+                }
+              \dim_set:Nn \l_@@_left_margin_dim { \box_wd:N \l_tmpa_box + 0.5em }
+            }
+        }
+%    \end{macrocode}
+% Now, the main job.
+%    \begin{macrocode}
       \ttfamily
       \bool_if:NT \c_@@_footnote_bool { \begin { savenotes } } 
       \vtop \bgroup 
-      \lua_now:n { ParseFile(token.scan_argument()) } { #1 }
+      \lua_now:e
+        { piton.ParseFile(token.scan_argument(),
+           \int_use:N \l_@@_first_line_int , 
+           \int_use:N \l_@@_last_line_int ) 
+        } 
+        { #2 }
       \egroup 
       \bool_if:NT \c_@@_footnote_bool { \end { savenotes } } 
       \@@_width_to_aux:
@@ -1601,13 +1838,52 @@ version 2005/12/01 or later.
 % stored by Lua in |\l_@@_nb_lines_int|. That information will be used to allow
 % or disallow page breaks.
 %    \begin{macrocode}
-            \lua_now:n { CountLines(token.scan_argument()) } { ##1 }  
+            \lua_now:n { piton.CountLines(token.scan_argument()) } { ##1 }  
+%    \end{macrocode}
+% 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|.
+%    \begin{macrocode}
+            \dim_compare:nNnT \l_@@_left_margin_dim < \c_zero_dim 
+              {
+                \bool_if:NT \l_@@_line_numbers_bool
+                  {
+                    \bool_if:NTF \l_@@_all_line_numbers_bool
+                      {
+                        \hbox_set:Nn \l_tmpa_box
+                          { 
+                            \footnotesize
+                            \int_to_arabic:n 
+                              { \g_@@_visual_line_int + \l_@@_nb_lines_int }  
+                          }
+                      }
+                      {
+                        \lua_now:n 
+                          { piton.CountNonEmptyLines(token.scan_argument()) } 
+                          { ##1 }  
+                        \hbox_set:Nn \l_tmpa_box
+                          { 
+                            \footnotesize
+                            \int_to_arabic:n 
+                              { 
+                                \g_@@_visual_line_int +
+                                \l_@@_nb_non_empty_lines_int 
+                              }   
+                          }
+                      }
+                    \dim_set:Nn \l_@@_left_margin_dim
+                      { \box_wd:N \l_tmpa_box + 0.5 em }
+                  }
+              }
+%    \end{macrocode}
+% Now, the main job.
+%    \begin{macrocode}
             \ttfamily
             \bool_if:NT \c_@@_footnote_bool { \begin { savenotes } } 
             \vtop \bgroup 
             \lua_now:e 
               { 
-                GobbleParse
+                piton.GobbleParse
                   ( \int_use:N \l_@@_gobble_int , token.scan_argument() ) 
               } 
               { ##1 }
@@ -1807,6 +2083,16 @@ version 2005/12/01 or later.
 % The last style |Post.Function| should be considered as an ``internal style''
 % (not available for the final user).
 %
+% \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}
+\bool_if:NT \c_@@_math_comments_bool
+  { \SetPitonStyle { Comment.Math } }
+%    \end{macrocode}
+% 
 % \bigskip
 % \subsubsection{Security}
 %
@@ -1832,20 +2118,36 @@ version 2005/12/01 or later.
 \ExplSyntaxOff
 \RequirePackage{luacode}
 %    \end{macrocode}
-%   
+% 
+%
+% \bigskip
+% The Lua code will be loaded via a |{luacode*}| environment. Thei 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|.
+%
 % \medskip
 %    \begin{macrocode}
 \begin{luacode*}
+piton = piton or { }
 %    \end{macrocode}
-%
+% 
+%    \begin{macrocode}
+if piton.comment_latex == nil then piton.comment_latex = ">" end 
+piton.comment_latex = "#" .. piton.comment_latex 
+%    \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, Cf = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cf
+local P, S, V, C, Ct, Cc = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc
+local Cf, Cs = lpeg.Cf, lpeg.Cs
 %    \end{macrocode}
 % 
 %
@@ -1854,13 +2156,14 @@ local P, S, V, C, Ct, Cc, Cf = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc,
 % \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''). That function will be widely used.
+% 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
@@ -1888,18 +2191,24 @@ end
 %    \end{macrocode}
 % 
 % \bigskip
-% The function |K| function creates a \textsc{lpeg} which will return as capture
+% 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 pattern (that is to say a \textsc{lpeg}
 % without capture) and the second element is a Lua string corresponding to the
-% name of a \pkg{piton} style.
+% name of a \pkg{piton} style. If the seconde argument is not present, the
+% function |K| behaves as the function |Q| does.
 %    \begin{macrocode}
 local function K(pattern, style)
+  if style 
+  then
   return 
      Lc ( "{\\PitonStyle{" .. style .. "}{" )
      * Q ( pattern )
      * Lc ( "}}" )
+  else 
+  return Q ( pattern ) 
+  end
 end
 %    \end{macrocode}
 % The formatting commands in a given \pkg{piton} style (eg. the style |Keyword|)
@@ -1911,17 +2220,18 @@ end
 % \bigskip
 % The following \textsc{lpeg} catches the Python chunks which are in LaTeX
 % escapes (and that chunks will be considered as normal LaTeX constructions). We
-% recall that |begin_espace| and |end_escape| are Lua strings corresponding to
-% the key |escape-inside|\footnote{The \pkg{piton} key |escape-inside| is
-% available at load-time only.}. 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|)
-% without number of catcode table at the first component of the table.
+% recall that |piton.begin_espace| and |piton_end_escape| are Lua strings
+% corresponding to the key |escape-inside|\footnote{The \pkg{piton} key
+% |escape-inside| is available at load-time only.}. 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|) without number of catcode table at the first component of
+% the table.
 %    \begin{macrocode}
 local Escape = 
-  P(begin_escape)
-  * L ( ( 1 - P(end_escape) ) ^ 1 ) 
-  * P(end_escape)
+  P(piton_begin_escape)
+  * L ( ( 1 - P(piton_end_escape) ) ^ 1 ) 
+  * P(piton_end_escape)
 %    \end{macrocode}
 % 
 % \vspace{1cm}
@@ -1959,13 +2269,9 @@ local identifier = letter * alphanum ^ 0
 % 
 % \medskip
 % On the other hand, the \textsc{lpeg} |Identifier| (with a capital) also return
-% a \emph{capture}. Since no special LaTeX formatting will be applied to the
-% Python identifiers, we use the function~|Q| and not the function~|K|. For
-% elements which require formatting, we will usually use our function~|K|
-% instead of the function~|C|. See just below for an example of use of the
-% function~|K|.
+% a \emph{capture}.
 %    \begin{macrocode}
-local Identifier = Q ( identifier )
+local Identifier = K ( identifier )
 %    \end{macrocode}
 %
 % \bigskip
@@ -1992,25 +2298,26 @@ local Number =
 %    \end{macrocode}
 %
 % \bigskip
-% We recall that |begin_espace| and |end_escape| are Lua strings 
+% We recall that |piton.begin_espace| and |piton_end_escape| are Lua strings
 % corresponding to the key |escape-inside|\footnote{The \pkg{piton} key
 % |escape-inside| is available at load-time only.}. Of course, if the final user
 % has not used the key |escape-inside|, these strings are empty.
 %    \begin{macrocode}
-if begin_escape ~= ''
-then Word = Q ( ( ( 1 - space - P(begin_escape) - P(end_escape) ) 
+local Word
+if piton_begin_escape ~= ''
+then Word = K ( ( ( 1 - space - P(piton_begin_escape) - P(piton_end_escape) ) 
                    - S "'\"\r[()]" - digit ) ^ 1 )
-else Word = Q ( ( ( 1 - space ) - S "'\"\r[()]" - digit ) ^ 1 )
+else Word = K ( ( ( 1 - space ) - S "'\"\r[()]" - digit ) ^ 1 )
 end
 %    \end{macrocode}
 %
 % \bigskip
 %    \begin{macrocode}
-local Space = Q ( ( space - P "\r" ) ^ 1 )
+local Space = K ( ( space - P "\r" ) ^ 1 )
 
-local SkipSpace = Q ( ( space - P "\r" ) ^ 0 )
+local SkipSpace = K ( ( space - P "\r" ) ^ 0 )
 
-local Punct = Q ( S ".,:;!" )
+local Punct = K ( S ".,:;!" )
 %    \end{macrocode}
 %
 % \bigskip
@@ -2040,10 +2347,19 @@ local EOL =
 %
 % \bigskip
 %    \begin{macrocode}
-local Delim = Q ( S "[()]" )
-
+local Delim = K ( S "[()]" )
+%    \end{macrocode}
+% 
+% \bigskip
+% Some strings of length 2 are explicit because we want the corresponding
+% ligatures in the font \emph{Fira Code} to be active.
+%    \begin{macrocode}
 local Operator = 
-  K ( P "!=" + P "==" + P "<<" + P ">>" + S "-~+/*%=<>&.@|" , 'Operator')
+  K ( P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" 
+      + P "//" + P "**" + S "-~+/*%=<>&.@|" 
+      , 
+      'Operator'
+    )
 
 local OperatorWord = 
   K ( P "in" + P "is" + P "and" + P "or" + P "not" , 'Operator.Word')
@@ -2095,9 +2411,9 @@ local Exception =
    + P "StopAsyncIteration" + P "ModuleNotFoundError" + P "RecursionError" ,
   'Exception' )
 
-local RaiseException = K ( P "raise" , 'Keyword' ) * SkipSpace * Exception * Q ( P "(" ) 
+local RaiseException = K ( P "raise" , 'Keyword' ) * SkipSpace * Exception * K ( P "(" ) 
 
-local ExceptionInConsole = Exception *  Q ( ( 1 - P "\r" ) ^ 0 ) * EOL  
+local ExceptionInConsole = Exception *  K ( ( 1 - P "\r" ) ^ 0 ) * EOL  
 %    \end{macrocode}
 %
 % \bigskip
@@ -2148,7 +2464,7 @@ local ImportAs =
    * ( 
        ( Space * K ( P "as" , 'Keyword' ) * Space * K ( identifier , 'Name.Namespace' ) )
        + 
-       ( SkipSpace * Q ( P "," ) * SkipSpace * K ( identifier , 'Name.Namespace' ) ) ^ 0 
+       ( SkipSpace * K ( P "," ) * SkipSpace * K ( identifier , 'Name.Namespace' ) ) ^ 0 
      ) 
 %    \end{macrocode}
 % Be careful: there is no commutativity of |+| in the previous expression.
@@ -2210,43 +2526,71 @@ local FromImport =
 local SingleShortInterpol =
     K ( P "{" , 'String.Interpol')
   * K ( ( 1 - S "}':" ) ^ 0 , 'Interpol.Inside' )
-  * Q ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1
+  * K ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1
   * K ( P "}" , 'String.Interpol' )
 
 local DoubleShortInterpol =
     K ( P "{" , 'String.Interpol' )
   * K ( ( 1 - S "}\":" ) ^ 0 , 'Interpol.Inside' )
-  * ( K ( P ":" , 'String.Interpol' ) * Q ( (1 - S "}:\"") ^ 0 ) ) ^ -1
+  * ( K ( P ":" , 'String.Interpol' ) * K ( (1 - S "}:\"") ^ 0 ) ) ^ -1
   * K ( P "}" , 'String.Interpol' )
 
 local SingleLongInterpol =
     K ( P "{" , 'String.Interpol' )
   * K ( ( 1 - S "}:\r" - P "'''" ) ^ 0 , 'Interpol.Inside' )
-  * Q ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1
+  * K ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1
   * K ( P "}" , 'String.Interpol' )
 
 local DoubleLongInterpol =
     K ( P "{" , 'String.Interpol' )
   * K ( ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 , 'Interpol.Inside' )
-  * Q ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1
+  * K ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1
   * K ( P "}" , 'String.Interpol' )
 %    \end{macrocode}
 %
+% 
+% \bigskip
+% The following \textsc{lpeg} catches a space (U+0032) and replace it by
+% |\l_@@_space_tl|. It will be used in the short strings. Usually,
+% |\l_@@_space_tl| will contain a space and therefore there won't be difference.
+% However, when the key |show-spaces| is in force, |\\l_@@_space_tl| will
+% contain ␣ (U+2423) in order to visualize the spaces.
+%    \begin{macrocode}
+local VisualSpace = P " " * Lc "\\l_@@_space_tl" 
+%    \end{macrocode}
+%
 % \bigskip
 % Now, we define \textsc{lpeg} for the parts of the strings which are \emph{not}
 % in the interpolations.
+%
 %    \begin{macrocode}
 local SingleShortPureString = 
-  Q ( ( P "\\'" + P "{{" + P "}}" + 1 - S "{}'" ) ^ 1 )
+  ( K ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 ) + VisualSpace )  ^ 1 
 
 local DoubleShortPureString = 
-  Q ( ( P "\\\"" + P "{{" + P "}}" + 1 - S "{}\"" ) ^ 1 )
+  ( K ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 ) + VisualSpace ) ^ 1
 
 local SingleLongPureString = 
-  Q ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 )
+  K ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 )
 
 local DoubleLongPureString = 
-  Q ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 ) 
+  K ( ( 1 - P "\"\"\"" - S " {}\"\r" ) ^ 1 )
+%    \end{macrocode}
+%
+% \bigskip
+% The interpolations beginning by |%| (even though there is more modern
+% technics now in Python).
+%    \begin{macrocode}
+local PercentInterpol =  
+  K ( P "%" 
+      * ( P "(" * alphanum ^ 1 * P ")" ) ^ -1 
+      * ( S "-#0 +" ) ^ 0 
+      * ( digit ^ 1 + P "*" ) ^ -1 
+      * ( P "." * ( digit ^ 1 + P "*" ) ) ^ -1 
+      * ( S "HlL" ) ^ -1
+      * S "sdfFeExXorgiGauc%" ,
+      'String.Interpol' 
+    ) 
 %    \end{macrocode}
 % 
 % \bigskip
@@ -2263,27 +2607,37 @@ local SingleShortString =
 %    \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 ( P "f'" + P "F'" ) 
          * ( SingleShortInterpol + SingleShortPureString ) ^ 0 
-         * Q ( P "'" )
+         * K ( 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'" ) 
-         * ( P "\\'" + 1 - S "'\r" ) ^ 0 * P "'" )
+         K ( P "'" + P "r'" + P "R'" ) 
+         * ( K ( ( P "\\'" + 1 - S " '\r%" ) ^ 1 ) 
+             + VisualSpace 
+             + PercentInterpol 
+             + K ( P "%" ) 
+           ) ^ 0 
+         * K ( P "'" )
      )
    * Lc ( "}}" ) 
 
 local DoubleShortString =
   Lc ( "{\\PitonStyle{String.Short}{" )
    * (
-         Q ( P "f\"" + P "F\"" ) 
+         K ( P "f\"" + P "F\"" ) 
          * ( DoubleShortInterpol + DoubleShortPureString ) ^ 0 
-         * Q ( P "\"" )
+         * K ( P "\"" )
        +
-         Q ( ( P "\"" + P "r\"" + P "R\"" ) 
-         * ( P "\\\"" + 1 - S "\"\r" ) ^ 0 * P "\"" )
+         K ( P "\"" + P "r\"" + P "R\"" ) 
+         * ( K ( ( P "\\\"" + 1 - S " \"\r%" ) ^ 1 ) 
+             + VisualSpace 
+             + PercentInterpol 
+             + K ( P "%" ) 
+           ) ^ 0 
+         * K ( P "\"" )
      )
    * Lc ( "}}" ) 
 
@@ -2299,7 +2653,7 @@ local ShortString = SingleShortString + DoubleShortString
 local SingleLongString =
   Lc "{\\PitonStyle{String.Long}{" 
    * (
-         Q ( S "fF" * P "'''" )
+         K ( S "fF" * P "'''" )
          * ( SingleLongInterpol + SingleLongPureString ) ^ 0
          * Lc "}}" 
          * (
@@ -2313,26 +2667,26 @@ local SingleLongString =
          * Lc "{\\PitonStyle{String.Long}{" 
          * ( SingleLongInterpol + SingleLongPureString ) ^ 0
        +
-         Q ( ( S "rR" ) ^ -1  * P "'''" 
+         K ( ( S "rR" ) ^ -1  * P "'''" 
              * ( 1 - P "'''" - P "\r" ) ^ 0 ) 
          * Lc "}}" 
          * (
              Lc "{\\PitonStyle{String.Long}{" 
-             * Q ( ( 1 - P "'''" - P "\r" ) ^ 0 )
+             * K ( ( 1 - P "'''" - P "\r" ) ^ 0 )  
              * Lc "}}" 
              * EOL
            ) ^ 0 
          * Lc "{\\PitonStyle{String.Long}{" 
-         * Q ( ( 1 - P "'''" - P "\r" ) ^ 0 )
+         * K ( ( 1 - P "'''" - P "\r" ) ^ 0 )
       )
-   * Q ( P "'''" )
+   * K ( P "'''" )
    * Lc "}}" 
 
 
 local DoubleLongString =
   Lc "{\\PitonStyle{String.Long}{" 
    * (
-         Q ( S "fF" * P "\"\"\"" )
+         K ( S "fF" * P "\"\"\"" )
          * ( DoubleLongInterpol + DoubleLongPureString ) ^ 0
          * Lc "}}" 
          * (
@@ -2346,19 +2700,19 @@ local DoubleLongString =
          * Lc "{\\PitonStyle{String.Long}{" 
          * ( DoubleLongInterpol + DoubleLongPureString ) ^ 0
        +
-         Q ( ( S "rR" ) ^ -1  * P "\"\"\""
+         K ( ( S "rR" ) ^ -1  * P "\"\"\""
               * ( 1 - P "\"\"\"" - P "\r" ) ^ 0 ) 
          * Lc "}}" 
          * (
              Lc "{\\PitonStyle{String.Long}{" 
-             * Q ( ( 1 - P "\"\"\"" - P "\r" ) ^ 0 )
+             * K ( ( 1 - P "\"\"\"" - P "\r" ) ^ 0 )
              * Lc "}}" 
              * EOL
            ) ^ 0 
          * Lc "{\\PitonStyle{String.Long}{" 
-         * Q ( ( 1 - P "\"\"\"" - P "\r" ) ^ 0 )
+         * K ( ( 1 - P "\"\"\"" - P "\r" ) ^ 0 )
       )
-   * Q ( P "\"\"\"" )
+   * K ( P "\"\"\"" )
    * Lc "}}" 
 %    \end{macrocode}
 %
@@ -2388,14 +2742,14 @@ local CommentMath =
 
 local Comment = 
   Lc ( "{\\PitonStyle{Comment}{" ) 
-  * Q ( P "#" ) 
-  * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0
+  * K ( P "#" ) 
+  * ( CommentMath + K ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0
   * Lc ( "}}" )
   * ( 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
@@ -2403,7 +2757,7 @@ local Comment =
 % the function~|C|) in a table (by using~|Ct|, which is an alias for |lpeg.Ct|).
 %    \begin{macrocode}
 local CommentLaTeX =
-  P "##"
+  P(piton.comment_latex) 
   * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" 
   * L ( ( 1 - P "\r" ) ^ 0 ) 
   * Lc "}}" 
@@ -2456,13 +2810,13 @@ local Param =
   SkipSpace * Identifier * SkipSpace
    * ( 
          K ( P "=" * Expression , 'InitialValues' )
-       + Q ( P ":" ) * SkipSpace * K ( letter^1 , 'Name.Type' ) 
+       + K ( P ":" ) * SkipSpace * K ( letter^1 , 'Name.Type' ) 
      ) ^ -1
 %    \end{macrocode}
 % 
 % \medskip
 %    \begin{macrocode}
-local Params = ( Param * ( Q "," * Param ) ^ 0 ) ^ -1
+local Params = ( Param * ( K "," * Param ) ^ 0 ) ^ -1
 %    \end{macrocode}
 % 
 % \bigskip
@@ -2477,8 +2831,9 @@ local DefFunction =
   * Space
   * K ( identifier , 'Name.Function' ) 
   * SkipSpace 
-  * Q ( P "(" ) * Params * Q ( P ")" ) 
+  * K ( P "(" ) * Params * K ( P ")" ) 
   * SkipSpace
+  * ( K ( P "->" ) * SkipSpace * K ( identifier , 'Name.Type' ) ) ^ -1
 %    \end{macrocode}
 % Here, we need a \pkg{piton} style |Post.Function| which will be linked to
 % |\@@_piton:n| (that means that the capture will be parsed once again by
@@ -2486,7 +2841,7 @@ local DefFunction =
 % grammar but we have probably here a better legibility.
 %    \begin{macrocode}
   * K ( ( 1 - S ":\r" )^0 , 'Post.Function' ) 
-  * Q ( P ":" )
+  * K ( P ":" )
   * ( SkipSpace
       * ( EOL + CommentLaTeX + Comment ) -- in all cases, that contains an EOL
       * Tab ^ 0 
@@ -2527,15 +2882,14 @@ local DefFunction =
 %
 %    \begin{macrocode}
 local ItemDict = 
-  ShortString * SkipSpace * Q ( P ":" ) * K ( Expression , 'Dict.Value' ) 
+  ShortString * SkipSpace * K ( P ":" ) * K ( Expression , 'Dict.Value' ) 
 
 local ItemOfSet = SkipSpace * ( ItemDict + ShortString ) * SkipSpace 
 
 local Set = 
-  Q ( P "{" ) 
-  * ItemOfSet * ( Q ( P "," ) * ItemOfSet )  ^ 0 
-  * Q ( P "}" )
-
+  K ( P "{" ) 
+  * ItemOfSet * ( K ( P "," ) * ItemOfSet )  ^ 0 
+  * K ( P "}" )
 %    \end{macrocode}
 %
 %
@@ -2587,7 +2941,7 @@ local SyntaxPythonAux =
       ) ^0 * -1 * Lc ( '\\@@_end_line:' )
 %    \end{macrocode}
 %
-% We have written a auxiliary \textsc{lpeg} |SyntaxPythonAux| for legibility only.
+% We have written an auxiliary \textsc{lpeg} |SyntaxPythonAux| for legibility only.
 %    \begin{macrocode}
 local SyntaxPython = Ct ( SyntaxPythonAux ) 
 %    \end{macrocode}
@@ -2603,8 +2957,8 @@ local SyntaxPython = Ct ( SyntaxPythonAux )
 % 
 % \bigskip
 %    \begin{macrocode}
-function Parse(code)
-  local t = SyntaxPython : match ( code )
+function piton.Parse(code)
+  local t = SyntaxPython : match ( code ) -- match is a method of the LPEG
   for _ , s in ipairs(t) do tex.tprint(s) end 
 end
 %    \end{macrocode}
@@ -2614,10 +2968,17 @@ end
 % 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 ParseFile(name)
+function piton.ParseFile(name,first_line,last_line)
   s = ''
-  for line in io.lines(name) do s = s .. '\r' .. line end
-  Parse(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
+  piton.Parse(s) 
 end
 %    \end{macrocode}
 %
@@ -2633,7 +2994,7 @@ end
 % a \textsc{lpeg} that we have to compute dynamically because if depends on the
 % value of~$n$.
 %    \begin{macrocode}
-function gobble(n,code)
+local function gobble(n,code)
   function concat(acc,new_value)
     return acc .. new_value
   end 
@@ -2653,25 +3014,13 @@ function gobble(n,code)
 end
 %    \end{macrocode}
 %
-% \bigskip
-%    \begin{macrocode}
-function GobbleParse(n,code)
-  if n==-1 
-  then n = AutoGobbleLPEG : match(code)
-  else if n==-2 
-       then n = EnvGobbleLPEG : match(code)
-       end
-  end
-  Parse(gobble(n,code))
-end 
-%    \end{macrocode}
 % 
 % 
 % \bigskip
 % The following function |add| will be used in the following \textsc{lpeg}
 % |AutoGobbleLPEG| and |EnvGobbleLPEG|.
 %    \begin{macrocode}
-function add(acc,new_value)
+local function add(acc,new_value)
   return acc + new_value
 end 
 %    \end{macrocode}
@@ -2682,7 +3031,7 @@ end
 % captures} (|lpeg.Cf|), one using |add| and the other (encompassing the
 % previous one) using |math.min| as folding operator.
 %    \begin{macrocode}
-AutoGobbleLPEG = 
+local AutoGobbleLPEG = 
     ( space ^ 0 * P "\r" ) ^ -1 
     * Cf (
            (
@@ -2711,28 +3060,59 @@ AutoGobbleLPEG =
 % traditionnal way to indent in LaTeX). The main work is done by a \emph{fold
 % capture} (|lpeg.Cf|) using the function |add| as folding operator.
 %    \begin{macrocode}
-EnvGobbleLPEG =
+local EnvGobbleLPEG =
   ( ( 1 - P "\r" ) ^ 0 * P "\r" ) ^ 0 
     * Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add ) * -1
 %    \end{macrocode}
 % 
 % \bigskip
+%    \begin{macrocode}
+function piton.GobbleParse(n,code)
+  if n==-1 
+  then n = AutoGobbleLPEG : match(code)
+  else if n==-2 
+       then n = EnvGobbleLPEG : match(code)
+       end
+  end
+  piton.Parse(gobble(n,code))
+end 
+%    \end{macrocode}
+%
+% \bigskip
 % \subsubsection{To count the number of lines}
 %
 % \medskip
 %    \begin{macrocode}
-function CountLines(code)
+function piton.CountLines(code)
   local count = 0 
-  for i in code:gmatch("\r") do count = count + 1 end 
+  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 = 
+  ( Cf (  Cc(0) * 
+          ( 
+            ( P " " ) ^ 0 * P "\r"  
+            + ( 1 - P "\r" ) ^ 0 * P "\r" * Cc(1) 
+          ) ^ 0 
+          * (1 - P "\r" ) ^ 0 ,
+         add
+       ) * -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 CountLinesFile(name)
+function piton.CountLinesFile(name)
   local count = 0 
   for line in io.lines(name) do count = count + 1 end
   tex.sprint( 
@@ -2740,6 +3120,23 @@ function CountLinesFile(name)
       '\\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
 %    \begin{macrocode}
@@ -2769,6 +3166,18 @@ end
 %
 % Integer value for the key |splittable|.
 %
+% \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|.
+%
 % \end{document}
 % 
 %
-- 
cgit v1.2.3

