From 7ffc72f568b89a4914168cd6921510d226a48620 Mon Sep 17 00:00:00 2001 From: Norbert Preining 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