texlive[68075] Master/texmf-dist: piton (26aug23)
commits+karl at tug.org
commits+karl at tug.org
Sat Aug 26 22:18:56 CEST 2023
Revision: 68075
http://tug.org/svn/texlive?view=revision&revision=68075
Author: karl
Date: 2023-08-26 22:18:56 +0200 (Sat, 26 Aug 2023)
Log Message:
-----------
piton (26aug23)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/lualatex/piton/README.md
trunk/Master/texmf-dist/doc/lualatex/piton/piton-french.pdf
trunk/Master/texmf-dist/doc/lualatex/piton/piton-french.tex
trunk/Master/texmf-dist/doc/lualatex/piton/piton.pdf
trunk/Master/texmf-dist/source/lualatex/piton/piton.dtx
trunk/Master/texmf-dist/source/lualatex/piton/piton.ins
trunk/Master/texmf-dist/tex/lualatex/piton/piton.sty
Added Paths:
-----------
trunk/Master/texmf-dist/tex/lualatex/piton/piton.lua
Modified: trunk/Master/texmf-dist/doc/lualatex/piton/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/piton/README.md 2023-08-26 20:18:37 UTC (rev 68074)
+++ trunk/Master/texmf-dist/doc/lualatex/piton/README.md 2023-08-26 20:18:56 UTC (rev 68075)
@@ -11,7 +11,7 @@
## Presentation
-The LaTeX package `piton` provides a command `\piton` and an environment `{Piton}` to typeset Python codes by using the Lua library LPEG. It requires the use of `lualatex`. It won't work with `xelatex` nor `pdflatex`.
+The LaTeX package `piton` provides a command `\piton` and an environment `{Piton}` to typeset Python, OCaml or C++ codes by using the Lua library LPEG. It requires the use of `lualatex`. It won't work with `xelatex` nor `pdflatex`.
@@ -24,9 +24,9 @@
* put the files `piton.ins` and `piton.dtx` in the same directory;
* run `latex piton.ins` in that directory.
-The file `piton.sty` will be generated.
+The files `piton.sty` and `piton.lua` will be generated.
-The file `piton.sty` is the only file necessary to use the extension `piton`.
-You have to put it in the same directory as your document or (best) in a `texmf` tree.
+These files `piton.sty` and `piton.lua` are the only files necessary to use the extension `piton`.
+You have to put them in the same directory as your document or (best) in a `texmf` tree.
Modified: trunk/Master/texmf-dist/doc/lualatex/piton/piton-french.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/lualatex/piton/piton-french.tex
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/piton/piton-french.tex 2023-08-26 20:18:37 UTC (rev 68074)
+++ trunk/Master/texmf-dist/doc/lualatex/piton/piton-french.tex 2023-08-26 20:18:56 UTC (rev 68075)
@@ -6,8 +6,19 @@
\usepackage[french]{babel}
\frenchsetup{og = « , fg = »}
-\usepackage[footnotehyper,escape-inside=$$,math-comments]{piton}
+\usepackage[footnotehyper]{piton}
+\PitonOptions
+ {
+ splittable = 4 ,
+ math-comments,
+ begin-escape = ! ,
+ end-escape = ! ,
+ begin-escape-math = \( ,
+ end-escape-math = \)
+ }
+
+
\usepackage[executable=python.exe]{pyluatex}
\usepackage{xcolor}
@@ -68,8 +79,8 @@
\begin{document}
-\PitonOptions{splittable = 4}
+
\VerbatimFootnotes
@@ -123,10 +134,12 @@
\end{Piton}
-\bigskip
-L'extension LaTeX \pkg{piton} est entièrement contenue dans le fichier |piton.sty|. Ce
-fichier peut être placé dans le répertoire courant ou dans une arborescence |texmf|. Le mieux reste néanmoins
+\section{Installation}
+
+L'extension \pkg{piton} est composée de deux fichiers : |piton.sty| et |piton.lua| (le fichier LaTeX |piton.sty|
+chargé par |\usepackage| va à son tour charger le fichier |piton.lua|). Les deux fichiers doivent être présents
+dans un répertoire où LaTeX pourra les trouver, de préférence dans une arborescence |texmf|. Le mieux reste néanmoins
d'installer \pkg{piton} avec une distribution TeX comme MiKTeX, TeX~Live ou MacTeX.
@@ -188,8 +201,7 @@
\item La commande \colorbox{gray!20}{\ttfamily \textbackslash PitonInputFile} doit être utilisée pour insérer et
composer un fichier extérieur.
-Cette commande prend en argument optionnel entre crochets deux clés |first-line| et |last-line| qui permettent de
-n'insérer que la partie du fichier comprise entre les lignes correspondantes.
+Il est possible de n'insérer qu'une partie du fichier : cf. partie~\ref{part-of-a-file}, p.~\pageref{part-of-a-file}.
\end{itemize}
@@ -278,11 +290,10 @@
\section{Personnalisation}
-Concernant la fonte de caractères utilisée dans les listings produits par
-l'extension \pkg{piton}, il s'agit simplement de la fonte mono-chasse courante
-(\pkg{piton} utilise simplement en interne la commande LaTeX standard |\ttfamily|).
+Concernant la fonte de caractères utilisée dans les listings produits par l'extension \pkg{piton}, il s'agit
+simplement de la fonte mono-chasse courante (\pkg{piton} utilise simplement en interne la commande LaTeX standard
+|\ttfamily|). Pour la changer, le mieux est d'utiliser |\setmonofont| de \pkg{fontspec}.
-
\subsection{Les clés de la commande \textbackslash PitonOptions}
\NewDocumentCommand{\Definition}{m}
@@ -313,27 +324,58 @@
valeur de~$n$. Le nom de cette clé vient de \emph{environment gobble}: le nombre d'espaces à retirer ne dépend que
de la position des délimiteurs |\begin{Piton}| et |\end{Piton}| de l'environnement.
-\item Avec la clé \Definition{line-numbers}, les lignes \emph{non vides} (et toutes les lignes des
-\emph{docstrings}, y compris celles qui sont vides) sont numérotées dans les environnements \verb|{Piton}| et dans
-les listings produits par la commande |\PitonInputFile|.
+\item La clé \Definition{line-numbers} active la numérotation des lignes (en débordement à gauche) dans les
+environnements \verb|{Piton}| et dans les listings produits par la commande |\PitonInputFile|.
-\item Avec la clé \Definition{all-line-numbers}, \emph{toutes} les lignes sont numérotées, y compris les lignes vides.
+\colorbox{yellow!50}{\textbf{Nouveau 2.1}}\enskip Cette clé propose en fait plusieurs sous-clés.
+\begin{itemize}
+\item La clé \Definition{line-numbers/skip-empty-lines} demande que les lignes vides soient considérées comme non existantes en
+ce qui concerne la numérotation des lignes (si la clé \verb|/absolute| est active, la clé \verb|/skip-empty-lines|
+n'a pas d'effet dans \verb|\PitonInputFile|). La valeur initiale de cette clé est \verb|true| (et non
+\verb|false|).\footnote{Avec le language Python, les lignes vides des \emph{docstrings} sont prises en compte.}
-\item La clé \Definition{numbers-sep} est la distance horizontale entre les numéros de lignes (insérés par |line-numbers|
-ou |all-line-numbers|) et les lignes du code informatique. La valeur initiale est 0.7~em.
+\item La clé \Definition{line/numbers/label-empty-lines} demande que les labels (c'est-à-dire les numéros) des lignes vides
+soient affichés. Si la clé \verb|/skip-empty-lines| est active, la clé \verb|/label-empty-lines| est sans effet. La
+valeur initiale de cette clé est \verb|true|.
+\item La clé \Definition{line-numbers/absolute} demande, pour les listings générés par \verb|\PitonInputFile|, que les numéros de
+lignes affichés soient absolus (c'est-à-dire ceux du fichier d'origine). Elle n'a d'intérêt que si on insère qu'une
+partie du fichier (cf. part~\ref{part-of-a-file}, p.~\pageref{part-of-a-file}). La clé |/absolute| est sans effet dans les environnements \verb|{Piton}|.
+
+\item La clé \Definition{line-numbers/resume} reprend la numérotation là où elle avait été laissée au dernier listing. En fait,
+la clé \verb|line-numbers/resume| a un alias, qui est \verb|resume| tout court.
+
+\item La clé \Definition{line-numbers/start} impose que la numérotation commence à ce numéro. Elle n'est pas disponible dans
+\verb|\PitonOptions|.
+
+\item La clé \Definition{sep} est la distance horizontale entre les numéros de lignes (insérés par |line-numbers|)
+et les lignes du code informatique. La valeur initiale est 0.7~em.
+\end{itemize}
+
+Pour la commmodité, un dispositif de factorisation du préfixe |line-numbers| est disponible, c'est-à-dire que l'on
+peut écrire :
+
+\begin{Verbatim}
+\PitonOptions
+ {
+ line-numbers =
+ {
+ skip-empty-lines = false ,
+ label-empty-lines = false ,
+ sep = 1 em
+ }
+ }
+\end{Verbatim}
+
+
\item La clé \Definition{left-margin} fixe une marge sur la gauche. Cette clé peut être utile, en particulier, en
-conjonction avec l'une des clés |line-numbers| et |all-line-numbers| si on ne souhaite pas que les numéros de ligne
-soient dans une position en débordement sur la gauche.
+conjonction avec la clé |line-numbers| si on ne souhaite pas que les numéros de ligne soient dans une position en
+débordement sur la gauche.
Il est possible de donner à la clé |left-margin| la valeur spéciale~|auto|. Avec cette valeur, une marge est
-insérée automatiquement pour les numéros de ligne quand l'une des clés |line-numbers| ou |all-line-numbers| est
-utilisée. Voir un exemple à la partie \ref{example-numbering} p.~\pageref{example-numbering}.
+insérée automatiquement pour les numéros de ligne quand la clé |line-numbers| est utilisée. Voir un exemple à la
+partie \ref{example-numbering} p.~\pageref{example-numbering}.
-\item Avec la clé \Definition{resume}, le compteur de lignes n'est pas remis à zéro comme il l'est normalement au
-début d'un environnement |{Piton}| ou bien au début d'un listing produit par |\PitonInputFile|. Cela permet de
-poursuivre la numérotation d'un environnement à l'autre.
-
\item La clé \Definition{background-color} fixe la couleur de fond des environnements |{Piton}| et des listings
produits par |\PitonInputFile| (ce fond a une largeur que l'on peut fixer avec la clé |width| décrite ci-dessous).
La clé |background-color| accepte une couleur définie «à la volée», c'est-à-dire que l'on peut écrire par exemple
@@ -589,6 +631,222 @@
\section{Fonctionnalités avancées}
+\subsection{Coupure des pages et des lignes}
+
+\label{breakable}
+
+\subsubsection{Coupure des pages}
+
+Par défaut les listings produits par l'environnement |{Piton}| et par la commande |\PitonInputFile| sont
+insécables.
+
+Néanmoins, la commande |\PitonOptions| propose la clé \Definition{splittable} pour autoriser de telles coupures.
+
+\begin{itemize}
+\item Si la clé |splittable| est utilisée sans valeur, les listings sont sécables n'importe où.
+
+\item Si la clé |splittable| est utilisée avec une valeur numérique $n$ (qui doit être un entier naturel non nul),
+alors les listings seront sécables mais aucune coupure ne pourra avoir lieu entre les $n$~premières lignes, ni
+entre les $n$~dernières. De ce fait, |splittable=1| est équivalent à |splittable|.
+\end{itemize}
+
+\medskip
+\emph{Remarque}\par\nobreak
+
+Même avec une couleur de fond (fixée avec |background-color|), les sauts de page sont possibles, à partir du moment
+où la clé |splittable| est utilisée.\footnote{Avec la clé |splittable|, un environnement |{Piton}| est sécable même dans un environnement de
+ \pkg{tcolorbox} (à partir du moment où la clé |breakable| de \pkg{tcolorbox} est utilisée). On précise cela parce
+ que, en revanche, un environnement de \pkg{tcolorbox} inclus dans un autre environnement de \pkg{tcolorbox} n'est
+ pas sécable, même quand les deux utilisent la clé |breakable|.}
+
+\subsubsection{Coupure des lignes}
+
+\label{line-breaks}
+
+Par défaut, les éléments produits par \pkg{piton} ne peuvent pas être coupés par une fin de ligne. Il existe
+néanmoins des clés pour autoriser de telles coupures (les points de coupure possibles sont les espaces, y compris
+les espaces dans les chaînes Python).
+\begin{itemize}
+\item Avec la clé \Definition{break-lines-in-piton}, les coupures de ligne sont autorisées dans la commande
+|\piton{...}| (mais pas dans la commande \verb+\piton|...|+, c'est-à-dire avec la syntaxe verbatim).
+
+\item Avec la clé \Definition{break-lines-in-Piton}, les coupures de ligne sont autorisées dans l'environnement
+|{Piton}| (d'où la lettre |P| capitale dans le nom) et les listings produits par |\PitonInputFile|.
+
+\item La clé \Definition{break-lines} est la conjonction des deux clés précédentes.
+\end{itemize}
+
+\medskip
+L'extension \pkg{piton} fournit aussi plusieurs clés pour contrôler l'apparence des coupures de ligne autorisées par |break-lines-in-Piton|.
+
+\begin{itemize}
+\item Avec la clé \Definition{indent-broken-lines}, l'indentation de la ligne coupée est respectée à chaque retour
+à la ligne.
+
+\item La clé \Definition{end-of-broken-line} correspond au symbole placé à la fin d'une ligne coupée. Sa valeur initiale est :
+|\hspace*{0.5em}\textbackslash|.
+
+\item La clé \Definition{continuation-symbol} correspond au symbole placé à chaque retour de ligne dans la marge
+gauche. Sa valeur initiale est : |+\;| (la commande |\;| insère un petit espace horizontal).
+
+\item La clé \Definition{continuation-symbol-on-indentation} correspond au symbole placé à chaque retour de ligne
+au niveau de l'indentation (uniquement dans le cas où la clé |indent-broken-lines| est active). Sa valeur initiale
+est : |$\hookrightarrow\;$|.
+\end{itemize}
+
+\bigskip
+Le code suivant a été composé avec le réglage suivant :
+
+\begin{Verbatim}
+\PitonOptions{width=12cm,break-lines,indent-broken-lines,background-color=gray!15}
+\end{Verbatim}
+
+\begin{center}
+\PitonOptions{width=12cm,break-lines,indent-broken-lines,background-color=gray!15}
+\begin{Piton}
+def dict_of_liste(liste):
+ """Convertit une liste de subrs et de descriptions de glyphes en dictionnaire"""
+ dict = {}
+ for liste_lettre in liste:
+ if (liste_lettre[0][0:3] == 'dup'): # si c'est un subr
+ nom = liste_lettre[0][4:-3]
+ print("On traite le subr de numéro " + nom)
+ else:
+ nom = liste_lettre[0][1:-3] # si c'est un glyphe
+ print("On traite le glyphe du caractère " + nom)
+ dict[nom] = [traite_ligne_Postscript(k) for k in liste_lettre[1:-1]]
+ return dict
+\end{Piton}
+\end{center}
+
+
+\bigskip
+\subsection{Insertion d'une partie d'un fichier}
+
+\label{part-of-a-file}
+
+La commande |\PitonInputFile| permet d'insérer (avec formatage) le contenu d'un fichier. En fait, il existe des
+mécanismes permettant de n'insérer qu'une partie du fichier en question.
+\begin{itemize}
+\item On peut spécifier la partie à insérer par les numéros de lignes (dans le fichier d'origine).
+\item \colorbox{yellow!50}{\textbf{Nouveau 2.1}}\enskip On peut aussi spécifier la partie à insérer par des marqueurs textuels.
+\end{itemize}
+Dans les deux cas, si on souhaite numéroter les lignes avec les numéros des lignes du fichier d'origine, il
+convient d'utiliser la clé |line-numbers/absolute|.
+
+\subsubsection{Avec les numéros de lignes absolus}
+
+La commande |\PitonInputFile| propose les clés \Definition{first-line} et \Definition{last-line} pour n'insérer que
+la partie du fichier comprise entre les lignes correspondantes. Ne pas confondre avec la clé |line-numbers/start|
+qui demande un numérotage des lignes commençant à la valeur donnée à cette clé (en un sens |line-numbers/start|
+concerne la sortie alors que |first-line| et |last-line| concernent l'entrée).
+
+
+\subsubsection{Avec des marqueurs textuels}
+
+\colorbox{yellow!50}{\textbf{Nouveau 2.1}}
+
+Pour utiliser cette technique, il convient d'abord de spécifier le format des marqueurs marquant le début et la fin
+de la partie du fichier à inclure. Cela se fait avec les deux clés \Definition{marker/beginning} et
+\Definition{marker/end} (usuellement dans la commande |\PitonOptions|).
+
+\medskip
+Prenons d'abord un exemple.
+
+\medskip
+Supposons que le fichier à inclure contienne des solutions à des exercices de programmation sur le modèle suivant :
+
+\begin{Verbatim}[formatcom=\small\color{gray}]
+~#[Exercice 1] Version itérative
+def fibo(n):
+ if n==0: return 0
+ else:
+ u=0
+ v=1
+ for i in range(n-1):
+ w = u+v
+ u = v
+ v = w
+ return v
+~#<Exercice 1>
+\end{Verbatim}
+
+Les marqueurs de début de début et de fin sont les chaînes |#[Exercice 1]| et |#<Exercice 1>|. La chaîne
+«|Exercice 1|» sera appelée le \emph{label} de l'exercice (ou de la partie du fichier à inclure).
+
+Pour spécifier des marqueurs de cette sorte dans \pkg{piton}, on utilisera les clés |marker/beginning| et |marker/end|
+de la manière suivante (le caractère |#| des commentaires de Python doit être inséré sous la forme échappée |\#|).
+
+\begin{Verbatim}
+\PitonOptions{ ~emphase#marker/beginning@ = \~#[~#1] , ~emphase#marker/end@ = \~#<~#1> }
+\end{Verbatim}
+
+Comme on le voit, |marker/beginning| est une expression correspondant à la fonction mathématique qui, au nom du
+label (par exemple |Exercice 1|), associe le marqueur de début (dans l'exemple |#[Exercice 1]|). La chaîne |#1|
+correspond aux occurrences de l'argument de cette fonction (c'est la syntaxe habituelle de TeX). De même pour
+|marker/end|.
+
+
+\bigskip
+Pour insérer une partie marquée d'un fichier, il suffit alors d'utiliser la clé \Definition{range} de
+|\PitonInputFile|.
+
+\smallskip
+\begin{Verbatim}
+\PitonInputFile[~emphase#range = Exercice 1@]{~textsl#nom_du_fichier@}
+\end{Verbatim}
+
+\medskip
+\begin{Piton}
+def fibo(n):
+ if n==0: return 0
+ else:
+ u=0
+ v=1
+ for i in range(n-1):
+ w = u+v
+ u = v
+ v = w
+ return v
+\end{Piton}
+
+\vspace{1cm}
+La clé \Definition{marker/include-line} demande que les lignes contenant les marqueurs soient également insérées.
+
+\begin{Verbatim}
+\PitonInputFile[~emphase#marker/include-lines@,range = Exercice 1]{~textsl#nom_du_fichier@}
+\end{Verbatim}
+
+\begin{Piton}
+#[Exercice 1] Version itérative
+def fibo(n):
+ if n==0: return 0
+ else:
+ u=0
+ v=1
+ for i in range(n-1):
+ w = u+v
+ u = v
+ v = w
+ return v
+#<Exercice 1>
+\end{Piton}
+
+
+\bigskip
+Il existe en fait aussi les clés \Definition{begin-range} et \Definition{end-range} pour insérer plusieurs
+contenus marqués simultanément.
+
+Par exemple, pour insérer les solutions des exercices 3 à 5, on pourra écrire (à condition que le fichier soit
+structuré correctement!):
+
+\begin{Verbatim}
+\PitonInputFile[~emphase#begin-range = Exercice 3, end-range = Exercice 5@]{~textsl#nom_du_fichier@}
+\end{Verbatim}
+
+
+
+
\subsection{Mise en évidence d'identificateurs}
On peut demander le changement de formatage de certains identificateurs avec la clé |identifiers| de
@@ -731,12 +989,12 @@
\begin{itemize}
\item Il est possible de changer le marquage syntaxique utilisé (qui vaut initialement~|#>|). Pour ce faire, il
-existe une clé |comment-latex|, disponible seulement au chargement de \pkg{piton} (c'est-à-dire au moment du
-|\usepackage|), qui permet de choisir les caractères qui (précédés par~|#|) serviront de marqueur syntaxique.
+existe une clé |comment-latex|, disponible uniquement dans le préambule du document, qui permet de choisir les
+caractères qui (précédés par~|#|) serviront de marqueur syntaxique.
-Par exemple, avec le chargement suivant :
+Par exemple, avec le réglage suivant (fait dans le préambule du document) :
-\quad \verb|\usepackage[comment-latex = LaTeX]{piton}|
+\verb|\PitonOptions{comment-latex = LaTeX}|
les commentaires LaTeX commenceront par~|#LaTeX|.
@@ -763,11 +1021,11 @@
\bigskip
-Si l'utilisateur a demandé l'affichage des numéros de ligne avec |line-numbers| ou |all-line-numbers|, il est
-possible de faire référence à ce numéro de ligne avec la commande |\label| placée dans un commentaire
-LaTeX.\footnote{Cette fonctionnalité est implémentée en redéfinissant, dans les environnements |{Piton}|, la
- commande |\label|. Il peut donc y avoir des incompatibilités avec les extensions qui redéfinissent (globalement)
- cette commande |\label| (comme \pkg{varioref}, \pkg{refcheck}, \pkg{showlabels}, etc.)}
+Si l'utilisateur a demandé l'affichage des numéros de ligne avec |line-numbers|, il est possible de faire référence
+à ce numéro de ligne avec la commande |\label| placée dans un commentaire LaTeX.\footnote{Cette fonctionnalité est
+ implémentée en redéfinissant, dans les environnements |{Piton}|, la commande |\label|. Il peut donc y avoir des
+ incompatibilités avec les extensions qui redéfinissent (globalement) cette commande |\label| (comme
+ \pkg{varioref}, \pkg{refcheck}, \pkg{showlabels}, etc.)}
@@ -778,11 +1036,11 @@
|#>|), les éléments placés entre symboles \texttt{\$} soient composés en mode mathématique de LaTeX (le reste du
commentaire restant composé en verbatim).
-La clé |math-comments|, qui n'est disponible qu'au chargement de \pkg{piton} (c'est-à-dire au moment du
-|\usepackage|), active ce comportement.
+La clé \Definition{math-comments} (qui ne peut être activée que dans le préambule du document) active ce
+comportement.
\bigskip
-Dans l'exemple suivant, on suppose que la clé |math-comments| a été utilisée au chargement de \pkg{piton}.
+Dans l'exemple suivant, on suppose que |\PitonOptions{math-comments}| a été utilisé dans le préambule du document.
\begin{Verbatim}
\begin{Piton}
@@ -797,20 +1055,20 @@
\end{Piton}
-\subsubsection{Le mécanisme «espace-inside»}
+\subsubsection{Le mécanisme «escape»}
Il est aussi possible de surcharger les listings Python pour y insérer du code LaTeX à peu près n'importe où (mais
entre deux lexèmes, bien entendu). Cette fonctionnalité n'est pas activée par défaut par \pkg{piton}. Pour
-l'utiliser, il faut spécifier les deux caractères marquant l'échappement (le premier le commençant et le deuxième
-le terminant) en utilisant la clé |escape-inside| au chargement de \pkg{piton} (c'est-à-dire au moment du
-|\usepackage|). Les deux caractères peuvent être identiques.
+l'utiliser, il faut spécifier les deux délimiteurs marquant l'échappement (le premier le commençant et le deuxième
+le terminant) en utilisant les clés \Definition{begin-escape} et \Definition{end-escape} (qui ne sont accessibles
+que dans le préambule du document). Les deux délimiteurs peuvent être identiques.
\bigskip
-Dans l'exemple suivant, on suppose que l'extension \pkg{piton} a été chargée de la manière suivante :
+Dans l'exemple suivant, on suppose que le préambule du document contient l'instruction :
\begin{Verbatim}
-\usepackage[~emphase#escape-inside=$$@]{piton}
+\PitonOptions{~emphase#begin-escape=!,end-escape=!@}
\end{Verbatim}
\medskip
@@ -823,7 +1081,7 @@
if n==0:
return 1
else:
- ~emphase#$\highLight{$@return n*fact(n-1)~emphase#$}$@
+ ~emphase#!\highLight{!@return n*fact(n-1)~emphase#!}!@
\end{Piton}
\end{Verbatim}
@@ -832,7 +1090,7 @@
if n==0:
return 1
else:
- $\highLight{$return n*fact(n-1)$}$
+ !\highLight{!return n*fact(n-1)!}!
\end{Piton}
\bigskip
@@ -856,7 +1114,7 @@
if n==0:
return 1
else:
- ~emphase#$\Jaune$@return n*fact(n-1)
+ ~emphase#!\Jaune!@return n*fact(n-1)
\end{Piton}
\end{Verbatim}
@@ -870,20 +1128,80 @@
if n==0:
return 1
else:
- $\Jaune$return n*fact(n-1)
+ !\Jaune!return n*fact(n-1)
\end{Piton}
\bigskip
-\emph{Attention} : L'échappement vers LaTeX permis par les caractères de |escape-inside| n'est pas actif dans les
-chaînes de caractères ni dans les commentaires (pour avoir un commentaire entièrement en échappement vers LaTeX,
-c'est-à-dire ce qui est
-appelé dans ce document «commentaire LaTeX», il suffit de le faire débuter par |#>|).
+\emph{Attention} : L'échappement vers LaTeX permis par les clés |begin-escape| et |end-escape| n'est pas actif dans
+les chaînes de caractères ni dans les commentaires (pour avoir un commentaire entièrement en échappement vers
+LaTeX, c'est-à-dire ce qui est appelé dans ce document «commentaire LaTeX», il suffit de le faire débuter par
+|#>|).
+\subsubsection{Le mécanisme «escape-math»}
+Le mécanisme «|escape-math|» est très similaire au mécanisme «|escape|» puisque la seule différence est que les
+éléments en échappement LaTeX y sont composés en mode mathématique.
+On active ce mécanisme avec les clés \Definition{begin-escape-math} et \Definition{end-escape-math} (qui ne sont
+accessibles que dans le préambule du document).
+
+\medskip
+Malgré la proximité technique, les usages du mécanisme «|escape-math|» sont en fait assez différents de ceux du
+mécanisme «|escape|». En effet, comme le contenu en échappement est composé en mode mathématique, il est en
+particulier composé dans un groupe TeX et ne pourra donc pas servir à changer le formatage d'autres unités lexicales.
+
+\medskip
+Dans les langages où le caractère \verb|$| ne joue pas un rôle syntaxique important, on peut assez naturellement
+vouloir activer le mécanisme «|escape-math|» avec le caractère \verb|$|:
+\begin{Verbatim}
+\PitonOptions{~emphase#begin-escape-math=$,end-escape-math=$@}
+\end{Verbatim}
+Remarquer que le caractère \verb|$| ne doit \emph{pas} être protégé par une contre-oblique.
+
+\bigskip
+Néanmoins, il est sans doute plus prudent d'utiliser |\(| et |\)|.
+\begin{Verbatim}
+\PitonOptions{~emphase#begin-escape-math=\(,end-escape-math=\)@}
+\end{Verbatim}
+
+\bigskip
+Voici un exemple d'utilisation typique :
+
+\medskip
+\begin{Verbatim}
+\begin{Piton}[line-numbers]
+def arctan(x,n=10):
+ if ~emphase#\(x < 0\)@ :
+ return ~emphase#\(-\arctan(-x)\)@
+ elif ~emphase#\(x > 1\)@ :
+ return ~emphase#\(\pi/2 - \arctan(1/x)\)@
+ else:
+ s = ~emphase#\(0\)@
+ for ~emphase#\(k\)@ in range(~emphase#\(n\)@): s += ~emphase#\(\smash{\frac{(-1)^k}{2k+1} x^{2k+1}}\)@
+ return s
+\end{Piton}
+\end{Verbatim}
+
+
+\bigskip
+
+\begin{Piton}[line-numbers]
+def arctan(x,n=10):
+ if \(x < 0\) :
+ return \(-\arctan(-x)\)
+ elif \(x > 1\) :
+ return \(\pi/2 - \arctan(1/x)\)
+ else:
+ s = \(0\)
+ for \(k\) in range(\(n\)): s += \(\smash{\frac{(-1)^k}{2k+1} x^{2k+1}}\)
+ return s
+\end{Piton}
+
+
+
\subsection{Comportement dans la classe Beamer}
\label{beamer}
@@ -898,9 +1216,10 @@
\medskip
Quand l'extension \pkg{piton} est utilisée dans la classe \cls{beamer}\footnote{L'extension \pkg{piton} détecte la
- classe \cls{beamer} mais il est aussi possible, si le besoin s'en faisait sentir, d'activer ce comportement avec
- la clé |beamer| au chargement de \pkg{piton} : |\usepackage[beamer]{piton}|}, le comportement de \pkg{piton} est
-légèrement modifié, comme décrit maintenant.
+ classe \cls{beamer} et l'extension \pkg{beamerarticle} si elle est chargée précédemment, mais il est aussi
+ possible, si le besoin s'en faisait sentir, d'activer ce comportement avec la clé |beamer| au chargement de
+ \pkg{piton} : |\usepackage[beamer]{piton}|}, le comportement de \pkg{piton} est légèrement modifié, comme décrit
+maintenant.
\subsubsection{\{Piton\} et \textbackslash PitonInputFile sont ``overlay-aware''}
@@ -933,7 +1252,7 @@
dans un «commentaire LaTeX», c'est-à-dire en écrivant |#> \pause|. Ainsi, si le code Python est copié, il est
interprétable par Python.} ;
\item un argument obligatoire : |\action|, |\alert|, |\invisible|, |\only|, |\uncover| et |\visible| ;
-\item deux arguments obligatoire : |\alt| ;
+\item deux arguments obligatoires : |\alt| ;
\item trois arguments obligatoires : |\temporal|.
\end{itemize}
@@ -1043,97 +1362,9 @@
\bigskip
-\subsection{Coupure des pages et des lignes}
-\label{breakable}
-\subsubsection{Coupure des pages}
-
-Par défaut les listings produits par l'environnement |{Piton}| et par la commande |\PitonInputFile| sont
-insécables.
-
-Néanmoins, la commande |\PitonOptions| propose la clé \Definition{splittable} pour autoriser de telles coupures.
-
-\begin{itemize}
-\item Si la clé |splittable| est utilisée sans valeur, les listings sont sécables n'importe où.
-
-\item Si la clé |splittable| est utilisée avec une valeur numérique $n$ (qui doit être un entier naturel non nul),
-alors les listings seront sécables mais aucune coupure ne pourra avoir lieu entre les $n$~premières lignes, ni
-entre les $n$~dernières. De ce fait, |splittable=1| est équivalent à |splittable|.
-\end{itemize}
-
-\medskip
-\emph{Remarque}\par\nobreak
-
-Même avec une couleur de fond (fixée avec |background-color|), les sauts de page sont possibles, à partir du moment
-où la clé |splittable| est utilisée.\footnote{Avec la clé |splittable|, un environnement |{Piton}| est sécable même dans un environnement de
- \pkg{tcolorbox} (à partir du moment où la clé |breakable| de \pkg{tcolorbox} est utilisée). On précise cela parce
- que, en revanche, un environnement de \pkg{tcolorbox} inclus dans un autre environnement de \pkg{tcolorbox} n'est
- pas sécable, même quand les deux utilisent la clé |breakable|.}
-
-\subsubsection{Coupure des lignes}
-
-\label{line-breaks}
-
-Par défaut, les éléments produits par \pkg{piton} ne peuvent pas être coupés par une fin de ligne. Il existe
-néanmoins des clés pour autoriser de telles coupures (les points de coupure possibles sont les espaces, y compris
-les espaces dans les chaînes Python).
-\begin{itemize}
-\item Avec la clé \Definition{break-lines-in-piton}, les coupures de ligne sont autorisées dans la commande
-|\piton{...}| (mais pas dans la commande \verb+\piton|...|+, c'est-à-dire avec la syntaxe verbatim).
-
-\item Avec la clé \Definition{break-lines-in-Piton}, les coupures de ligne sont autorisées dans l'environnement
-|{Piton}| (d'où la lettre |P| capitale dans le nom) et les listings produits par |\PitonInputFile|.
-
-\item La clé \Definition{break-lines} est la conjonction des deux clés précédentes.
-\end{itemize}
-
-\medskip
-L'extension \pkg{piton} fournit aussi plusieurs clés pour contrôler l'apparence des coupures de ligne autorisées par |break-lines-in-Piton|.
-
-\begin{itemize}
-\item Avec la clé \Definition{indent-broken-lines}, l'indentation de la ligne coupée est respectée à chaque retour
-à la ligne.
-
-\item La clé \Definition{end-of-broken-line} correspond au symbole placé à la fin d'une ligne coupée. Sa valeur initiale est :
-|\hspace*{0.5em}\textbackslash|.
-
-\item La clé \Definition{continuation-symbol} correspond au symbole placé à chaque retour de ligne dans la marge
-gauche. Sa valeur initiale est : |+\;|.
-
-\item La clé \Definition{continuation-symbol-on-indentation} correspond au symbole placé à chaque retour de ligne
-au niveau de l'indentation (uniquement dans le cas où la clé |indent-broken-lines| est active). Sa valeur initiale
-est : |$\hookrightarrow\;$|.
-\end{itemize}
-
\bigskip
-Le code suivant a été composé avec le réglage suivant :
-
-\begin{Verbatim}
-\PitonOptions{width=12cm,break-lines,indent-broken-lines,background-color=gray!15}
-\end{Verbatim}
-
-\begin{center}
-\PitonOptions{width=12cm,break-lines,indent-broken-lines,background-color=gray!15}
-\begin{Piton}
-def dict_of_liste(liste):
- """Convertit une liste de subrs et de descriptions de glyphes en dictionnaire"""
- dict = {}
- for liste_lettre in liste:
- if (liste_lettre[0][0:3] == 'dup'): # si c'est un subr
- nom = liste_lettre[0][4:-3]
- print("On traite le subr de numéro " + nom)
- else:
- nom = liste_lettre[0][1:-3] # si c'est un glyphe
- print("On traite le glyphe du caractère " + nom)
- dict[nom] = [traite_ligne_Postscript(k) for k in liste_lettre[1:-1]]
- return dict
-\end{Piton}
-\end{center}
-
-
-
-\bigskip
\subsection{Notes de pied de page dans les environnements de piton}
\label{footnote}
@@ -1186,7 +1417,7 @@
\label{example-numbering}
-On rappelle que l'on peut demander la numérotation des lignes des listings avec la clé |line-numbers| ou la clé |all-line-numbers|.
+On rappelle que l'on peut demander la numérotation des lignes des listings avec la clé |line-numbers|.
Par défaut, les numéros de ligne sont composés par \pkg{piton} en débordement à gauche (en utilisant en interne la commande |\llap| de LaTeX).
Modified: trunk/Master/texmf-dist/doc/lualatex/piton/piton.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/source/lualatex/piton/piton.dtx
===================================================================
--- trunk/Master/texmf-dist/source/lualatex/piton/piton.dtx 2023-08-26 20:18:37 UTC (rev 68074)
+++ trunk/Master/texmf-dist/source/lualatex/piton/piton.dtx 2023-08-26 20:18:56 UTC (rev 68075)
@@ -1,4 +1,4 @@
-% \iffalse -*- coding: utf-8 ; -*- \fi \iffalse meta-comment
+% \iffalse -*- coding: utf-8 ; -*- \fi \iffalse meta-comment
%
% Copyright (C) 2023 by F. Pantigny
% -----------------------------------
@@ -15,10 +15,7 @@
%
% \fi
% \iffalse
-\def\myfileversion{2.0}
-\def\myfiledate{2023/08/01}
-%
-%
+%
%<*batchfile>
\begingroup
\input l3docstrip.tex
@@ -45,7 +42,13 @@
%</batchfile>
%
%<@@=piton>
+%<*STY>
+\def\myfileversion{2.1}
+\def\myfiledate{2023/08/26}
+%</STY>
%<*driver>
+\def\myfileversion{2.1}
+\def\myfiledate{2023/08/26}
\documentclass{l3doc}
\usepackage{geometry}
\geometry{left=2.8cm,right=2.8cm,top=2.5cm,bottom=2.5cm,papersize={21cm,29.7cm}}
@@ -56,7 +59,16 @@
\fvset{commandchars=\~\#\@,formatcom=\color{gray}}
\captionsetup{labelfont = bf}
\usepackage{ragged2e}
-\usepackage[footnotehyper,escape-inside=$$,math-comments]{piton} % $$
+\usepackage[footnotehyper]{piton}
+\PitonOptions
+ {
+ splittable = 4 ,
+ math-comments,
+ begin-escape = ! ,
+ end-escape = ! ,
+ begin-escape-math = \( ,
+ end-escape-math = \)
+ }
\parindent 0pt
\skip\footins = 2\bigskipamount
@@ -68,6 +80,7 @@
\EnableCrossrefs
\begin{document}
+
\DocInput{piton.dtx}
\end{document}
%</driver>
@@ -128,17 +141,17 @@
% return s
% \end{Piton}
%
-%
-% \bigskip
-% The package \pkg{piton} is entirely contained in the file
-% |piton.sty|. This file may be put in the current directory or in a
-% |texmf| tree. However, the best is to install \pkg{piton} with a TeX
-% distribution such as MiKTeX, TeX Live or MacTeX.
%
+% \section{Installation}
%
+% The package \pkg{piton} is contained in two files: |piton.sty| and |piton.lua|
+% (the LaTeX file |piton.sty| loaded by |\usepackage| will load the Lua file
+% |piton.lua|). Both files must be in a repertory where LaTeX will be able to
+% find them, for instance in a |texmf| tree. However, the best is to install
+% \pkg{piton} with a TeX distribution such as MiKTeX, TeX Live or MacTeX.
+%
% \section{Use of the package}
%
-%
% \subsection{Loading the package}
%
% The package \pkg{piton} should be loaded with the classical command
@@ -193,11 +206,10 @@
% cf.~\ref{NewPitonEnvironment} p.~\pageref{NewPitonEnvironment}.
%
% \item The command \colorbox{gray!20}{\ttfamily\textbackslash PitonInputFile}
-% is used to insert and typeset a whole external file.
+% is used to insert and typeset a external file.
%
-% That command 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.
+% It's possible to insert only a part of the file: cf.
+% part~\ref{part-of-a-file}, p.~\pageref{part-of-a-file}.
% \end{itemize}
%
% \subsection{The syntax of the command \textbackslash piton}
@@ -327,32 +339,63 @@
% gobble is set by the position of the commands |\begin{Piton}| and
% |\end{Piton}| which delimit the current environment.
%
-% \item With the key \Definition{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
+% \item The key \Definition{line-numbers} activates the line numbering. in the
+% environments |{Piton}| and in the listings resulting from the use of
% |\PitonInputFile|.
%
-% \item With the key \Definition{all-line-numbers}, \emph{all} the lines are numbered,
-% including the empty ones.
+% \colorbox{yellow!50}{\textbf{New 2.1}}\enskip In fact, the key |line-numbers| has
+% several subkeys.
+% \begin{itemize}
+% \item With the key \Definition{line-numbers/skip-empty-lines}, the empty lines
+% are considered as non existent for the line numbering (if the key |/absolute|
+% is in force, the key |/skip-empty-lines| is no-op in |\PitonInputFile|). The
+% initial value of that key is |true| (and not |false|).\footnote{For the
+% language Python, the empty lines in the docstrings are taken into account (by
+% design).}
+% \item With the key \Definition{line-numbers/label-empty-lines}, the labels
+% (that is to say the numbers) of the empty lines are displayed. If the key
+% |/skip-empty-line| is in force, the clé |/label-empty-lines| is no-op. The
+% initial value of that key is~|true|.
+% \item With the key \Definition{line-numbers/absolute}, in the listings
+% generated in |\PitonInputFile|, the numbers of the lines displayed are
+% \emph{absolute} (that is to say: they are the numbers of the lines in the
+% file). That key may be useful when |\PitonInputFile| is used to insert only a
+% part of the file (cf. part~\ref{part-of-a-file}, p.~\pageref{part-of-a-file}).
+% The key |/absolute| is no-op in the environments |{Piton}|.
+% \item The key \Definition{line-numbers/start} requires that the line numbering
+% begins to the value of the key. That key is not available in |\PitonOptions|.
+% \item With the key \Definition{line-numbers/resume}, the counter of lines is
+% not set to zero at the beginning of each environment |{Piton}| or use of
+% |\PitonInputFile| as it is otherwise. That allows a numbering of the lines
+% across several environments.
+% \item The key \Definition{line-numbers/sep} is the horizontal distance between
+% the numbers of lines (inserted by |line-numbers|) and the beginning of the
+% lines of code. The initial value is 0.7~em.
+% \end{itemize}
%
-% \item The key \Definition{numbers-sep} is the horizontal distance between the
-% numbers of lines (inserted by |line-numbers| of |all-line-numbers|) and the
-% beginning of the lines of code. The initial value is 0.7~em.
+% For convenience, a mechanism of factorisation of the prefix |line-numbers| is
+% provided. That means that it is possible, for instance, to write:
+% \begin{Verbatim}
+% \PitonOptions
+% {
+% line-numbers =
+% {
+% skip-empty-lines = false ,
+% label-empty-lines = false ,
+% sep = 1 em
+% }
+% }
+% \end{Verbatim}
%
-% \item With the key \Definition{resume}, the counter of lines is not set to zero
-% at the beginning of each environment |{Piton}| or use of |\PitonInputFile| as
-% it is otherwise. That allows a numbering of the lines across several
-% environments.
%
% \item The key \Definition{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.
+% That key may be useful in conjonction with the key |line-numbers| if one does
+% not want the numbers in an overlapping position on the left.
%
% It's possible to use the key |left-margin| with the value |auto|. With that
-% value, if the key |line-numbers| 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}.
+% value, if the key |line-numbers| is in force, a margin will be automatically
+% inserted to fit the numbers of lines. See an example part
+% \ref{example-numbering} on page~\pageref{example-numbering}.
%
% \item The key \Definition{background-color} sets the background color of the
% environments |{Piton}| and the listings produced by |\PitonInputFile| (it's
@@ -374,8 +417,8 @@
% continuation ``|...|'') characteristic of the Python consoles with
% \textsc{repl} (\emph{read-eval-print loop}).
%
-% \item The key |width| will fix the width of the listing. That width applies to
-% the colored backgrounds specified by |background-color| and
+% \item The key \Definition{width} will fix the width of the listing. That width
+% applies to the colored backgrounds specified by |background-color| and
% |prompt-background-color| but also for the automatic breaking of the lines
% (when required by |break-lines|: cf.~\ref{line-breaks},
% p.~\pageref{line-breaks}).
@@ -627,6 +670,240 @@
%
% \section{Advanced features}
%
+% \subsection{Page breaks and line breaks}
+%
+% \label{breakable}
+%
+% \subsubsection{Page breaks}
+%
+% By default, the listings produced by the environment |{Piton}| and the command
+% |\PitonInputFile| are not breakable.
+%
+% However, the command |\PitonOptions| provides the key \Definition{splittable}
+% to allow such breaks.
+%
+% \begin{itemize}
+% \item If the key |splittable| is used without any value, the
+% listings are breakable everywhere.
+% \item If the key |splittable| is used with a numeric value~$n$ (which must be
+% a non-negative integer number), the listings are breakable but no break will
+% occur within the first $n$ lines and within the last $n$ lines. Therefore,
+% |splittable=1| is equivalent to |splittable|.
+% \end{itemize}
+%
+% \medskip
+% Even with a background color (set by the key |background-color|), the pages
+% breaks are allowed, as soon as the key |splittable| is in force.\footnote{With
+% the key |splittable|, the environments \texttt{\{Piton\}} are breakable, even
+% within a (breakable) environment of \pkg{tcolorbox}. Remind that an
+% environment of \pkg{tcolorbox} included in another environment of
+% \pkg{tcolorbox} is \emph{not} breakable, even when both environments use the
+% key |breakable| of \pkg{tcolorbox}.}
+%
+% \subsubsection{Line breaks}
+%
+% \label{line-breaks}
+%
+% By default, the elements produced by \pkg{piton} can't be broken by an end on
+% line. However, there are keys to allow such breaks (the possible breaking
+% points are the spaces, even the spaces in the Python strings).
+% \begin{itemize}
+% \item With the key \Definition{break-lines-in-piton}, the line breaks are
+% allowed in the command |\piton{...}| (but not in the command
+% \verb+\piton|...|+, that is to say the command |\piton| in verbatim mode).
+% \item With the key \Definition{break-lines-in-Piton}, the line breaks are
+% allowed in the environment |{Piton}| (hence the capital letter |P| in the name) and in the
+% listings produced by |\PitonInputFile|.
+% \item The key \Definition{break-lines} is a conjonction of the two previous keys.
+% \end{itemize}
+%
+% \bigskip
+% The package \pkg{piton} provides also several keys to control the appearance
+% on the line breaks allowed by |break-lines-in-Piton|.
+%
+% \begin{itemize}
+% \item With the key \Definition{indent-broken-lines}, the indentation of a
+% broken line is respected at carriage return.
+%
+% \item The key \Definition{end-of-broken-line} corresponds to the symbol placed
+% at the end of a broken line. The initial value is:
+% |\hspace*{0.5em}\textbackslash|.
+%
+% \item The key \Definition{continuation-symbol} corresponds to the symbol
+% placed at each carriage return. The initial value is: |+\;| (the command |\;|
+% inserts a small horizontal space).
+%
+% \item The key \Definition{continuation-symbol-on-indentation} corresponds to
+% the symbol placed at each carriage return, on the position of the indentation
+% (only when the key |indent-broken-line| is in force). The initial value is:
+% |$\hookrightarrow\;$|.
+% \end{itemize}
+%
+%
+% \bigskip
+% The following code has been composed with the following tuning:
+%
+% \begin{Verbatim}
+% \PitonOptions{width=12cm,break-lines,indent-broken-lines,background-color=gray!15}
+% \end{Verbatim}
+%
+% \begin{center}
+% \PitonOptions{width=12cm,break-lines,indent-broken-lines,background-color=gray!15}
+% \begin{Piton}
+% def dict_of_list(l):
+% """Converts a list of subrs and descriptions of glyphs in a dictionary"""
+% our_dict = {}
+% for list_letter in l:
+% if (list_letter[0][0:3] == 'dup'): # if it's a subr
+% name = list_letter[0][4:-3]
+% print("We treat the subr of number " + name)
+% else:
+% name = list_letter[0][1:-3] # if it's a glyph
+% print("We treat the glyph of number " + name)
+% our_dict[name] = [treat_Postscript_line(k) for k in list_letter[1:-1]]
+% return dict
+% \end{Piton}
+% \end{center}
+%
+%
+% \bigskip
+% \subsection{Insertion of a part of a file}
+%
+% \label{part-of-a-file}
+%
+% The command |\PitonInputFile| inserts (with formating) the content of a file.
+% In fact, it's possible to insert only \emph{a part} of that file. Two
+% mechanisms are provided in this aim.
+% \begin{itemize}
+% \item It's possible to specify the part that we want to insert by the numbers
+% of the lines (in the original file).
+% \item \colorbox{yellow!50}{\textbf{New 2.1}}\enskip It's also possible to
+% specify the part to insert with textual markers.
+% \end{itemize}
+% In both cases, if we want to number the lines with the numbers of the
+% lines in the file, we have to use the key |line-numbers/absolute|.
+%
+% \subsubsection{With line numbers}
+%
+% The command |\PitonInputFile| supports the keys \Definition{first-line} and
+% \Definition{last-line} in order to insert only the part of file between the
+% corresponding lines. Not to be confused with the key |line-numbers/start|
+% which fixes the first line number for the line numbering. In a sens,
+% |line-numbers/start| deals with the output whereas |first-line| and
+% |last-line| deal with the input.
+%
+% \subsubsection{With textual markers}
+%
+% \colorbox{yellow!50}{\textbf{New 2.1}}
+%
+% In order to use that feature, we first have to specify the format of the
+% markers (for the beginning and the end of the part to include) with the keys
+% \Definition{marker-beginning} and \Definition{marker-end} (usually with the
+% command |\PitonOptions|).
+%
+%
+% \medskip
+% Let us take a practical example.
+%
+% \medskip
+% We assume that the file to include contains solutions to exercises of
+% programmation on the following model.
+%
+% \begin{Verbatim}[formatcom=\small\color{gray}]
+% ~#[Exercise 1] Iterative version
+% def fibo(n):
+% if n==0: return 0
+% else:
+% u=0
+% v=1
+% for i in range(n-1):
+% w = u+v
+% u = v
+% v = w
+% return v
+% ~#<Exercise 1>
+% \end{Verbatim}
+%
+% The markers of the beginning and the end are the strings |#[Exercise 1]| and
+% |#<Exercise 1>|. The string ``|Exercise 1|'' will be called the \emph{label}
+% of the exercise (or of the part of the file to be included).
+%
+% In order to specify such markers in \pkg{piton}, we will use the keys
+% |marker/beginning| and |marker/end| with the following instruction (the
+% character |#| of the comments of Python must be inserted with the protected
+% form |\#|).
+%
+% \begin{Verbatim}
+% \PitonOptions{ ~emphase#marker/beginning@ = \~#[~#1] , ~emphase#marker/end@ = \~#<~#1> }
+% \end{Verbatim}
+%
+% As one can see, |marker/beginning| is an expression corresponding to the
+% mathematical function which transforms the label (here |Exercise 1|) into the
+% the beginning marker (in the example |#[Exercise 1]|). The string |#1|
+% corresponds to the occurrences of the argument of that function, which the
+% classical syntax in TeX. Idem for |marker/end|.
+%
+% \bigskip
+% Now, you only have to use the key \Definition{range} of |\PitonInputFile| to
+% insert a marked content of the file.
+%
+% \smallskip
+% \begin{Verbatim}
+% \PitonInputFile[~emphase#range = Exercise 1@]{~textsl#file_name@}
+% \end{Verbatim}
+%
+% \medskip
+% \begin{Piton}
+% def fibo(n):
+% if n==0: return 0
+% else:
+% u=0
+% v=1
+% for i in range(n-1):
+% w = u+v
+% u = v
+% v = w
+% return v
+% \end{Piton}
+%
+% \vspace{1cm}
+% The key \Definition{marker/include-line} requires the insertion of the lines
+% containing the markers.
+%
+% \begin{Verbatim}
+% \PitonInputFile[~emphase#marker/include-lines@,range = Exercise 1]{~textsl#file_name@}
+% \end{Verbatim}
+%
+% \begin{Piton}
+% #[Exercise 1] Iterative version
+% def fibo(n):
+% if n==0: return 0
+% else:
+% u=0
+% v=1
+% for i in range(n-1):
+% w = u+v
+% u = v
+% v = w
+% return v
+% #<Exercise 1>
+% \end{Piton}
+%
+%
+% \bigskip
+% In fact, there exist also the keys \Definition{begin-range} and
+% \Definition{end-range} to insert several marked contents at the same time.
+%
+% For example, in order to insert the solutions of the exercises~3 to~5, we will
+% write (if the file has the correct structure!):
+%
+%
+% \begin{Verbatim}
+% \PitonInputFile[~emphase#begin-range = Exercise 3, end-range = Exercise 5@]{~textsl#file_name@}
+% \end{Verbatim}
+%
+%
+%
% \subsection{Highlighting some identifiers}
%
% It's possible to require a changement of formating for some identifiers with
@@ -639,17 +916,17 @@
% instructions}| }|
%
% \begin{itemize}
-% \item \textsl{\ttfamily names} is a (comma-separated) list of identifiers
+% \item \textsl{\ttfamily names} is a (comma-separated) list of identifier
% names;
%
% \item \textsl{\ttfamily instructions} is a list of LaTeX instructions of the
-% same type that \pkg{piton} ``styles'' previously presented (cf~\ref{styles}
+% same type as \pkg{piton} ``styles'' previously presented (cf~\ref{styles}
% p.~\pageref{styles}).
% \end{itemize}
%
% \emph{Caution}: Only the identifiers may be concerned by that key. The
% keywords and the built-in functions won't be affected, even if their name is
-% in the list |\textsl{\ttfamily names}|.
+% in the list \textsl{\ttfamily names}.
%
% \begin{Verbatim}
% \PitonOptions
@@ -772,13 +1049,13 @@
%
% \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,
+% For this purpose, there is a key |comment-latex| available only in the
+% preamble of the document, allows to choice the characters which,
% preceded by |#|, will be the syntatic marker.
%
-% For example, with the following loading:
+% For example, if the preamble contains the following instruction:
%
-% \quad \verb|\usepackage[comment-latex = LaTeX]{piton}|
+% \quad \verb|\PitonOptions{comment-latex = LaTeX}|
%
% the LaTeX comments will begin by |#LaTeX|.
%
@@ -804,8 +1081,7 @@
% \end{itemize}
%
% \bigskip
-% If the user has required line numbers in the left margin (with the
-% key |line-numbers| or the key |all-line-numbers| of |\PitonOptions|), it's
+% If the user has required line numbers (with the key |line-numbers|), it's
% possible to refer to a number of line with the command |\label| used in a
% LaTeX comment.\footnote{That feature is implemented by using a redefinition of
% the standard command \texttt{\textbackslash label} in the environments
@@ -820,13 +1096,13 @@
% 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|).
+% That feature is activated by the key \Definition{math-comments}, which is
+% available only in the preamble of the document.
%
% \medskip
-% In the following example, we assume that the key |math-comments| has been used
-% when loading \pkg{piton}.
-%
+% Here is a example, where we have assumed that the preamble of the document
+% contains the instruction |\PitonOptions{math-comment}|:
+%
% \begin{Verbatim}
% \begin{Piton}
% def square(x):
@@ -839,23 +1115,23 @@
% return x*x # compute $x^2$
% \end{Piton}
%
-% \subsubsection{The mechanism ``escape-inside''}
+% \subsubsection{The mechanism ``escape''}
%
% It's also possible to overwrite the Python listings to insert LaTeX code
% almost everywhere (but between lexical units, of course). By default,
-% \pkg{piton} does not fix any character for that kind of escape.
+% \pkg{piton} does not fix any delimiters for that kind of escape.
%
-% In order to use this mechanism, it's necessary to specify two characters which
+% In order to use this mechanism, it's necessary to specify the delimiters which
% will delimit the escape (one for the beginning and one for the end) by using
-% the key |escape-inside| at load-time (that is to say at the
-% |\begin{docuemnt}|).
+% the keys \Definition{begin-escape} and \Definition{end-escape}, available only
+% in the preamble of the document.
%
% \medskip
-% In the following example, we assume that the extension \pkg{piton} has been
-% loaded by the following instruction.
+% In the following example, we assume that the preamble of the document contains
+% the following instruction:
%
% \begin{Verbatim}
-% \usepackage[~emphase#escape-inside=$$@]{piton}
+% \PitonOptions{~emphase#begin-escape=!,end-escape=!@}
% \end{Verbatim}
%
% \medskip
@@ -869,7 +1145,7 @@
% if n==0:
% return 1
% else:
-% ~emphase#$\highLight{$@return n*fact(n-1)~emphase#$}$@
+% ~emphase#!\highLight{!@return n*fact(n-1)~emphase#!}!@
% \end{Piton}
% \end{Verbatim}
%
@@ -878,7 +1154,7 @@
% if n==0:
% return 1
% else:
-% $\highLight{$return n*fact(n-1)$}$
+% !\highLight{!return n*fact(n-1)!}!
% \end{Piton}
%
% \bigskip
@@ -902,7 +1178,7 @@
% if n==0:
% return 1
% else:
-% ~emphase#$\Yellow$@return n*fact(n-1)
+% ~emphase#!\Yellow!@return n*fact(n-1)
% \end{Piton}
% \end{Verbatim}
%
@@ -916,19 +1192,83 @@
% if n==0:
% return 1
% else:
-% $\Yellow$return n*fact(n-1)
+% !\Yellow!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).
+% \emph{Caution} : The escape to LaTeX allowed by the |begin-escape| and
+% |end-escape| is not active in the strings nor in the Python comments (however,
+% it's possible to have a whole Python comment composed in LaTeX by beginning it
+% with |#>|; such comments are merely called ``LaTeX comments'' in this
+% document).
%
%
+% \subsubsection{The mechanism ``escape-math''}
+%
+% The mechanism ``|escape-math|'' is very similar to the mechanism ``|escape|''
+% since the only difference is that the elements sent to LaTeX are composed in
+% the math mode of LaTeX.
+%
+% This mechanism is activated with the keys \Definition{begin-escape-math} and
+% \Definition{end-escape-math} (which are available only in the preamble of the
+% document).
+%
+% Despite the technical similarity, the use of the the mechanism
+% ``|escape-math|'' is in fact rather different from that of the mechanism
+% ``|escape|''. Indeed, since the elements are composed in a mathématical mode
+% of LaTeX, they are, in particular, composed within a TeX group and therefore,
+% they can't be used to change the formatting of other lexical units.
+%
+% In the langages where the character \verb|$| does not play a important role,
+% it's possible to activate that mechanism ``|escape-math|'' with the character
+% \verb|$|:
+% \begin{Verbatim}
+% \PitonOptions{~emphase#begin-escape-math=$,end-escape-math=$@}
+% \end{Verbatim}
+% Remark that the character \verb|$| must \emph{not} be protected by a backslash.
+%
+% \bigskip
+% However, it's probably more prudent to use |\(| et |\)|.
+% \begin{Verbatim}
+% \PitonOptions{~emphase#begin-escape-math=\(,end-escape-math=\)@}
+% \end{Verbatim}
+%
+% \bigskip
+% Here is an example of utilisation.
+%
+% \medskip
+% \begin{Verbatim}
+% \begin{Piton}[line-numbers]
+% def arctan(x,n=10):
+% if ~emphase#\(x < 0\)@ :
+% return ~emphase#\(-\arctan(-x)\)@
+% elif ~emphase#\(x > 1\)@ :
+% return ~emphase#\(\pi/2 - \arctan(1/x)\)@
+% else:
+% s = ~emphase#\(0\)@
+% for ~emphase#\(k\)@ in range(~emphase#\(n\)@): s += ~emphase#\(\smash{\frac{(-1)^k}{2k+1} x^{2k+1}}\)@
+% return s
+% \end{Piton}
+% \end{Verbatim}
+%
+%
+% \bigskip
+%
+% \begin{Piton}[line-numbers]
+% def arctan(x,n=10):
+% if \(x < 0\) :
+% return \(-\arctan(-x)\)
+% elif \(x > 1\) :
+% return \(\pi/2 - \arctan(1/x)\)
+% else:
+% s = \(0\)
+% for \(k\) in range(\(n\)): s += \(\smash{\frac{(-1)^k}{2k+1} x^{2k+1}}\)
+% return s
+% \end{Piton}
+%
+%
% \subsection{Behaviour in the class Beamer}
%
% \label{beamer}
@@ -946,6 +1286,7 @@
% \bigskip
% When the package \pkg{piton} is used within the class
% \cls{beamer}\footnote{The extension \pkg{piton} detects the class \cls{beamer}
+% and the package \pkg{beamerarticle} if it is loaded previously
% but, if needed, it's also possible to activate that mechanism with the key
% |beamer| provided by \pkg{piton} at load-time: |\textbackslash
% usepackage[beamer]\{piton\}|}, the behaviour of \pkg{piton} is slightly
@@ -1095,100 +1436,7 @@
% environments |{Piton}| (we recall that the command |\alert| relies upon that
% environment |{alertenv}|).
%
-% \subsection{Page breaks and line breaks}
-%
-% \label{breakable}
-%
-% \subsubsection{Page breaks}
-%
-% By default, the listings produced by the environment |{Piton}| and the command
-% |\PitonInputFile| are not breakable.
-%
-% However, the command |\PitonOptions| provides the key \Definition{splittable}
-% to allow such breaks.
-%
-% \begin{itemize}
-% \item If the key |splittable| is used without any value, the
-% listings are breakable everywhere.
-% \item If the key |splittable| is used with a numeric value~$n$ (which must be
-% a non-negative integer number), the listings are breakable but no break will
-% occur within the first $n$ lines and within the last $n$ lines. Therefore,
-% |splittable=1| is equivalent to |splittable|.
-% \end{itemize}
-%
-% \medskip
-% Even with a background color (set by the key |background-color|), the pages
-% breaks are allowed, as soon as the key |splittable| is in force.\footnote{With
-% the key |splittable|, the environments \texttt{\{Piton\}} are breakable, even
-% within a (breakable) environment of \pkg{tcolorbox}. Remind that an
-% environment of \pkg{tcolorbox} included in another environment of
-% \pkg{tcolorbox} is \emph{not} breakable, even when both environments use the
-% key |breakable| of \pkg{tcolorbox}.}
%
-% \subsubsection{Line breaks}
-%
-% \label{line-breaks}
-%
-% By default, the elements produced by \pkg{piton} can't be broken by an end on
-% line. However, there are keys to allow such breaks (the possible breaking
-% points are the spaces, even the spaces in the Python strings).
-% \begin{itemize}
-% \item With the key \Definition{break-lines-in-piton}, the line breaks are
-% allowed in the command |\piton{...}| (but not in the command
-% \verb+\piton|...|+, that is to say the command |\piton| in verbatim mode).
-% \item With the key \Definition{break-lines-in-Piton}, the line breaks are
-% allowed in the environment |{Piton}| (hence the capital letter |P| in the name) and in the
-% listings produced by |\PitonInputFile|.
-% \item The key \Definition{break-lines} is a conjonction of the two previous keys.
-% \end{itemize}
-%
-% \bigskip
-% The package \pkg{piton} provides also several keys to control the appearance
-% on the line breaks allowed by |break-lines-in-Piton|.
-%
-% \begin{itemize}
-% \item With the key \Definition{indent-broken-lines}, the indentation of a
-% broken line is respected at carriage return.
-%
-% \item The key \Definition{end-of-broken-line} corresponds to the symbol placed
-% at the end of a broken line. The initial value is:
-% |\hspace*{0.5em}\textbackslash|.
-%
-% \item The key \Definition{continuation-symbol} corresponds to the symbol
-% placed at each carriage return. The initial value is: |+\;|.
-%
-% \item The key \Definition{continuation-symbol-on-indentation} corresponds to
-% the symbol placed at each carriage return, on the position of the indentation
-% (only when the key |indent-broken-line| is in force). The initial value is:
-% |$\hookrightarrow\;$|.
-% \end{itemize}
-%
-%
-% \bigskip
-% The following code has been composed with the following tuning:
-%
-% \begin{Verbatim}
-% \PitonOptions{width=12cm,break-lines,indent-broken-lines,background-color=gray!15}
-% \end{Verbatim}
-%
-% \begin{center}
-% \PitonOptions{width=12cm,break-lines,indent-broken-lines,background-color=gray!15}
-% \begin{Piton}
-% def dict_of_list(l):
-% """Converts a list of subrs and descriptions of glyphs in a dictionary"""
-% our_dict = {}
-% for list_letter in l:
-% if (list_letter[0][0:3] == 'dup'): # if it's a subr
-% name = list_letter[0][4:-3]
-% print("We treat the subr of number " + name)
-% else:
-% name = list_letter[0][1:-3] # if it's a glyph
-% print("We treat the glyph of number " + name)
-% our_dict[name] = [treat_Postscript_line(k) for k in list_letter[1:-1]]
-% return dict
-% \end{Piton}
-% \end{center}
-%
% \subsection{Footnotes in the environments of piton}
%
% \label{footnote}
@@ -1247,7 +1495,7 @@
% \label{example-numbering}
%
% We remind that it's possible to have an automatic numbering of the lines in
-% the Python listings by using the key |line-numbers| or the key |all-line-numbers|.
+% the Python listings by using the key |line-numbers|.
%
% By default, the numbers of the lines are composed by \pkg{piton} in an
% overlapping position on the left (by using internally the command |\llap| of LaTeX).
@@ -1802,7 +2050,7 @@
%
% \section{Implementation}
%
-% % \medskip
+% \medskip
% The development of the extension \pkg{piton} is done on the following GitHub
% depot:
%
@@ -1936,6 +2184,7 @@
%
% \subsubsection{Declaration of the package}
% \begin{macrocode}
+%<*STY>
\NeedsTeXFormat{LaTeX2e}
\RequirePackage{l3keys2e}
\ProvidesExplPackage
@@ -1947,7 +2196,18 @@
%
% \bigskip
% \begin{macrocode}
-\msg_new:nnn { piton } { LuaLaTeX~mandatory }
+\cs_new_protected:Npn \@@_error:n { \msg_error:nn { piton } }
+\cs_new_protected:Npn \@@_warning:n { \msg_warning:nn { piton } }
+\cs_new_protected:Npn \@@_error:nn { \msg_error:nnn { piton } }
+\cs_new_protected:Npn \@@_error:nnn { \msg_error:nnnn { piton } }
+\cs_new_protected:Npn \@@_fatal:n { \msg_fatal:nn { piton } }
+\cs_new_protected:Npn \@@_fatal:nn { \msg_fatal:nnn { piton } }
+\cs_new_protected:Npn \@@_msg_new:nn { \msg_new:nnn { piton } }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\@@_msg_new:nn { LuaLaTeX~mandatory }
{
LuaLaTeX~is~mandatory.\\
The~package~'piton'~requires~the~engine~LuaLaTeX.\\
@@ -1962,32 +2222,48 @@
% \begin{macrocode}
\RequirePackage { luatexbase }
% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\@@_msg_new:nn { piton.lua~not~found }
+ {
+ The~file~'piton.lua'~can't~be~found.\\
+ The package~'piton'~won't be loaded.
+ }
+% \end{macrocode}
%
% \bigskip
-% The boolean |\c_@@_footnotehyper_bool| will indicate if the option
+% \begin{macrocode}
+\file_if_exist:nF { piton.lua }
+ { \msg_critical:nn { piton } { piton.lua~not~found } }
+% \end{macrocode}
+%
+%
+% \bigskip
+% The boolean |\g_@@_footnotehyper_bool| will indicate if the option
% |footnotehyper| is used.
% \begin{macrocode}
-\bool_new:N \c_@@_footnotehyper_bool
+\bool_new:N \g_@@_footnotehyper_bool
% \end{macrocode}
%
% \medskip
-% The boolean |\c_@@_footnote_bool| will indicate if the option |footnote| is
+% The boolean |\g_@@_footnote_bool| will indicate if the option |footnote| is
% used, but quicky, it will also be set to |true| if the option |footnotehyper|
% is used.
% \begin{macrocode}
-\bool_new:N \c_@@_footnote_bool
+\bool_new:N \g_@@_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
+\bool_new:N \g_@@_math_comments_bool
% \end{macrocode}
%
% \medskip
-% The following boolean corresponds to the key |beamer|.
% \begin{macrocode}
-\bool_new:N \c_@@_beamer_bool
+\bool_new:N \g_@@_beamer_bool
+\tl_new:N \g_@@_escape_inside_tl
% \end{macrocode}
%
% \bigskip
@@ -1995,31 +2271,54 @@
% \begin{macrocode}
\keys_define:nn { piton / package }
{
- footnote .bool_set:N = \c_@@_footnote_bool ,
- 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 ,
- beamer .bool_set:N = \c_@@_beamer_bool ,
- beamer .default:n = true ,
- unknown .code:n = \msg_error:nn { piton } { unknown~key~for~package }
+ footnote .bool_gset:N = \g_@@_footnote_bool ,
+ footnotehyper .bool_gset:N = \g_@@_footnotehyper_bool ,
+
+ beamer .bool_gset:N = \g_@@_beamer_bool ,
+ beamer .default:n = true ,
+
+ escape-inside .code:n = \@@_error:n { key-escape-inside-deleted } ,
+ math-comments .code:n = \@@_error:n { moved~to~preamble } ,
+ comment-latex .code:n = \@@_error:n { moved~to~preamble } ,
+
+ unknown .code:n = \@@_error:n { Unknown~key~for~package }
}
% \end{macrocode}
%
+% \bigskip
% \begin{macrocode}
-\msg_new:nnn { piton } { unknown~key~for~package }
+\@@_msg_new:nn { key-escape-inside-deleted }
{
+ The~key~'escape-inside'~has~been~deleted.~You~must~now~use~
+ the~keys~'begin-escape'~and~'end-escape'~in~
+ \token_to_str:N \PitonOptions.\\
+ That~key~will~be~ignored.
+ }
+% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\@@_msg_new:nn { moved~to~preamble }
+ {
+ The~key~'\l_keys_key_str'~*must*~now~be~used~with~
+ \token_to_str:N \PitonOptions`in~the~preamble~of~your~
+ document.\\
+ That~key~will~be~ignored.
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\@@_msg_new:nn { Unknown~key~for~package }
+ {
Unknown~key.\\
You~have~used~the~key~'\l_keys_key_str'~but~the~only~keys~available~here~
- are~'beamer',~'comment-latex',~'escape-inside',~'footnote',~'footnotehyper'~and~
- 'math-comments'.~Other~keys~are~available~in~\token_to_str:N \PitonOptions.\\
+ are~'beamer',~'footnote',~'footnotehyper'.~Other~keys~are~available~in~
+ \token_to_str:N \PitonOptions.\\
That~key~will~be~ignored.
}
% \end{macrocode}
%
+%
% \bigskip
% We process the options provided by the user at load-time.
% \begin{macrocode}
@@ -2026,25 +2325,12 @@
\ProcessKeysOptions { piton / package }
% \end{macrocode}
%
-% \bigskip
-% \begin{macrocode}
-\begingroup
-\cs_new_protected:Npn \@@_set_escape_char:nn #1 #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
- { \tl_head:V \c_@@_escape_inside_tl }
- { \tl_tail:V \c_@@_escape_inside_tl }
-\endgroup
-% \end{macrocode}
%
% \bigskip
% \begin{macrocode}
-\@ifclassloaded { beamer } { \bool_set_true:N \c_@@_beamer_bool } { }
-\bool_if:NT \c_@@_beamer_bool { \lua_now:n { piton_beamer = true } }
+\@ifclassloaded { beamer } { \bool_gset_true:N \g_@@_beamer_bool } { }
+\@ifpackageloaded { beamerarticle } { \bool_gset_true:N \g_@@_beamer_bool } { }
+\bool_if:NT \g_@@_beamer_bool { \lua_now:n { piton_beamer = true } }
% \end{macrocode}
%
% \bigskip
@@ -2058,7 +2344,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\msg_new:nnn { piton } { xcolor~not~loaded }
+\@@_msg_new:nn { xcolor~not~loaded }
{
xcolor~not~loaded \\
The~package~'xcolor'~is~required~by~'piton'.\\
@@ -2068,7 +2354,7 @@
%
%
% \begin{macrocode}
-\msg_new:nnn { piton } { footnote~with~footnotehyper~package }
+\@@_msg_new:nn { footnote~with~footnotehyper~package }
{
Footnote~forbidden.\\
You~can't~use~the~option~'footnote'~because~the~package~
@@ -2081,7 +2367,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\msg_new:nnn { piton } { footnotehyper~with~footnote~package }
+\@@_msg_new:nn { footnotehyper~with~footnote~package }
{
You~can't~use~the~option~'footnotehyper'~because~the~package~
footnote~has~already~been~loaded.~
@@ -2094,7 +2380,7 @@
%
% \medskip
% \begin{macrocode}
-\bool_if:NT \c_@@_footnote_bool
+\bool_if:NT \g_@@_footnote_bool
{
% \end{macrocode}
% The class \cls{beamer} has its own system to extract footnotes and that's why
@@ -2101,7 +2387,7 @@
% we have nothing to do if \cls{beamer} is used.
% \begin{macrocode}
\@ifclassloaded { beamer }
- { \bool_set_false:N \c_@@_footnote_bool }
+ { \bool_gset_false:N \g_@@_footnote_bool }
{
\@ifpackageloaded { footnotehyper }
{ \@@_error:n { footnote~with~footnotehyper~package } }
@@ -2111,7 +2397,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\bool_if:NT \c_@@_footnotehyper_bool
+\bool_if:NT \g_@@_footnotehyper_bool
{
% \end{macrocode}
% The class \cls{beamer} has its own system to extract footnotes and that's why
@@ -2118,18 +2404,23 @@
% we have nothing to do if \cls{beamer} is used.
% \begin{macrocode}
\@ifclassloaded { beamer }
- { \bool_set_false:N \c_@@_footnote_bool }
+ { \bool_gset_false:N \g_@@_footnote_bool }
{
\@ifpackageloaded { footnote }
{ \@@_error:n { footnotehyper~with~footnote~package } }
{ \usepackage { footnotehyper } }
- \bool_set_true:N \c_@@_footnote_bool
+ \bool_gset_true:N \g_@@_footnote_bool
}
}
% \end{macrocode}
-% The flag |\c_@@_footnote_bool| is raised and so, we will only have to test
-% |\c_@@_footnote_bool| in order to know if we have to insert an environment
+% The flag |\g_@@_footnote_bool| is raised and so, we will only have to test
+% |\g_@@_footnote_bool| in order to know if we have to insert an environment
% |{savenotes}|.
+%
+% \bigskip
+% \begin{macrocode}
+\lua_now:n { piton = piton~or { } }
+% \end{macrocode}
%
% \bigskip
% \subsubsection{Parameters and technical definitions}
@@ -2142,6 +2433,20 @@
\str_set:Nn \l_@@_language_str { python }
% \end{macrocode}
%
+% \medskip
+% In order to have a better control over the keys.
+% \begin{macrocode}
+\bool_new:N \l_@@_in_PitonOptions_bool
+\bool_new:N \l_@@_in_PitonInputFile_bool
+% \end{macrocode}
+%
+% \medskip
+% The following flag will be raised in the |\AtBeginDocument|.
+% \begin{macrocode}
+\bool_new:N \g_@@_in_document_bool
+% \end{macrocode}
+%
+% \medskip
% We will compute (with Lua) the numbers of lines of the Python code and store
% it in the following counter.
% \begin{macrocode}
@@ -2161,7 +2466,7 @@
% \end{macrocode}
%
% \medskip
-% The following token list will contains the (potential) informations to write
+% The following token list will contain the (potential) informations to write
% on the |aux| (to be used in the next compilation).
% \begin{macrocode}
\tl_new:N \g_@@_aux_tl
@@ -2197,9 +2502,22 @@
% \begin{macrocode}
\tl_new:N \l_@@_prompt_bg_color_tl
% \end{macrocode}
-%
%
% \medskip
+% The following parameters correspond to the keys |begin-range| and |end-range| of
+% the command |\PitonInputFile|.
+% \begin{macrocode}
+\str_new:N \l_@@_begin_range_str
+\str_new:N \l_@@_end_range_str
+% \end{macrocode}
+%
+% \medskip
+% The argument of |\PitonInputFile|.
+% \begin{macrocode}
+\str_new:N \l_@@_file_name_str
+% \end{macrocode}
+%
+% \medskip
% We will count the environments |{Piton}| (and, in fact, also the commands
% |\PitonInputFile|, despite the name |\g_@@_env_int|).
% \begin{macrocode}
@@ -2395,19 +2713,29 @@
}
\@esphack
}
- { \msg_error:nn { piton } { label~with~lines~numbers } }
+ { \@@_error:n { label~with~lines~numbers } }
}
% \end{macrocode}
%
+% \bigskip
+% The following commands corresponds to the keys |marker/beginning| and
+% |marker/end|. The values of that keys are functions that will be applied to
+% the ``\emph{range}'' specified by the final user in an individual
+% |\PitonInputFile|. They will construct the markers used to find textually in
+% the external file loaded by \pkg{piton} the part which must be included (and
+% formatted).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_marker_beginning:n #1 { }
+\cs_new_protected:Npn \@@_marker_end:n #1 { }
+% \end{macrocode}
%
+%
% \bigskip
% The following commands are a easy way to insert safely braces (|{| and |}|) in
% the TeX flow.
% \begin{macrocode}
-\cs_new_protected:Npn \@@_open_brace:
- { \directlua { piton.open_brace() } }
-\cs_new_protected:Npn \@@_close_brace:
- { \directlua { piton.close_brace() } }
+\cs_new_protected:Npn \@@_open_brace: { \directlua { piton.open_brace() } }
+\cs_new_protected:Npn \@@_close_brace: { \directlua { piton.close_brace() } }
% \end{macrocode}
%
% \bigskip
@@ -2504,12 +2832,22 @@
\skip_horizontal:N \l_@@_left_margin_dim
\bool_if:NT \l_@@_line_numbers_bool
{
- \bool_if:NF \l_@@_all_line_numbers_bool
- { \tl_if_eq:nnF { #1 } { \PitonStyle {Prompt}{} } }
-% \end{macrocode}
-% Remember that |\@@_print_number:| always uses |\hbox_overlap_left:n|.
-% \begin{macrocode}
- \@@_print_number:
+ \bool_if:nF
+ {
+ \str_if_eq_p:nn { #1 } { \PitonStyle {Prompt}{} }
+ &&
+ \l_@@_skip_empty_lines_bool
+ }
+ { \int_gincr:N \g_@@_visual_line_int}
+
+ \bool_if:nT
+ {
+ ! \str_if_eq_p:nn { #1 } { \PitonStyle {Prompt}{} }
+ ||
+ ( ! \l_@@_skip_empty_lines_bool && \l_@@_label_empty_lines_bool )
+ }
+ \@@_print_number:
+
}
% \end{macrocode}
% If there is a background, we must remind that there is a left margin of 0.5~em
@@ -2588,7 +2926,7 @@
{
\hbox_to_wd:nn \l_@@_line_width_dim
% \end{macrocode}
-% We unpack the bock in order to free the potential |\hfill| springs present in
+% We unpack the block in order to free the potential |\hfill| springs present in
% the LaTeX comments (cf. section~\ref{example-comments}, p.~\pageref{example-comments}).
% \begin{macrocode}
{ \hbox_unpack:N \l_tmpa_box \hfil }
@@ -2644,9 +2982,9 @@
{ \l_@@_nb_lines_int - \g_@@_line_int } > \l_@@_splittable_int
{
\egroup
- \bool_if:NT \c_@@_footnote_bool { \end { savenotes } }
+ \bool_if:NT \g_@@_footnote_bool { \end { savenotes } }
\par \mode_leave_vertical: % \newline
- \bool_if:NT \c_@@_footnote_bool { \begin { savenotes } }
+ \bool_if:NT \g_@@_footnote_bool { \begin { savenotes } }
\vtop \bgroup
}
}
@@ -2687,18 +3025,91 @@
% \subsubsection{PitonOptions}
%
% \medskip
-% The following parameters correspond to the keys |line-numbers| and
-% |all-line-numbers|.
% \begin{macrocode}
\bool_new:N \l_@@_line_numbers_bool
-\bool_new:N \l_@@_all_line_numbers_bool
+\bool_new:N \l_@@_skip_empty_lines_bool
+\bool_set_true:N \l_@@_skip_empty_lines_bool
+\bool_new:N \l_@@_line_numbers_absolute_bool
+\bool_new:N \l_@@_label_empty_lines_bool
+\bool_set_true:N \l_@@_label_empty_lines_bool
+\int_new:N \l_@@_number_lines_start_int
+\bool_new:N \l_@@_resume_bool
% \end{macrocode}
%
-% \medskip
-% The following flag corresponds to the key |resume|.
+%
+% \bigskip
% \begin{macrocode}
-\bool_new:N \l_@@_resume_bool
+\keys_define:nn { PitonOptions / marker }
+ {
+ beginning .code:n = \cs_set:Nn \@@_marker_beginning:n { #1 } ,
+ beginning .value_required:n = true ,
+ end .code:n = \cs_set:Nn \@@_marker_end:n { #1 } ,
+ end .value_required:n = true ,
+ include-lines .bool_set:N = \l_@@_marker_include_lines_bool ,
+ include-lines .default:n = true ,
+ unknown .code:n = \@@_error:n { Unknown~key~for~marker }
+ }
% \end{macrocode}
+%
+% \bigskip
+% \begin{macrocode}
+\keys_define:nn { PitonOptions / line-numbers }
+ {
+ true .code:n = \bool_set_true:N \l_@@_line_numbers_bool ,
+ false .code:n = \bool_set_false:N \l_@@_line_numbers_bool ,
+
+ start .code:n =
+ \bool_if:NTF \l_@@_in_PitonOptions_bool
+ { Invalid~key }
+ {
+ \bool_set_true:N \l_@@_line_numbers_bool
+ \int_set:Nn \l_@@_number_lines_start_int { #1 }
+ } ,
+ start .value_required:n = true ,
+
+ skip-empty-lines .code:n =
+ \bool_if:NF \l_@@_in_PitonOptions_bool
+ { \bool_set_true:N \l_@@_line_numbers_bool }
+ \str_if_eq:nnTF { #1 } { false }
+ { \bool_set_false:N \l_@@_skip_empty_lines_bool }
+ { \bool_set_true:N \l_@@_skip_empty_lines_bool } ,
+ skip-empty-lines .default:n = true ,
+
+ label-empty-lines .code:n =
+ \bool_if:NF \l_@@_in_PitonOptions_bool
+ { \bool_set_true:N \l_@@_line_numbers_bool }
+ \str_if_eq:nnTF { #1 } { false }
+ { \bool_set_false:N \l_@@_label_empty_lines_bool }
+ { \bool_set_true:N \l_@@_label_empty_lines_bool } ,
+ label-empty-lines .default:n = true ,
+
+ absolute .code:n =
+ \bool_if:NTF \l_@@_in_PitonOptions_bool
+ { \bool_set_true:N \l_@@_line_numbers_absolute_bool }
+ { \bool_set_true:N \l_@@_line_numbers_bool }
+ \bool_if:NT \l_@@_in_PitonInputFile_bool
+ {
+ \bool_set_true:N \l_@@_line_numbers_absolute_bool
+ \bool_set_false:N \l_@@_skip_empty_lines_bool
+ }
+ \bool_lazy_or:nnF
+ \l_@@_in_PitonInputFile_bool
+ \l_@@_in_PitonOptions_bool
+ { \@@_error:n { Invalid~key } } ,
+ absolute .value_forbidden:n = true ,
+
+ resume .code:n =
+ \bool_set_true:N \l_@@_resume_bool
+ \bool_if:NF \l_@@_in_PitonOptions_bool
+ { \bool_set_true:N \l_@@_line_numbers_bool } ,
+ resume .value_forbidden:n = true ,
+
+ sep .dim_set:N = \l_@@_numbers_sep_dim ,
+ sep .value_required:n = true ,
+
+ unknown .code:n = \@@_error:n { Unknown~key~for~line-numbers }
+ }
+% \end{macrocode}
%
% \bigskip
% Be careful! The name of the following set of keys must be considered as
@@ -2707,6 +3118,41 @@
% \begin{macrocode}
\keys_define:nn { PitonOptions }
{
+% \end{macrocode}
+% First, we put keys that should be avalaible only in the preamble.
+% \begin{macrocode}
+ begin-escape .code:n =
+ \lua_now:e { piton.begin_escape = "\lua_escape:n{#1}" } ,
+ begin-escape .value_required:n = true ,
+ begin-escape .usage:n = preamble ,
+
+ end-escape .code:n =
+ \lua_now:e { piton.end_escape = "\lua_escape:n{#1}" } ,
+ end-escape .value_required:n = true ,
+ end-escape .usage:n = preamble ,
+
+ begin-escape-math .code:n =
+ \lua_now:e { piton.begin_escape_math = "\lua_escape:n{#1}" } ,
+ begin-escape-math .value_required:n = true ,
+ begin-escape-math .usage:n = preamble ,
+
+ end-escape-math .code:n =
+ \lua_now:e { piton.end_escape_math = "\lua_escape:n{#1}" } ,
+ end-escape-math .value_required:n = true ,
+ end-escape-math .usage:n = preamble ,
+
+ comment-latex .code:n = \lua_now:n { comment_latex = "#1" } ,
+ comment-latex .value_required:n = true ,
+ comment-latex .usage:n = preamble ,
+
+ math-comments .bool_set:N = \g_@@_math_comments_bool ,
+ math-comments .default:n = true ,
+ math-comments .usage:n = preamble ,
+% \end{macrocode}
+%
+% \bigskip
+% Now, general keys.
+% \begin{macrocode}
language .code:n =
\str_set:Nx \l_@@_language_str { \str_lowercase:n { #1 } } ,
language .value_required:n = true ,
@@ -2718,14 +3164,20 @@
env-gobble .value_forbidden:n = true ,
tabs-auto-gobble .code:n = \int_set:Nn \l_@@_gobble_int { -3 } ,
tabs-auto-gobble .value_forbidden:n = true ,
- line-numbers .bool_set:N = \l_@@_line_numbers_bool ,
- line-numbers .default:n = true ,
- all-line-numbers .code:n =
- \bool_set_true:N \l_@@_line_numbers_bool
- \bool_set_true:N \l_@@_all_line_numbers_bool ,
- all-line-numbers .value_forbidden:n = true ,
- resume .bool_set:N = \l_@@_resume_bool ,
- resume .value_forbidden:n = true ,
+
+ marker .code:n =
+ \bool_lazy_or:nnTF
+ \l_@@_in_PitonInputFile_bool
+ \l_@@_in_PitonOptions_bool
+ { \keys_set:nn { PitonOptions / marker } { #1 } }
+ { \@@_error:n { Invalid~key } } ,
+ marker .value_required:n = true ,
+
+ line-numbers .code:n =
+ \keys_set:nn { PitonOptions / line-numbers } { #1 } ,
+ line-numbers .default:n = true ,
+
+
splittable .int_set:N = \l_@@_splittable_int ,
splittable .default:n = 1 ,
background-color .clist_set:N = \l_@@_bg_color_clist ,
@@ -2732,7 +3184,8 @@
background-color .value_required:n = true ,
prompt-background-color .tl_set:N = \l_@@_prompt_bg_color_tl ,
prompt-background-color .value_required:n = true ,
- width .code:n =
+
+ width .code:n =
\str_if_eq:nnTF { #1 } { min }
{
\bool_set_true:N \l_@@_width_min_bool
@@ -2742,7 +3195,8 @@
\bool_set_false:N \l_@@_width_min_bool
\dim_set:Nn \l_@@_width_dim { #1 }
} ,
- width .value_required:n = true ,
+ width .value_required:n = true ,
+
left-margin .code:n =
\str_if_eq:nnTF { #1 } { auto }
{
@@ -2754,8 +3208,7 @@
\bool_set_false:N \l_@@_left_margin_auto_bool
} ,
left-margin .value_required:n = true ,
- numbers-sep .dim_set:N = \l_@@_numbers_sep_dim ,
- numbers-sep .value_required:n = true ,
+
tab-size .code:n = \@@_set_tab_tl:n { #1 } ,
tab-size .value_required:n = true ,
show-spaces .bool_set:N = \l_@@_show_spaces_bool ,
@@ -2776,27 +3229,80 @@
continuation-symbol .value_required:n = true ,
continuation-symbol-on-indentation .tl_set:N = \l_@@_csoi_tl ,
continuation-symbol-on-indentation .value_required:n = true ,
- unknown .code:n =
- \msg_error:nn { piton } { Unknown~key~for~PitonOptions }
+
+ first-line .code:n = \@@_in_PitonInputFile:n
+ { \int_set:Nn \l_@@_first_line_int { #1 } } ,
+ first-line .value_required:n = true ,
+
+ last-line .code:n = \@@_in_PitonInputFile:n
+ { \int_set:Nn \l_@@_last_line_int { #1 } } ,
+ last-line .value_required:n = true ,
+
+ begin-range .code:n = \@@_in_PitonInputFile:n
+ { \str_set:Nn \l_@@_begin_range_str { #1 } } ,
+ begin-range .value_required:n = true ,
+
+ end-range .code:n = \@@_in_PitonInputFile:n
+ { \str_set:Nn \l_@@_end_range_str { #1 } } ,
+ end-range .value_required:n = true ,
+
+ range .code:n = \@@_in_PitonInputFile:n
+ {
+ \str_set:Nn \l_@@_begin_range_str { #1 }
+ \str_set:Nn \l_@@_end_range_str { #1 }
+ } ,
+ range .value_required:n = true ,
+
+ resume .meta:n = line-numbers/resume ,
+
+ unknown .code:n = \@@_error:n { Unknown~key~for~PitonOptions } ,
+
+ % deprecated
+ all-line-numbers .code:n =
+ \bool_set_true:N \l_@@_line_numbers_bool
+ \bool_set_false:N \l_@@_skip_empty_lines_bool ,
+ all-line-numbers .value_forbidden:n = true ,
+
+ % deprecated
+ numbers-sep .dim_set:N = \l_@@_numbers_sep_dim ,
+ numbers-sep .value_required:n = true
}
% \end{macrocode}
%
+% \bigskip
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_in_PitonInputFile:n #1
+ {
+ \bool_if:NTF \l_@@_in_PitonInputFile_bool
+ { #1 }
+ { \@@_error:n { Invalid~key } }
+ }
+% \end{macrocode}
%
-% \bigskip
-%
+%
% \bigskip
-% The argument of |\PitonOptions| is provided by curryfication.
% \begin{macrocode}
-\NewDocumentCommand \PitonOptions { } { \keys_set:nn { PitonOptions } }
+\NewDocumentCommand \PitonOptions { m }
+ {
+ \bool_set_true:N \l_@@_in_PitonOptions_bool
+ \keys_set:nn { PitonOptions } { #1 }
+ \bool_set_false:N \l_@@_in_PitonOptions_bool
+ }
% \end{macrocode}
%
+%
% \bigskip
+% \begin{macrocode}
+\hook_gput_code:nnn { begindocument } { . }
+ { \bool_gset_true:N \g_@@_in_document_bool }
+% \end{macrocode}
+%
+% \bigskip
% \subsubsection{The numbers of the lines}
%
% \medskip
% The following counter will be used to count the lines in the code when the
-% user requires the numbers of the lines to be printed (with |line-numbers| or
-% |all-line-numbers|).
+% user requires the numbers of the lines to be printed (with |line-numbers|).
%
% \begin{macrocode}
\int_new:N \g_@@_visual_line_int
@@ -2806,10 +3312,13 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_print_number:
{
- \int_gincr:N \g_@@_visual_line_int
\hbox_overlap_left:n
{
- { \color { gray } \footnotesize \int_to_arabic:n \g_@@_visual_line_int }
+ {
+ \color { gray }
+ \footnotesize
+ \int_to_arabic:n \g_@@_visual_line_int
+ }
\skip_horizontal:N \l_@@_numbers_sep_dim
}
}
@@ -3028,18 +3537,7 @@
}
% \end{macrocode}
%
-% \bigskip
-% \begin{macrocode}
-\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
% 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
@@ -3054,12 +3552,8 @@
\hbox_set:Nn \l_tmpa_box
{
\footnotesize
- \bool_if:NTF \l_@@_all_line_numbers_bool
+ \bool_if:NTF \l_@@_skip_empty_lines_bool
{
- \int_to_arabic:n
- { \g_@@_visual_line_int + \l_@@_nb_lines_int }
- }
- {
\lua_now:n
{ piton.#1(token.scan_argument()) }
{ #2 }
@@ -3066,6 +3560,10 @@
\int_to_arabic:n
{ \g_@@_visual_line_int + \l_@@_nb_non_empty_lines_int }
}
+ {
+ \int_to_arabic:n
+ { \g_@@_visual_line_int + \l_@@_nb_lines_int }
+ }
}
\dim_set:Nn \l_@@_left_margin_dim
{ \box_wd:N \l_tmpa_box + \l_@@_numbers_sep_dim + 0.1 em }
@@ -3169,10 +3667,10 @@
\ttfamily
\dim_zero:N \parskip % added 2023/07/06
% \end{macrocode}
-% |\c_@@_footnote_bool| is raised when the package \pkg{piton} has been load
+% |\g_@@_footnote_bool| is raised when the package \pkg{piton} has been load
% with the key |footnote| \emph{or} the key |footnotehyper|.
% \begin{macrocode}
- \bool_if:NT \c_@@_footnote_bool { \begin { savenotes } }
+ \bool_if:NT \g_@@_footnote_bool { \begin { savenotes } }
\vtop \bgroup
\lua_now:e
{
@@ -3186,7 +3684,7 @@
{ ##1 }
\vspace { 2.5 pt }
\egroup
- \bool_if:NT \c_@@_footnote_bool { \end { savenotes } }
+ \bool_if:NT \g_@@_footnote_bool { \end { savenotes } }
% \end{macrocode}
% If the user has used the key |width| with the special value~|min|, we write on
% the |aux| file the value of |\l_@@_line_width_dim| (largest width of the lines
@@ -3211,6 +3709,8 @@
{
#3
\@@_pre_env:
+ \int_compare:nNnT \l_@@_number_lines_start_int > 0
+ { \int_gset:Nn \g_@@_visual_line_int { \l_@@_number_lines_start_int - 1 } }
\group_begin:
\tl_map_function:nN
{ \ \\ \{ \} \$ \& \# \^ \_ \% \~ \^^I }
@@ -3238,11 +3738,11 @@
% provided by the package \pkg{piton}. Of course, you use
% |\NewPitonEnvironment|.
% \begin{macrocode}
-\bool_if:NTF \c_@@_beamer_bool
+\bool_if:NTF \g_@@_beamer_bool
{
\NewPitonEnvironment { Piton } { d < > O { } }
{
- \PitonOptions { #2 }
+ \keys_set:nn { PitonOptions } { #2 }
\IfValueTF { #1 }
{ \begin { uncoverenv } < #1 > }
{ \begin { uncoverenv } }
@@ -3249,8 +3749,9 @@
}
{ \end { uncoverenv } }
}
- { \NewPitonEnvironment { Piton } { O { } }
- { \PitonOptions { #1 } }
+ {
+ \NewPitonEnvironment { Piton } { O { } }
+ { \keys_set:nn { PitonOptions } { #1 } }
{ }
}
% \end{macrocode}
@@ -3265,7 +3766,7 @@
{
\file_if_exist:nTF { #3 }
{ \@@_input_file:nnn { #1 } { #2 } { #3 } }
- { \msg_error:nnn { piton } { unknown~file } { #3 } }
+ { \msg_error:nnn { piton } { Unknown~file } { #3 } }
}
% \end{macrocode}
%
@@ -3272,6 +3773,7 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_input_file:nnn #1 #2 #3
{
+ \str_set:Nn \l_@@_file_name_str { #3 }
% \end{macrocode}
% We recall that, if we are in Beamer, the command |\PitonInputFile| is
% ``overlay-aware'' and that's why there is an optional argument between angular
@@ -3279,16 +3781,58 @@
% \begin{macrocode}
\tl_if_novalue:nF { #1 }
{
- \bool_if:NTF \c_@@_beamer_bool
+ \bool_if:NTF \g_@@_beamer_bool
{ \begin { uncoverenv } < #1 > }
- { \msg_error:nn { piton } { overlay~without~beamer } }
+ { \@@_error:n { overlay~without~beamer } }
}
\group_begin:
\int_zero_new:N \l_@@_first_line_int
\int_zero_new:N \l_@@_last_line_int
\int_set_eq:NN \l_@@_last_line_int \c_max_int
- \keys_set:nn { PitonInputFile } { #2 }
+ \bool_set_true:N \l_@@_in_PitonInputFile_bool
+ \keys_set:nn { PitonOptions } { #2 }
+ \bool_if:NT \l_@@_line_numbers_absolute_bool
+ { \bool_set_false:N \l_@@_skip_empty_lines_bool }
+ \bool_if:nTF
+ {
+ (
+ \int_compare_p:nNn \l_@@_first_line_int > 0
+ || \int_compare_p:nNn \l_@@_last_line_int < \c_max_int
+ )
+ && ! \str_if_empty_p:N \l_@@_begin_range_str
+ }
+ {
+ \@@_error:n { bad~range~specification }
+ \int_zero:N \l_@@_first_line_int
+ \int_set_eq:NN \l_@@_last_line_int \c_max_int
+ }
+ {
+ \str_if_empty:NF \l_@@_begin_range_str
+ {
+ \@@_compute_range:
+ \bool_lazy_or:nnT
+ \l_@@_marker_include_lines_bool
+ { ! \str_if_eq_p:NN \l_@@_begin_range_str \l_@@_end_range_str }
+ {
+ \int_decr:N \l_@@_first_line_int
+ \int_incr:N \l_@@_last_line_int
+ }
+ }
+ }
\@@_pre_env:
+ \bool_if:NT \l_@@_line_numbers_absolute_bool
+ { \int_gset:Nn \g_@@_visual_line_int { \l_@@_first_line_int - 1 } }
+ \int_compare:nNnT \l_@@_number_lines_start_int > 0
+ {
+ \int_gset:Nn \g_@@_visual_line_int
+ { \l_@@_number_lines_start_int - 1 }
+ }
+% \end{macrocode}
+% The following case arise when the code |line-numbers/absolute| is in force
+% without the use of a marked range.
+% \begin{macrocode}
+ \int_compare:nNnT \g_@@_visual_line_int < 0
+ { \int_gzero:N \g_@@_visual_line_int }
\mode_if_vertical:TF \mode_leave_vertical: \newline
% \end{macrocode}
% We count with Lua the number of lines of the argument. The result will be
@@ -3295,7 +3839,7 @@
% stored by Lua in |\l_@@_nb_lines_int|. That information will be used to allow
% or disallow page breaks.
% \begin{macrocode}
- \lua_now:n { piton.CountLinesFile(token.scan_argument()) } { #3 }
+ \lua_now:e { piton.CountLinesFile('\l_@@_file_name_str') }
% \end{macrocode}
% The first argument of the following function is the name of the Lua function
% that will be applied to the second argument in order to count the number of lines.
@@ -3303,19 +3847,18 @@
\@@_compute_left_margin:nn { CountNonEmptyLinesFile } { #3 }
\@@_compute_width:
\ttfamily
- \bool_if:NT \c_@@_footnote_bool { \begin { savenotes } }
+ \bool_if:NT \g_@@_footnote_bool { \begin { savenotes } }
\vtop \bgroup
\lua_now:e
{
piton.ParseFile(
- '\l_@@_language_str',
- token.scan_argument() ,
+ '\l_@@_language_str' ,
+ '\l_@@_file_name_str' ,
\int_use:N \l_@@_first_line_int ,
\int_use:N \l_@@_last_line_int )
}
- { #3 }
\egroup
- \bool_if:NT \c_@@_footnote_bool { \end { savenotes } }
+ \bool_if:NT \g_@@_footnote_bool { \end { savenotes } }
\bool_if:NT \l_@@_width_min_bool \@@_width_to_aux:
\group_end:
% \end{macrocode}
@@ -3324,12 +3867,40 @@
% that we have opened at the beginning of the command.
% \begin{macrocode}
\tl_if_novalue:nF { #1 }
- { \bool_if:NT \c_@@_beamer_bool { \end { uncoverenv } } }
+ { \bool_if:NT \g_@@_beamer_bool { \end { uncoverenv } } }
\@@_write_aux:
}
% \end{macrocode}
%
+%
% \bigskip
+% The following command computes the values of |\l_@@_first_line_int| and
+% |\l_@@_last_line_int| when |\PitonInputFile| is used with textual markers.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_compute_range:
+ {
+% \end{macrocode}
+% We store the markers in L3 strings (|str|) in order to do safely the following
+% replacement of |\#|.
+% \begin{macrocode}
+ \str_set:Nx \l_tmpa_str { \@@_marker_beginning:n \l_@@_begin_range_str }
+ \str_set:Nx \l_tmpb_str { \@@_marker_end:n \l_@@_end_range_str }
+% \end{macrocode}
+% We replace the sequences |\#| which may be present in the prefixes (and, more
+% unlikely, suffixes) added to the markers by the functions
+% |\@@_marker_beginning:n| and |\@@_marker_end:n|
+% \begin{macrocode}
+ \exp_args:NnV \regex_replace_all:nnN { \\\# } \c_hash_str \l_tmpa_str
+ \exp_args:NnV \regex_replace_all:nnN { \\\# } \c_hash_str \l_tmpb_str
+ \lua_now:e
+ {
+ piton.ComputeRange
+ ( '\l_tmpa_str' , '\l_tmpb_str' , '\l_@@_file_name_str' )
+ }
+ }
+% \end{macrocode}
+%
+% \bigskip
% \subsubsection{The styles}
%
% \medskip
@@ -3406,7 +3977,7 @@
ParseAgain.noCR .tl_set:c = pitonStyle ParseAgain.noCR ,
ParseAgain.noCR .value_required:n = true ,
unknown .code:n =
- \msg_error:nn { piton } { Unknown~key~for~SetPitonStyle }
+ \@@_error:n { Unknown~key~for~SetPitonStyle }
}
% \end{macrocode}
%
@@ -3425,7 +3996,7 @@
{
\str_compare:nNnTF { #1 } < { #2 }
\sort_return_same:
- \sort_return_swapped:
+ \sort_return_swapped:
}
% \end{macrocode}
%
@@ -3480,7 +4051,7 @@
% 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 } }
+\bool_if:NT \g_@@_math_comments_bool { \SetPitonStyle { Comment.Math } }
% \end{macrocode}
%
% \bigskip
@@ -3592,7 +4163,7 @@
%
%
% \begin{macrocode}
-\msg_new:nnn { piton } { Unknown~key~for~SetPitonStyle }
+\@@_msg_new:nn { Unknown~key~for~SetPitonStyle }
{
The~style~'\l_keys_key_str'~is~unknown.\\
This~key~will~be~ignored.\\
@@ -3601,8 +4172,53 @@
}
% \end{macrocode}
%
+% \begin{macrocode}
+\@@_msg_new:nn { Invalid~key }
+ {
+ Wrong~use~of~key.\\
+ You~can't~use~the~key~'\l_keys_key_str'~here.\\
+ That~key~will~be~ignored.
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\@@_msg_new:nn { Unknown~key~for~line-numbers }
+ {
+ Unknown~key. \\
+ The~key~'line-numbers / \l_keys_key_str'~is~unknown.\\
+ The~available~keys~of~the~family~'line-numbers'~are~(in~
+ alphabetic~order):~
+ absolute,~false,~label-empty-lines,~resume,~skip-empty-lines,~
+ sep,~start~and~true.\\
+ That~key~will~be~ignored.
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\@@_msg_new:nn { Unknown~key~for~marker }
+ {
+ Unknown~key. \\
+ The~key~'marker / \l_keys_key_str'~is~unknown.\\
+ The~available~keys~of~the~family~'marker'~are~(in~
+ alphabetic~order):~ beginning,~end~and~include-lines.\\
+ That~key~will~be~ignored.
+ }
+% \end{macrocode}
+%
+%
+%
+% \begin{macrocode}
+\@@_msg_new:nn { bad~range~specification }
+ {
+ Incompatible~keys.\\
+ You~can't~specify~the~range~of~lines~to~include~by~using~both~
+ markers~and~explicit~number~of~lines.\\
+ Your~whole~file~'\l_@@_file_name_str'~will~be~included.
+ }
+% \end{macrocode}
+%
% \begin{macrocode}
-\msg_new:nnn { piton } { syntax~error }
+\@@_msg_new:nn { syntax~error }
{
Your~code~is~not~syntactically~correct.\\
It~won't~be~printed~in~the~PDF~file.
@@ -3611,12 +4227,43 @@
%
% \begin{macrocode}
\NewDocumentCommand \PitonSyntaxError { }
- { \msg_error:nn { piton } { syntax~error } }
+ { \@@_error:n { syntax~error } }
% \end{macrocode}
+%
+%
+% \begin{macrocode}
+\@@_msg_new:nn { begin~marker~not~found }
+ {
+ Marker~not~found.\\
+ The~range~'\l_@@_begin_range_str'~provided~to~the~
+ command~\token_to_str:N \PitonInputFile\ has~not~been~found.~
+ The~whole~file~'\l_@@_file_name_str'~will~be~inserted.
+ }
+% \end{macrocode}
+%
%
% \begin{macrocode}
-\msg_new:nnn { piton } { unknown~file }
+\@@_msg_new:nn { end~marker~not~found }
{
+ Marker~not~found.\\
+ The~marker~of~end~of~the~range~'\l_@@_end_range_str'~
+ provided~to~the~command~\token_to_str:N \PitonInputFile\
+ has~not~been~found.~The~file~'\l_@@_file_name_str'~will~
+ be~inserted~till~the~end.
+ }
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+\NewDocumentCommand \PitonBeginMarkerNotFound { }
+ { \@@_error:n { begin~marker~not~found } }
+\NewDocumentCommand \PitonEndMarkerNotFound { }
+ { \@@_error:n { end~marker~not~found } }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\@@_msg_new:nn { Unknown~file }
+ {
Unknown~file. \\
The~file~'#1'~is~unknown.\\
Your~command~\token_to_str:N \PitonInputFile\ will~be~discarded.
@@ -3633,15 +4280,15 @@
}
{
The~available~keys~are~(in~alphabetic~order):~
- all-line-numbers,~
auto-gobble,~
background-color,~
break-lines,~
break-lines-in-piton,~
break-lines-in-Piton,~
- continuation-symbol,~
+ continuation-symbol,~
continuation-symbol-on-indentation,~
end-of-broken-line,~
+ end-range,~
env-gobble,~
gobble,~
identifiers,~
@@ -3648,7 +4295,8 @@
indent-broken-lines,~
language,~
left-margin,~
- line-numbers,~
+ line-numbers/,~
+ marker/,~
prompt-background-color,~
resume,~
show-spaces,~
@@ -3661,11 +4309,10 @@
%
% \bigskip
% \begin{macrocode}
-\msg_new:nnn { piton } { label~with~lines~numbers }
+\@@_msg_new:nn { label~with~lines~numbers }
{
You~can't~use~the~command~\token_to_str:N \label\
- because~the~key~'line-numbers'~(or~'all-line-numbers')~
- is~not~active.\\
+ because~the~key~'line-numbers'~is~not~active.\\
If~you~go~on,~that~command~will~ignored.
}
% \end{macrocode}
@@ -3672,7 +4319,7 @@
%
% \bigskip
% \begin{macrocode}
-\msg_new:nnn { piton } { cr~not~allowed }
+\@@_msg_new:nn { cr~not~allowed }
{
You~can't~put~any~carriage~return~in~the~argument~
of~a~command~\c_backslash_str
@@ -3685,7 +4332,7 @@
%
% \bigskip
% \begin{macrocode}
-\msg_new:nnn { piton } { overlay~without~beamer }
+\@@_msg_new:nn { overlay~without~beamer }
{
You~can't~use~an~argument~<...>~for~your~command~
\token_to_str:N \PitonInputFile\ because~you~are~not~
@@ -3696,20 +4343,26 @@
%
% \bigskip
% \begin{macrocode}
-\msg_new:nnn { Piton } { Python~error }
+\@@_msg_new:nn { Python~error }
{ A~Python~error~has~been~detected. }
% \end{macrocode}
-%
+%
% \bigskip
-% \subsection{The Lua part of the implementation}
+% \subsubsection{We load piton.lua}
%
+%
% \bigskip
% \begin{macrocode}
-\ExplSyntaxOff
-\RequirePackage{luacode}
+\hook_gput_code:nnn { begindocument } { . }
+ { \lua_now:e { require("piton.lua") } }
+%</STY>
% \end{macrocode}
%
+% \bigskip
+% \subsection{The Lua part of the implementation}
%
+%
+%
% \bigskip
% The Lua code will be loaded via a |{luacode*}| environment. The environment
% is by itself a Lua block and the local declarations will be local to that
@@ -3716,13 +4369,9 @@
% 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}
+%<*LUA>
if piton.comment_latex == nil then piton.comment_latex = ">" end
piton.comment_latex = "#" .. piton.comment_latex
% \end{macrocode}
@@ -3773,7 +4422,7 @@
% with standard LaTeX catcodes for all the characters: the elements captured
% will be formatted as normal LaTeX codes. It's suitable for the ``LaTeX
% comments'' in the environments |{Piton}| and the elements beetween
-% ``|escape-inside|''. That function won't be much used.
+% |begin-escape| and |end-escape|. That function won't be much used.
% \begin{macrocode}
local function L(pattern)
return Ct ( C ( pattern ) )
@@ -3827,21 +4476,35 @@
%
% \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 |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.
+% escapes (and that chunks will be considered as normal LaTeX constructions).
+% 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(piton_begin_escape)
- * L ( ( 1 - P(piton_end_escape) ) ^ 1 )
- * P(piton_end_escape)
+Escape = P ( false )
+if piton.begin_escape ~= nil
+then
+ Escape =
+ P(piton.begin_escape)
+ * L ( ( 1 - P(piton.end_escape) ) ^ 1 )
+ * P(piton.end_escape)
+end
% \end{macrocode}
%
+% \begin{macrocode}
+EscapeMath = P ( false )
+if piton.begin_escape_math ~= nil
+then
+ EscapeMath =
+ P(piton.begin_escape_math)
+ * Lc ( "\\ensuremath{" )
+ * L ( ( 1 - P(piton.end_escape_math) ) ^ 1 )
+ * Lc ( "}" )
+ * P(piton.end_escape_math)
+end
+% \end{macrocode}
+%
% \vspace{1cm}
% The following line is mandatory.
% \begin{macrocode}
@@ -3907,13 +4570,11 @@
%
% \bigskip
% 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.
+% corresponding to the keys |begin-escape| and |end-escape|.
% \begin{macrocode}
local Word
-if piton_begin_escape ~= ''
-then Word = Q ( ( ( 1 - space - P(piton_begin_escape) - P(piton_end_escape) )
+if piton.begin_escape ~= nil -- before : ''
+then Word = Q ( ( ( 1 - space - P(piton.begin_escape) - P(piton.end_escape) )
- S "'\"\r[()]" - digit ) ^ 1 )
else Word = Q ( ( ( 1 - space ) - S "'\"\r[()]" - digit ) ^ 1 )
end
@@ -4624,7 +5285,7 @@
EOL
+ Space
+ Tab
- + Escape
+ + Escape + EscapeMath
+ CommentLaTeX
+ Beamer
+ LongString
@@ -5137,7 +5798,7 @@
EOL
+ Space
+ Tab
- + Escape
+ + Escape + EscapeMath
+ Beamer
+ TypeParameter
+ String + QuotedString + Char
@@ -5472,7 +6133,7 @@
EOL
+ Space
+ Tab
- + Escape
+ + Escape + EscapeMath
+ CommentLaTeX
+ Beamer
+ Preproc
@@ -5831,10 +6492,45 @@
'\\int_set:Nn \\l_@@_nb_non_empty_lines_int {' .. count .. '}' )
end
% \end{macrocode}
+%
%
+% \bigskip
+% The following function stores in |\l_@@_first_line_int| and
+% |\l_@@_last_line_int| the numbers of lines of the file |file_name|
+% corresponding to the strings |marker_beginning| and |marker_end|.
% \begin{macrocode}
-\end{luacode*}
+function piton.ComputeRange(marker_beginning,marker_end,file_name)
+ local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( marker_beginning )
+ local t = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( marker_end )
+ local first_line = -1
+ local count = 0
+ local last_found = false
+ for line in io.lines(file_name)
+ do if first_line == -1
+ then if string.sub(line,1,#s) == s
+ then first_line = count
+ end
+ else if string.sub(line,1,#t) == t
+ then last_found = true
+ break
+ end
+ end
+ count = count + 1
+ end
+ if first_line == -1
+ then tex.sprint("\\PitonBeginMarkerNotFound")
+ else if last_found == false
+ then tex.sprint("\\PitonEndMarkerNotFound")
+ end
+ end
+ tex.sprint(
+ luatexbase.catcodetables.expl ,
+ '\\int_set:Nn \\l_@@_first_line_int {' .. first_line .. ' + 2 }'
+ .. '\\int_set:Nn \\l_@@_last_line_int {' .. count .. ' }' )
+end
+%</LUA>
% \end{macrocode}
+%
%
%
% \vspace{1cm}
@@ -5855,6 +6551,22 @@
%
% \verb|https://github.com/fpantigny/piton|
%
+% \subsection*{Changes between versions 2.0 and 2.1}
+%
+% The key |line-numbers| has now subkeys |line-numbers/skip-empty-lines|,
+% |line-numbers/label-empty-lines|, etc.
+%
+% The key |all-line-numbers| is deprecated: use
+% |line-numbers/skip-empty-lines=false|.
+%
+% New system to import, with |\PitonInputFile|, only a part (of the file)
+% delimited by textual markers.
+%
+% New keys |begin-escape|, |end-escape|, |begin-escape-math| and |end-escape-math|.
+%
+% The key |escape-inside| is deprecated: use |begin-escape| and |end-escape|.
+%
+%
% \subsection*{Changes between versions 1.6 and 2.0}
%
% The extension \pkg{piton} nows supports the computer languages OCaml and C
Modified: trunk/Master/texmf-dist/source/lualatex/piton/piton.ins
===================================================================
--- trunk/Master/texmf-dist/source/lualatex/piton/piton.ins 2023-08-26 20:18:37 UTC (rev 68074)
+++ trunk/Master/texmf-dist/source/lualatex/piton/piton.ins 2023-08-26 20:18:56 UTC (rev 68075)
@@ -30,13 +30,16 @@
LaTeX version 2005/12/01 or later.
\endpreamble
-\generate{\file{piton.sty}{\from{piton.dtx}{package}}}
+\generate{\file{piton.sty}{\from{piton.dtx}{STY}}}
+\nopreamble
+\nopostamble
+\generate{\file{piton.lua}{\from{piton.dtx}{LUA}}}
\Msg{*********************************************************}
\Msg{*}
\Msg{* To finish the installation you have to move the}
\Msg{* following files into a directory searched by TeX:}
\Msg{*}
-\Msg{* \space\space piton.sty}
+\Msg{* \space\space piton.sty, piton.lua}
\Msg{*}
\Msg{* To produce the documentation run the file piton.dtx}
\Msg{* through LuaLaTeX.}
Added: trunk/Master/texmf-dist/tex/lualatex/piton/piton.lua
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/piton/piton.lua (rev 0)
+++ trunk/Master/texmf-dist/tex/lualatex/piton/piton.lua 2023-08-26 20:18:56 UTC (rev 68075)
@@ -0,0 +1,1232 @@
+
+
+if piton.comment_latex == nil then piton.comment_latex = ">" end
+piton.comment_latex = "#" .. piton.comment_latex
+function piton.open_brace ()
+ tex.sprint("{")
+end
+function piton.close_brace ()
+ tex.sprint("}")
+end
+local P, S, V, C, Ct, Cc = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc
+local Cf, Cs , Cg , Cmt , Cb = lpeg.Cf, lpeg.Cs, lpeg.Cg , lpeg.Cmt , lpeg.Cb
+local R = lpeg.R
+local function Q(pattern)
+ return Ct ( Cc ( luatexbase.catcodetables.CatcodeTableOther ) * C ( pattern ) )
+end
+local function L(pattern)
+ return Ct ( C ( pattern ) )
+end
+local function Lc(string)
+ return Cc ( { luatexbase.catcodetables.expl , string } )
+end
+local function K(style, pattern)
+ return
+ Lc ( "{\\PitonStyle{" .. style .. "}{" )
+ * Q ( pattern )
+ * Lc ( "}}" )
+end
+local function WithStyle(style,pattern)
+ return
+ Ct ( Cc "Open" * Cc ( "{\\PitonStyle{" .. style .. "}{" ) * Cc "}}" )
+ * pattern
+ * Ct ( Cc "Close" )
+end
+Escape = P ( false )
+if piton.begin_escape ~= nil
+then
+ Escape =
+ P(piton.begin_escape)
+ * L ( ( 1 - P(piton.end_escape) ) ^ 1 )
+ * P(piton.end_escape)
+end
+EscapeMath = P ( false )
+if piton.begin_escape_math ~= nil
+then
+ EscapeMath =
+ P(piton.begin_escape_math)
+ * Lc ( "\\ensuremath{" )
+ * L ( ( 1 - P(piton.end_escape_math) ) ^ 1 )
+ * Lc ( "}" )
+ * P(piton.end_escape_math)
+end
+lpeg.locale(lpeg)
+local alpha, digit = lpeg.alpha, lpeg.digit
+local space = P " "
+local letter = alpha + P "_"
+ + P "â" + P "à" + P "ç" + P "é" + P "è" + P "ê" + P "ë" + P "ï" + P "î"
+ + P "ô" + P "û" + P "ü" + P "Â" + P "À" + P "Ç" + P "É" + P "È" + P "Ê"
+ + P "Ë" + P "Ï" + P "Î" + P "Ô" + P "Û" + P "Ü"
+
+local alphanum = letter + digit
+local identifier = letter * alphanum ^ 0
+local Identifier = K ( 'Identifier' , identifier)
+local Number =
+ K ( 'Number' ,
+ ( digit^1 * P "." * digit^0 + digit^0 * P "." * digit^1 + digit^1 )
+ * ( S "eE" * S "+-" ^ -1 * digit^1 ) ^ -1
+ + digit^1
+ )
+local Word
+if piton.begin_escape ~= nil -- before : ''
+then Word = Q ( ( ( 1 - space - P(piton.begin_escape) - P(piton.end_escape) )
+ - S "'\"\r[()]" - digit ) ^ 1 )
+else Word = Q ( ( ( 1 - space ) - S "'\"\r[()]" - digit ) ^ 1 )
+end
+local Space = ( Q " " ) ^ 1
+
+local SkipSpace = ( Q " " ) ^ 0
+
+local Punct = Q ( S ".,:;!" )
+
+local Tab = P "\t" * Lc ( '\\l__piton_tab_tl' )
+local SpaceIndentation = Lc ( '\\__piton_an_indentation_space:' ) * ( Q " " )
+local Delim = Q ( S "[()]" )
+local VisualSpace = space * Lc "\\l__piton_space_tl"
+local Beamer = P ( false )
+local BeamerBeginEnvironments = P ( true )
+local BeamerEndEnvironments = P ( true )
+if piton_beamer
+then
+ local BeamerNamesEnvironments =
+ P "uncoverenv" + P "onlyenv" + P "visibleenv" + P "invisibleenv"
+ + P "alertenv" + P "actionenv"
+ BeamerBeginEnvironments =
+ ( space ^ 0 *
+ L
+ (
+ P "\\begin{" * BeamerNamesEnvironments * "}"
+ * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1
+ )
+ * P "\r"
+ ) ^ 0
+ BeamerEndEnvironments =
+ ( space ^ 0 *
+ L ( P "\\end{" * BeamerNamesEnvironments * P "}" )
+ * P "\r"
+ ) ^ 0
+ function OneBeamerEnvironment(name,lpeg)
+ return
+ Ct ( Cc "Open"
+ * C (
+ P ( "\\begin{" .. name .. "}" )
+ * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
+ )
+ * Cc ( "\\end{" .. name .. "}" )
+ )
+ * (
+ C ( ( 1 - P ( "\\end{" .. name .. "}" ) ) ^ 0 )
+ / ( function (s) return lpeg : match(s) end )
+ )
+ * P ( "\\end{" .. name .. "}" ) * Ct ( Cc "Close" )
+ end
+end
+local languages = { }
+local Operator =
+ K ( 'Operator' ,
+ P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":="
+ + P "//" + P "**" + S "-~+/*%=<>&.@|"
+ )
+
+local OperatorWord =
+ K ( 'Operator.Word' , P "in" + P "is" + P "and" + P "or" + P "not" )
+
+local Keyword =
+ K ( 'Keyword' ,
+ P "as" + P "assert" + P "break" + P "case" + P "class" + P "continue"
+ + P "def" + P "del" + P "elif" + P "else" + P "except" + P "exec"
+ + P "finally" + P "for" + P "from" + P "global" + P "if" + P "import"
+ + P "lambda" + P "non local" + P "pass" + P "return" + P "try"
+ + P "while" + P "with" + P "yield" + P "yield from" )
+ + K ( 'Keyword.Constant' ,P "True" + P "False" + P "None" )
+
+local Builtin =
+ K ( 'Name.Builtin' ,
+ P "__import__" + P "abs" + P "all" + P "any" + P "bin" + P "bool"
+ + P "bytearray" + P "bytes" + P "chr" + P "classmethod" + P "compile"
+ + P "complex" + P "delattr" + P "dict" + P "dir" + P "divmod"
+ + P "enumerate" + P "eval" + P "filter" + P "float" + P "format"
+ + P "frozenset" + P "getattr" + P "globals" + P "hasattr" + P "hash"
+ + P "hex" + P "id" + P "input" + P "int" + P "isinstance" + P "issubclass"
+ + P "iter" + P "len" + P "list" + P "locals" + P "map" + P "max"
+ + P "memoryview" + P "min" + P "next" + P "object" + P "oct" + P "open"
+ + P "ord" + P "pow" + P "print" + P "property" + P "range" + P "repr"
+ + P "reversed" + P "round" + P "set" + P "setattr" + P "slice" + P "sorted"
+ + P "staticmethod" + P "str" + P "sum" + P "super" + P "tuple" + P "type"
+ + P "vars" + P "zip" )
+
+local Exception =
+ K ( 'Exception' ,
+ P "ArithmeticError" + P "AssertionError" + P "AttributeError"
+ + P "BaseException" + P "BufferError" + P "BytesWarning" + P "DeprecationWarning"
+ + P "EOFError" + P "EnvironmentError" + P "Exception" + P "FloatingPointError"
+ + P "FutureWarning" + P "GeneratorExit" + P "IOError" + P "ImportError"
+ + P "ImportWarning" + P "IndentationError" + P "IndexError" + P "KeyError"
+ + P "KeyboardInterrupt" + P "LookupError" + P "MemoryError" + P "NameError"
+ + P "NotImplementedError" + P "OSError" + P "OverflowError"
+ + P "PendingDeprecationWarning" + P "ReferenceError" + P "ResourceWarning"
+ + P "RuntimeError" + P "RuntimeWarning" + P "StopIteration"
+ + P "SyntaxError" + P "SyntaxWarning" + P "SystemError" + P "SystemExit"
+ + P "TabError" + P "TypeError" + P "UnboundLocalError" + P "UnicodeDecodeError"
+ + P "UnicodeEncodeError" + P "UnicodeError" + P "UnicodeTranslateError"
+ + P "UnicodeWarning" + P "UserWarning" + P "ValueError" + P "VMSError"
+ + P "Warning" + P "WindowsError" + P "ZeroDivisionError"
+ + P "BlockingIOError" + P "ChildProcessError" + P "ConnectionError"
+ + P "BrokenPipeError" + P "ConnectionAbortedError" + P "ConnectionRefusedError"
+ + P "ConnectionResetError" + P "FileExistsError" + P "FileNotFoundError"
+ + P "InterruptedError" + P "IsADirectoryError" + P "NotADirectoryError"
+ + P "PermissionError" + P "ProcessLookupError" + P "TimeoutError"
+ + P "StopAsyncIteration" + P "ModuleNotFoundError" + P "RecursionError" )
+
+local RaiseException = K ( 'Keyword' , P "raise" ) * SkipSpace * Exception * Q ( P "(" )
+
+local Decorator = K ( 'Name.Decorator' , P "@" * letter^1 )
+local DefClass =
+ K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier )
+local ImportAs =
+ K ( 'Keyword' , P "import" )
+ * Space
+ * K ( 'Name.Namespace' ,
+ identifier * ( P "." * identifier ) ^ 0 )
+ * (
+ ( Space * K ( 'Keyword' , P "as" ) * Space
+ * K ( 'Name.Namespace' , identifier ) )
+ +
+ ( SkipSpace * Q ( P "," ) * SkipSpace
+ * K ( 'Name.Namespace' , identifier ) ) ^ 0
+ )
+local FromImport =
+ K ( 'Keyword' , P "from" )
+ * Space * K ( 'Name.Namespace' , identifier )
+ * Space * K ( 'Keyword' , P "import" )
+local PercentInterpol =
+ K ( 'String.Interpol' ,
+ P "%"
+ * ( P "(" * alphanum ^ 1 * P ")" ) ^ -1
+ * ( S "-#0 +" ) ^ 0
+ * ( digit ^ 1 + P "*" ) ^ -1
+ * ( P "." * ( digit ^ 1 + P "*" ) ) ^ -1
+ * ( S "HlL" ) ^ -1
+ * S "sdfFeExXorgiGauc%"
+ )
+local SingleShortString =
+ WithStyle ( 'String.Short' ,
+ Q ( P "f'" + P "F'" )
+ * (
+ K ( 'String.Interpol' , P "{" )
+ * K ( 'Interpol.Inside' , ( 1 - S "}':" ) ^ 0 )
+ * Q ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1
+ * K ( 'String.Interpol' , P "}" )
+ +
+ VisualSpace
+ +
+ Q ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 )
+ ) ^ 0
+ * Q ( P "'" )
+ +
+ Q ( P "'" + P "r'" + P "R'" )
+ * ( Q ( ( P "\\'" + 1 - S " '\r%" ) ^ 1 )
+ + VisualSpace
+ + PercentInterpol
+ + Q ( P "%" )
+ ) ^ 0
+ * Q ( P "'" ) )
+
+local DoubleShortString =
+ WithStyle ( 'String.Short' ,
+ Q ( P "f\"" + P "F\"" )
+ * (
+ K ( 'String.Interpol' , P "{" )
+ * Q ( ( 1 - S "}\":" ) ^ 0 , 'Interpol.Inside' )
+ * ( K ( 'String.Interpol' , P ":" ) * Q ( (1 - S "}:\"") ^ 0 ) ) ^ -1
+ * K ( 'String.Interpol' , P "}" )
+ +
+ VisualSpace
+ +
+ Q ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 )
+ ) ^ 0
+ * Q ( P "\"" )
+ +
+ Q ( P "\"" + P "r\"" + P "R\"" )
+ * ( Q ( ( P "\\\"" + 1 - S " \"\r%" ) ^ 1 )
+ + VisualSpace
+ + PercentInterpol
+ + Q ( P "%" )
+ ) ^ 0
+ * Q ( P "\"" ) )
+
+local ShortString = SingleShortString + DoubleShortString
+local balanced_braces =
+ P { "E" ,
+ E =
+ (
+ P "{" * V "E" * P "}"
+ +
+ ShortString
+ +
+ ( 1 - S "{}" )
+ ) ^ 0
+ }
+if piton_beamer
+then
+ Beamer =
+ L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 )
+ +
+ Ct ( Cc "Open"
+ * C (
+ (
+ P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
+ + P "\\invisible" + P "\\action"
+ )
+ * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
+ * P "{"
+ )
+ * Cc "}"
+ )
+ * ( C ( balanced_braces ) / (function (s) return MainLoopPython:match(s) end ) )
+ * P "}" * Ct ( Cc "Close" )
+ + OneBeamerEnvironment ( "uncoverenv" , MainLoopPython )
+ + OneBeamerEnvironment ( "onlyenv" , MainLoopPython )
+ + OneBeamerEnvironment ( "visibleenv" , MainLoopPython )
+ + OneBeamerEnvironment ( "invisibleenv" , MainLoopPython )
+ + OneBeamerEnvironment ( "alertenv" , MainLoopPython )
+ + OneBeamerEnvironment ( "actionenv" , MainLoopPython )
+ +
+ L (
+ ( P "\\alt" )
+ * P "<" * (1 - P ">") ^ 0 * P ">"
+ * P "{"
+ )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}{" )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}" )
+ +
+ L (
+ ( P "\\temporal" )
+ * P "<" * (1 - P ">") ^ 0 * P ">"
+ * P "{"
+ )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}{" )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}{" )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}" )
+end
+local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\__piton_prompt:' ) ) ^ -1
+local Prompt = K ( 'Prompt' , ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1 )
+local EOL =
+ P "\r"
+ *
+ (
+ ( space^0 * -1 )
+ +
+ Ct (
+ Cc "EOL"
+ *
+ Ct (
+ Lc "\\__piton_end_line:"
+ * BeamerEndEnvironments
+ * BeamerBeginEnvironments
+ * PromptHastyDetection
+ * Lc "\\__piton_newline: \\__piton_begin_line:"
+ * Prompt
+ )
+ )
+ )
+ *
+ SpaceIndentation ^ 0
+local SingleLongString =
+ WithStyle ( 'String.Long' ,
+ ( Q ( S "fF" * P "'''" )
+ * (
+ K ( 'String.Interpol' , P "{" )
+ * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "'''" ) ^ 0 )
+ * Q ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1
+ * K ( 'String.Interpol' , P "}" )
+ +
+ Q ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 )
+ +
+ EOL
+ ) ^ 0
+ +
+ Q ( ( S "rR" ) ^ -1 * P "'''" )
+ * (
+ Q ( ( 1 - P "'''" - S "\r%" ) ^ 1 )
+ +
+ PercentInterpol
+ +
+ P "%"
+ +
+ EOL
+ ) ^ 0
+ )
+ * Q ( P "'''" ) )
+
+local DoubleLongString =
+ WithStyle ( 'String.Long' ,
+ (
+ Q ( S "fF" * P "\"\"\"" )
+ * (
+ K ( 'String.Interpol', P "{" )
+ * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 )
+ * Q ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1
+ * K ( 'String.Interpol' , P "}" )
+ +
+ Q ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 )
+ +
+ EOL
+ ) ^ 0
+ +
+ Q ( ( S "rR" ) ^ -1 * P "\"\"\"" )
+ * (
+ Q ( ( 1 - P "\"\"\"" - S "%\r" ) ^ 1 )
+ +
+ PercentInterpol
+ +
+ P "%"
+ +
+ EOL
+ ) ^ 0
+ )
+ * Q ( P "\"\"\"" )
+ )
+local LongString = SingleLongString + DoubleLongString
+local StringDoc =
+ K ( 'String.Doc' , P "\"\"\"" )
+ * ( K ( 'String.Doc' , (1 - P "\"\"\"" - P "\r" ) ^ 0 ) * EOL
+ * Tab ^ 0
+ ) ^ 0
+ * K ( 'String.Doc' , ( 1 - P "\"\"\"" - P "\r" ) ^ 0 * P "\"\"\"" )
+local CommentMath =
+ P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$"
+
+local Comment =
+ WithStyle ( 'Comment' ,
+ Q ( P "#" )
+ * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 )
+ * ( EOL + -1 )
+local CommentLaTeX =
+ P(piton.comment_latex)
+ * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces"
+ * L ( ( 1 - P "\r" ) ^ 0 )
+ * Lc "}}"
+ * ( EOL + -1 )
+local expression =
+ P { "E" ,
+ E = ( P "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * P "'"
+ + P "\"" * (P "\\\"" + 1 - S "\"\r" ) ^ 0 * P "\""
+ + P "{" * V "F" * P "}"
+ + P "(" * V "F" * P ")"
+ + P "[" * V "F" * P "]"
+ + ( 1 - S "{}()[]\r," ) ) ^ 0 ,
+ F = ( P "{" * V "F" * P "}"
+ + P "(" * V "F" * P ")"
+ + P "[" * V "F" * P "]"
+ + ( 1 - S "{}()[]\r\"'" ) ) ^ 0
+ }
+local Param =
+ SkipSpace * Identifier * SkipSpace
+ * (
+ K ( 'InitialValues' , P "=" * expression )
+ + Q ( P ":" ) * SkipSpace * K ( 'Name.Type' , letter ^ 1 )
+ ) ^ -1
+local Params = ( Param * ( Q "," * Param ) ^ 0 ) ^ -1
+local DefFunction =
+ K ( 'Keyword' , P "def" )
+ * Space
+ * K ( 'Name.Function.Internal' , identifier )
+ * SkipSpace
+ * Q ( P "(" ) * Params * Q ( P ")" )
+ * SkipSpace
+ * ( Q ( P "->" ) * SkipSpace * K ( 'Name.Type' , identifier ) ) ^ -1
+ * K ( 'ParseAgain' , ( 1 - S ":\r" )^0 )
+ * Q ( P ":" )
+ * ( SkipSpace
+ * ( EOL + CommentLaTeX + Comment ) -- in all cases, that contains an EOL
+ * Tab ^ 0
+ * SkipSpace
+ * StringDoc ^ 0 -- there may be additionnal docstrings
+ ) ^ -1
+local ExceptionInConsole = Exception * Q ( ( 1 - P "\r" ) ^ 0 ) * EOL
+local MainPython =
+ EOL
+ + Space
+ + Tab
+ + Escape + EscapeMath
+ + CommentLaTeX
+ + Beamer
+ + LongString
+ + Comment
+ + ExceptionInConsole
+ + Delim
+ + Operator
+ + OperatorWord * ( Space + Punct + Delim + EOL + -1 )
+ + ShortString
+ + Punct
+ + FromImport
+ + RaiseException
+ + DefFunction
+ + DefClass
+ + Keyword * ( Space + Punct + Delim + EOL + -1 )
+ + Decorator
+ + Builtin * ( Space + Punct + Delim + EOL + -1 )
+ + Identifier
+ + Number
+ + Word
+MainLoopPython =
+ ( ( space^1 * -1 )
+ + MainPython
+ ) ^ 0
+local python = P ( true )
+
+python =
+ Ct (
+ ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1
+ * BeamerBeginEnvironments
+ * PromptHastyDetection
+ * Lc '\\__piton_begin_line:'
+ * Prompt
+ * SpaceIndentation ^ 0
+ * MainLoopPython
+ * -1
+ * Lc '\\__piton_end_line:'
+ )
+languages['python'] = python
+local Delim = Q ( P "[|" + P "|]" + S "[()]" )
+local Punct = Q ( S ",:;!" )
+local cap_identifier = R "AZ" * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0
+local Constructor = K ( 'Name.Constructor' , cap_identifier )
+local ModuleType = K ( 'Name.Type' , cap_identifier )
+local identifier =
+ ( R "az" + P "_") * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0
+local Identifier = K ( 'Identifier' , identifier )
+local expression_for_fields =
+ P { "E" ,
+ E = ( P "{" * V "F" * P "}"
+ + P "(" * V "F" * P ")"
+ + P "[" * V "F" * P "]"
+ + P "\"" * (P "\\\"" + 1 - S "\"\r" )^0 * P "\""
+ + P "'" * ( P "\\'" + 1 - S "'\r" )^0 * P "'"
+ + ( 1 - S "{}()[]\r;" ) ) ^ 0 ,
+ F = ( P "{" * V "F" * P "}"
+ + P "(" * V "F" * P ")"
+ + P "[" * V "F" * P "]"
+ + ( 1 - S "{}()[]\r\"'" ) ) ^ 0
+ }
+local OneFieldDefinition =
+ ( K ( 'KeyWord' , P "mutable" ) * SkipSpace ) ^ -1
+ * K ( 'Name.Field' , identifier ) * SkipSpace
+ * Q ":" * SkipSpace
+ * K ( 'Name.Type' , expression_for_fields )
+ * SkipSpace
+
+local OneField =
+ K ( 'Name.Field' , identifier ) * SkipSpace
+ * Q "=" * SkipSpace
+ * ( C ( expression_for_fields ) / ( function (s) return LoopOCaml:match(s) end ) )
+ * SkipSpace
+
+local Record =
+ Q "{" * SkipSpace
+ *
+ (
+ OneFieldDefinition * ( Q ";" * SkipSpace * OneFieldDefinition ) ^ 0
+ +
+ OneField * ( Q ";" * SkipSpace * OneField ) ^ 0
+ )
+ *
+ Q "}"
+local DotNotation =
+ (
+ K ( 'Name.Module' , cap_identifier )
+ * Q "."
+ * ( Identifier + Constructor + Q "(" + Q "[" + Q "{" )
+
+ +
+ Identifier
+ * Q "."
+ * K ( 'Name.Field' , identifier )
+ )
+ * ( Q "." * K ( 'Name.Field' , identifier ) ) ^ 0
+local Operator =
+ K ( 'Operator' ,
+ P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":="
+ + P "||" + P "&&" + P "//" + P "**" + P ";;" + P "::" + P "->"
+ + P "+." + P "-." + P "*." + P "/."
+ + S "-~+/*%=<>&@|"
+ )
+
+local OperatorWord =
+ K ( 'Operator.Word' ,
+ P "and" + P "asr" + P "land" + P "lor" + P "lsl" + P "lxor"
+ + P "mod" + P "or" )
+
+local Keyword =
+ K ( 'Keyword' ,
+ P "assert" + P "as" + P "begin" + P "class" + P "constraint" + P "done"
+ + P "downto" + P "do" + P "else" + P "end" + P "exception" + P "external"
+ + P "for" + P "function" + P "functor" + P "fun" + P "if"
+ + P "include" + P "inherit" + P "initializer" + P "in" + P "lazy" + P "let"
+ + P "match" + P "method" + P "module" + P "mutable" + P "new" + P "object"
+ + P "of" + P "open" + P "private" + P "raise" + P "rec" + P "sig"
+ + P "struct" + P "then" + P "to" + P "try" + P "type"
+ + P "value" + P "val" + P "virtual" + P "when" + P "while" + P "with" )
+ + K ( 'Keyword.Constant' , P "true" + P "false" )
+
+local Builtin =
+ K ( 'Name.Builtin' , P "not" + P "incr" + P "decr" + P "fst" + P "snd" )
+local Exception =
+ K ( 'Exception' ,
+ P "Division_by_zero" + P "End_of_File" + P "Failure"
+ + P "Invalid_argument" + P "Match_failure" + P "Not_found"
+ + P "Out_of_memory" + P "Stack_overflow" + P "Sys_blocked_io"
+ + P "Sys_error" + P "Undefined_recursive_module" )
+local Char =
+ K ( 'String.Short' , P "'" * ( ( 1 - P "'" ) ^ 0 + P "\\'" ) * P "'" )
+local balanced_braces =
+ P { "E" ,
+ E =
+ (
+ P "{" * V "E" * P "}"
+ +
+ P "\"" * ( 1 - S "\"" ) ^ 0 * P "\"" -- OCaml strings
+ +
+ ( 1 - S "{}" )
+ ) ^ 0
+ }
+if piton_beamer
+then
+ Beamer =
+ L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 )
+ +
+ Ct ( Cc "Open"
+ * C (
+ (
+ P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
+ + P "\\invisible" + P "\\action"
+ )
+ * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
+ * P "{"
+ )
+ * Cc "}"
+ )
+ * ( C ( balanced_braces ) / (function (s) return MainLoopOCaml:match(s) end ) )
+ * P "}" * Ct ( Cc "Close" )
+ + OneBeamerEnvironment ( "uncoverenv" , MainLoopOCaml )
+ + OneBeamerEnvironment ( "onlyenv" , MainLoopOCaml )
+ + OneBeamerEnvironment ( "visibleenv" , MainLoopOCaml )
+ + OneBeamerEnvironment ( "invisibleenv" , MainLoopOCaml )
+ + OneBeamerEnvironment ( "alertenv" , MainLoopOCaml )
+ + OneBeamerEnvironment ( "actionenv" , MainLoopOCaml )
+ +
+ L (
+ ( P "\\alt" )
+ * P "<" * (1 - P ">") ^ 0 * P ">"
+ * P "{"
+ )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}{" )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}" )
+ +
+ L (
+ ( P "\\temporal" )
+ * P "<" * (1 - P ">") ^ 0 * P ">"
+ * P "{"
+ )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}{" )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}{" )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}" )
+end
+local EOL =
+ P "\r"
+ *
+ (
+ ( space^0 * -1 )
+ +
+ Ct (
+ Cc "EOL"
+ *
+ Ct (
+ Lc "\\__piton_end_line:"
+ * BeamerEndEnvironments
+ * BeamerBeginEnvironments
+ * PromptHastyDetection
+ * Lc "\\__piton_newline: \\__piton_begin_line:"
+ * Prompt
+ )
+ )
+ )
+ *
+ SpaceIndentation ^ 0
+local ocaml_string =
+ Q ( P "\"" )
+ * (
+ VisualSpace
+ +
+ Q ( ( 1 - S " \"\r" ) ^ 1 )
+ +
+ EOL
+ ) ^ 0
+ * Q ( P "\"" )
+local String = WithStyle ( 'String.Long' , ocaml_string )
+local ext = ( R "az" + P "_" ) ^ 0
+local open = "{" * Cg(ext, 'init') * "|"
+local close = "|" * C(ext) * "}"
+local closeeq =
+ Cmt ( close * Cb('init'),
+ function (s, i, a, b) return a==b end )
+local QuotedStringBis =
+ WithStyle ( 'String.Long' ,
+ (
+ VisualSpace
+ +
+ Q ( ( 1 - S " \r" ) ^ 1 )
+ +
+ EOL
+ ) ^ 0 )
+
+local QuotedString =
+ C ( open * ( 1 - closeeq ) ^ 0 * close ) /
+ ( function (s) return QuotedStringBis : match(s) end )
+local Comment =
+ WithStyle ( 'Comment' ,
+ P {
+ "A" ,
+ A = Q "(*"
+ * ( V "A"
+ + Q ( ( 1 - P "(*" - P "*)" - S "\r$\"" ) ^ 1 ) -- $
+ + ocaml_string
+ + P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" -- $
+ + EOL
+ ) ^ 0
+ * Q "*)"
+ } )
+local balanced_parens =
+ P { "E" ,
+ E =
+ (
+ P "(" * V "E" * P ")"
+ +
+ ( 1 - S "()" )
+ ) ^ 0
+ }
+local Argument =
+ K ( 'Identifier' , identifier )
+ + Q "(" * SkipSpace
+ * K ( 'Identifier' , identifier ) * SkipSpace
+ * Q ":" * SkipSpace
+ * K ( 'Name.Type' , balanced_parens ) * SkipSpace
+ * Q ")"
+local DefFunction =
+ K ( 'Keyword' , P "let open" )
+ * Space
+ * K ( 'Name.Module' , cap_identifier )
+ +
+ K ( 'Keyword' , P "let rec" + P "let" + P "and" )
+ * Space
+ * K ( 'Name.Function.Internal' , identifier )
+ * Space
+ * (
+ Q "=" * SkipSpace * K ( 'Keyword' , P "function" )
+ +
+ Argument
+ * ( SkipSpace * Argument ) ^ 0
+ * (
+ SkipSpace
+ * Q ":"
+ * K ( 'Name.Type' , ( 1 - P "=" ) ^ 0 )
+ ) ^ -1
+ )
+local DefModule =
+ K ( 'Keyword' , P "module" ) * Space
+ *
+ (
+ K ( 'Keyword' , P "type" ) * Space
+ * K ( 'Name.Type' , cap_identifier )
+ +
+ K ( 'Name.Module' , cap_identifier ) * SkipSpace
+ *
+ (
+ Q "(" * SkipSpace
+ * K ( 'Name.Module' , cap_identifier ) * SkipSpace
+ * Q ":" * SkipSpace
+ * K ( 'Name.Type' , cap_identifier ) * SkipSpace
+ *
+ (
+ Q "," * SkipSpace
+ * K ( 'Name.Module' , cap_identifier ) * SkipSpace
+ * Q ":" * SkipSpace
+ * K ( 'Name.Type' , cap_identifier ) * SkipSpace
+ ) ^ 0
+ * Q ")"
+ ) ^ -1
+ *
+ (
+ Q "=" * SkipSpace
+ * K ( 'Name.Module' , cap_identifier ) * SkipSpace
+ * Q "("
+ * K ( 'Name.Module' , cap_identifier ) * SkipSpace
+ *
+ (
+ Q ","
+ *
+ K ( 'Name.Module' , cap_identifier ) * SkipSpace
+ ) ^ 0
+ * Q ")"
+ ) ^ -1
+ )
+ +
+ K ( 'Keyword' , P "include" + P "open" )
+ * Space * K ( 'Name.Module' , cap_identifier )
+local TypeParameter = K ( 'TypeParameter' , P "'" * alpha * # ( 1 - P "'" ) )
+MainOCaml =
+ EOL
+ + Space
+ + Tab
+ + Escape + EscapeMath
+ + Beamer
+ + TypeParameter
+ + String + QuotedString + Char
+ + Comment
+ + Delim
+ + Operator
+ + Punct
+ + FromImport
+ + Exception
+ + DefFunction
+ + DefModule
+ + Record
+ + Keyword * ( Space + Punct + Delim + EOL + -1 )
+ + OperatorWord * ( Space + Punct + Delim + EOL + -1 )
+ + Builtin * ( Space + Punct + Delim + EOL + -1 )
+ + DotNotation
+ + Constructor
+ + Identifier
+ + Number
+ + Word
+
+LoopOCaml = MainOCaml ^ 0
+
+MainLoopOCaml =
+ ( ( space^1 * -1 )
+ + MainOCaml
+ ) ^ 0
+local ocaml = P ( true )
+
+ocaml =
+ Ct (
+ ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1
+ * BeamerBeginEnvironments
+ * Lc ( '\\__piton_begin_line:' )
+ * SpaceIndentation ^ 0
+ * MainLoopOCaml
+ * -1
+ * Lc ( '\\__piton_end_line:' )
+ )
+languages['ocaml'] = ocaml
+local Operator =
+ K ( 'Operator' ,
+ P "!=" + P "==" + P "<<" + P ">>" + P "<=" + P ">="
+ + P "||" + P "&&" + S "-~+/*%=<>&.@|!"
+ )
+
+local Keyword =
+ K ( 'Keyword' ,
+ P "alignas" + P "asm" + P "auto" + P "break" + P "case" + P "catch"
+ + P "class" + P "const" + P "constexpr" + P "continue"
+ + P "decltype" + P "do" + P "else" + P "enum" + P "extern"
+ + P "for" + P "goto" + P "if" + P "nexcept" + P "private" + P "public"
+ + P "register" + P "restricted" + P "return" + P "static" + P "static_assert"
+ + P "struct" + P "switch" + P "thread_local" + P "throw" + P "try"
+ + P "typedef" + P "union" + P "using" + P "virtual" + P "volatile"
+ + P "while"
+ )
+ + K ( 'Keyword.Constant' ,
+ P "default" + P "false" + P "NULL" + P "nullptr" + P "true"
+ )
+
+local Builtin =
+ K ( 'Name.Builtin' ,
+ P "alignof" + P "malloc" + P "printf" + P "scanf" + P "sizeof"
+ )
+
+local Type =
+ K ( 'Name.Type' ,
+ P "bool" + P "char" + P "char16_t" + P "char32_t" + P "double"
+ + P "float" + P "int" + P "int8_t" + P "int16_t" + P "int32_t"
+ + P "int64_t" + P "long" + P "short" + P "signed" + P "unsigned"
+ + P "void" + P "wchar_t"
+ )
+
+local DefFunction =
+ Type
+ * Space
+ * K ( 'Name.Function.Internal' , identifier )
+ * SkipSpace
+ * # P "("
+local DefClass =
+ K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier )
+local String =
+ WithStyle ( 'String.Long' ,
+ Q "\""
+ * ( VisualSpace
+ + K ( 'String.Interpol' ,
+ P "%" * ( S "difcspxXou" + P "ld" + P "li" + P "hd" + P "hi" )
+ )
+ + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 )
+ ) ^ 0
+ * Q "\""
+ )
+local balanced_braces =
+ P { "E" ,
+ E =
+ (
+ P "{" * V "E" * P "}"
+ +
+ String
+ +
+ ( 1 - S "{}" )
+ ) ^ 0
+ }
+if piton_beamer
+then
+ Beamer =
+ L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 )
+ +
+ Ct ( Cc "Open"
+ * C (
+ (
+ P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
+ + P "\\invisible" + P "\\action"
+ )
+ * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
+ * P "{"
+ )
+ * Cc "}"
+ )
+ * ( C ( balanced_braces ) / (function (s) return MainLoopC:match(s) end ) )
+ * P "}" * Ct ( Cc "Close" )
+ + OneBeamerEnvironment ( "uncoverenv" , MainLoopC )
+ + OneBeamerEnvironment ( "onlyenv" , MainLoopC )
+ + OneBeamerEnvironment ( "visibleenv" , MainLoopC )
+ + OneBeamerEnvironment ( "invisibleenv" , MainLoopC )
+ + OneBeamerEnvironment ( "alertenv" , MainLoopC )
+ + OneBeamerEnvironment ( "actionenv" , MainLoopC )
+ +
+ L (
+ ( P "\\alt" )
+ * P "<" * (1 - P ">") ^ 0 * P ">"
+ * P "{"
+ )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}{" )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}" )
+ +
+ L (
+ ( P "\\temporal" )
+ * P "<" * (1 - P ">") ^ 0 * P ">"
+ * P "{"
+ )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}{" )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}{" )
+ * K ( 'ParseAgain.noCR' , balanced_braces )
+ * L ( P "}" )
+end
+local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\__piton_prompt:' ) ) ^ -1
+local Prompt = K ( 'Prompt' , ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1 )
+local EOL =
+ P "\r"
+ *
+ (
+ ( space^0 * -1 )
+ +
+ Ct (
+ Cc "EOL"
+ *
+ Ct (
+ Lc "\\__piton_end_line:"
+ * BeamerEndEnvironments
+ * BeamerBeginEnvironments
+ * PromptHastyDetection
+ * Lc "\\__piton_newline: \\__piton_begin_line:"
+ * Prompt
+ )
+ )
+ )
+ *
+ SpaceIndentation ^ 0
+local Preproc =
+ K ( 'Preproc' , P "#" * (1 - P "\r" ) ^ 0 ) * ( EOL + -1 )
+local CommentMath =
+ P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$"
+
+local Comment =
+ WithStyle ( 'Comment' ,
+ Q ( P "//" )
+ * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 )
+ * ( EOL + -1 )
+
+local LongComment =
+ WithStyle ( 'Comment' ,
+ Q ( P "/*" )
+ * ( CommentMath + Q ( ( 1 - P "*/" - S "$\r" ) ^ 1 ) + EOL ) ^ 0
+ * Q ( P "*/" )
+ ) -- $
+local CommentLaTeX =
+ P(piton.comment_latex)
+ * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces"
+ * L ( ( 1 - P "\r" ) ^ 0 )
+ * Lc "}}"
+ * ( EOL + -1 )
+local MainC =
+ EOL
+ + Space
+ + Tab
+ + Escape + EscapeMath
+ + CommentLaTeX
+ + Beamer
+ + Preproc
+ + Comment + LongComment
+ + Delim
+ + Operator
+ + String
+ + Punct
+ + DefFunction
+ + DefClass
+ + Type * ( Q ( "*" ) ^ -1 + Space + Punct + Delim + EOL + -1 )
+ + Keyword * ( Space + Punct + Delim + EOL + -1 )
+ + Builtin * ( Space + Punct + Delim + EOL + -1 )
+ + Identifier
+ + Number
+ + Word
+MainLoopC =
+ ( ( space^1 * -1 )
+ + MainC
+ ) ^ 0
+languageC =
+ Ct (
+ ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1
+ * BeamerBeginEnvironments
+ * PromptHastyDetection
+ * Lc '\\__piton_begin_line:'
+ * Prompt
+ * SpaceIndentation ^ 0
+ * MainLoopC
+ * -1
+ * Lc '\\__piton_end_line:'
+ )
+languages['c'] = languageC
+function piton.Parse(language,code)
+ local t = languages[language] : match ( code )
+ if t == nil
+ then
+ tex.sprint("\\PitonSyntaxError")
+ return -- to exit in force the function
+ end
+ local left_stack = {}
+ local right_stack = {}
+ for _ , one_item in ipairs(t)
+ do
+ if one_item[1] == "EOL"
+ then
+ for _ , s in ipairs(right_stack)
+ do tex.sprint(s)
+ end
+ for _ , s in ipairs(one_item[2])
+ do tex.tprint(s)
+ end
+ for _ , s in ipairs(left_stack)
+ do tex.sprint(s)
+ end
+ else
+ if one_item[1] == "Open"
+ then
+ tex.sprint( one_item[2] )
+ table.insert(left_stack,one_item[2])
+ table.insert(right_stack,one_item[3])
+ else
+ if one_item[1] == "Close"
+ then
+ tex.sprint( right_stack[#right_stack] )
+ left_stack[#left_stack] = nil
+ right_stack[#right_stack] = nil
+ else
+ tex.tprint(one_item)
+ end
+ end
+ end
+ end
+end
+function piton.ParseFile(language,name,first_line,last_line)
+ local s = ''
+ local i = 0
+ for line in io.lines(name)
+ do i = i + 1
+ if i >= first_line
+ then s = s .. '\r' .. line
+ end
+ if i >= last_line then break end
+ end
+ if string.byte(s,1) == 13
+ then if string.byte(s,2) == 239
+ then if string.byte(s,3) == 187
+ then if string.byte(s,4) == 191
+ then s = string.sub(s,5,-1)
+ end
+ end
+ end
+ end
+ piton.Parse(language,s)
+end
+function piton.ParseBis(language,code)
+ local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( code )
+ return piton.Parse(language,s)
+end
+function piton.ParseTer(language,code)
+ local s = ( Cs ( ( P '\\__piton_breakable_space:' / ' ' + 1 ) ^ 0 ) )
+ : match ( code )
+ return piton.Parse(language,s)
+end
+local function gobble(n,code)
+ function concat(acc,new_value)
+ return acc .. new_value
+ end
+ if n==0
+ then return code
+ else
+ return Cf (
+ Cc ( "" ) *
+ ( 1 - P "\r" ) ^ (-n) * C ( ( 1 - P "\r" ) ^ 0 )
+ * ( C ( P "\r" )
+ * ( 1 - P "\r" ) ^ (-n)
+ * C ( ( 1 - P "\r" ) ^ 0 )
+ ) ^ 0 ,
+ concat
+ ) : match ( code )
+ end
+end
+local function add(acc,new_value)
+ return acc + new_value
+end
+local AutoGobbleLPEG =
+ ( space ^ 0 * P "\r" ) ^ -1
+ * Cf (
+ (
+ ( P " " ) ^ 0 * P "\r"
+ +
+ Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add )
+ * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 * P "\r"
+ ) ^ 0
+ *
+ ( Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add )
+ * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 ,
+ math.min
+ )
+local TabsAutoGobbleLPEG =
+ ( space ^ 0 * P "\r" ) ^ -1
+ * Cf (
+ (
+ ( P "\t" ) ^ 0 * P "\r"
+ +
+ Cf ( Cc(0) * ( P "\t" * Cc(1) ) ^ 0 , add )
+ * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 * P "\r"
+ ) ^ 0
+ *
+ ( Cf ( Cc(0) * ( P "\t" * Cc(1) ) ^ 0 , add )
+ * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 ,
+ math.min
+ )
+local EnvGobbleLPEG =
+ ( ( 1 - P "\r" ) ^ 0 * P "\r" ) ^ 0
+ * Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add ) * -1
+function piton.GobbleParse(language,n,code)
+ if n==-1
+ then n = AutoGobbleLPEG : match(code)
+ else if n==-2
+ then n = EnvGobbleLPEG : match(code)
+ else if n==-3
+ then n = TabsAutoGobbleLPEG : match(code)
+ end
+ end
+ end
+ piton.Parse(language,gobble(n,code))
+end
+function piton.CountLines(code)
+ local count = 0
+ for i in code : gmatch ( "\r" ) do count = count + 1 end
+ tex.sprint(
+ luatexbase.catcodetables.expl ,
+ '\\int_set:Nn \\l__piton_nb_lines_int {' .. count .. '}' )
+end
+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__piton_nb_non_empty_lines_int {' .. count .. '}' )
+end
+function piton.CountLinesFile(name)
+ local count = 0
+ for line in io.lines(name) do count = count + 1 end
+ tex.sprint(
+ luatexbase.catcodetables.expl ,
+ '\\int_set:Nn \\l__piton_nb_lines_int {' .. count .. '}' )
+end
+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__piton_nb_non_empty_lines_int {' .. count .. '}' )
+end
+function piton.ComputeRange(marker_beginning,marker_end,file_name)
+ local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( marker_beginning )
+ local t = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( marker_end )
+ local first_line = -1
+ local count = 0
+ local last_found = false
+ for line in io.lines(file_name)
+ do if first_line == -1
+ then if string.sub(line,1,#s) == s
+ then first_line = count
+ end
+ else if string.sub(line,1,#t) == t
+ then last_found = true
+ break
+ end
+ end
+ count = count + 1
+ end
+ if first_line == -1
+ then tex.sprint("\\PitonBeginMarkerNotFound")
+ else if last_found == false
+ then tex.sprint("\\PitonEndMarkerNotFound")
+ end
+ end
+ tex.sprint(
+ luatexbase.catcodetables.expl ,
+ '\\int_set:Nn \\l__piton_first_line_int {' .. first_line .. ' + 2 }'
+ .. '\\int_set:Nn \\l__piton_last_line_int {' .. count .. ' }' )
+end
+
Property changes on: trunk/Master/texmf-dist/tex/lualatex/piton/piton.lua
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/tex/lualatex/piton/piton.sty
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/piton/piton.sty 2023-08-26 20:18:37 UTC (rev 68074)
+++ trunk/Master/texmf-dist/tex/lualatex/piton/piton.sty 2023-08-26 20:18:56 UTC (rev 68075)
@@ -4,7 +4,7 @@
%%
%% The original source files were:
%%
-%% piton.dtx (with options: `package')
+%% piton.dtx (with options: `STY')
%%
%% Copyright (C) 2022-2023 by F. Pantigny
%%
@@ -18,8 +18,8 @@
%% and version 1.3 or later is part of all distributions of
%% LaTeX version 2005/12/01 or later.
%%
-\def\myfileversion{2.0}
-\def\myfiledate{2023/08/01}
+\def\myfileversion{2.1}
+\def\myfiledate{2023/08/26}
\NeedsTeXFormat{LaTeX2e}
@@ -29,7 +29,14 @@
{\myfiledate}
{\myfileversion}
{Highlight Python codes with LPEG on LuaLaTeX}
-\msg_new:nnn { piton } { LuaLaTeX~mandatory }
+\cs_new_protected:Npn \__piton_error:n { \msg_error:nn { piton } }
+\cs_new_protected:Npn \__piton_warning:n { \msg_warning:nn { piton } }
+\cs_new_protected:Npn \__piton_error:nn { \msg_error:nnn { piton } }
+\cs_new_protected:Npn \__piton_error:nnn { \msg_error:nnnn { piton } }
+\cs_new_protected:Npn \__piton_fatal:n { \msg_fatal:nn { piton } }
+\cs_new_protected:Npn \__piton_fatal:nn { \msg_fatal:nnn { piton } }
+\cs_new_protected:Npn \__piton_msg_new:nn { \msg_new:nnn { piton } }
+\__piton_msg_new:nn { LuaLaTeX~mandatory }
{
LuaLaTeX~is~mandatory.\\
The~package~'piton'~requires~the~engine~LuaLaTeX.\\
@@ -39,46 +46,58 @@
}
\sys_if_engine_luatex:F { \msg_critical:nn { piton } { LuaLaTeX~mandatory } }
\RequirePackage { luatexbase }
-\bool_new:N \c__piton_footnotehyper_bool
-\bool_new:N \c__piton_footnote_bool
-\bool_new:N \c__piton_math_comments_bool
-\bool_new:N \c__piton_beamer_bool
+\__piton_msg_new:nn { piton.lua~not~found }
+ {
+ The~file~'piton.lua'~can't~be~found.\\
+ The package~'piton'~won't be loaded.
+ }
+\file_if_exist:nF { piton.lua }
+ { \msg_critical:nn { piton } { piton.lua~not~found } }
+\bool_new:N \g__piton_footnotehyper_bool
+\bool_new:N \g__piton_footnote_bool
+\bool_new:N \g__piton_math_comments_bool
+\bool_new:N \g__piton_beamer_bool
+\tl_new:N \g__piton_escape_inside_tl
\keys_define:nn { piton / package }
{
- footnote .bool_set:N = \c__piton_footnote_bool ,
- footnotehyper .bool_set:N = \c__piton_footnotehyper_bool ,
- escape-inside .tl_set:N = \c__piton_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__piton_math_comments_bool ,
- math-comments .default:n = true ,
- beamer .bool_set:N = \c__piton_beamer_bool ,
- beamer .default:n = true ,
- unknown .code:n = \msg_error:nn { piton } { unknown~key~for~package }
+ footnote .bool_gset:N = \g__piton_footnote_bool ,
+ footnotehyper .bool_gset:N = \g__piton_footnotehyper_bool ,
+
+ beamer .bool_gset:N = \g__piton_beamer_bool ,
+ beamer .default:n = true ,
+
+ escape-inside .code:n = \__piton_error:n { key-escape-inside-deleted } ,
+ math-comments .code:n = \__piton_error:n { moved~to~preamble } ,
+ comment-latex .code:n = \__piton_error:n { moved~to~preamble } ,
+
+ unknown .code:n = \__piton_error:n { Unknown~key~for~package }
}
-\msg_new:nnn { piton } { unknown~key~for~package }
+\__piton_msg_new:nn { key-escape-inside-deleted }
{
+ The~key~'escape-inside'~has~been~deleted.~You~must~now~use~
+ the~keys~'begin-escape'~and~'end-escape'~in~
+ \token_to_str:N \PitonOptions.\\
+ That~key~will~be~ignored.
+ }
+\__piton_msg_new:nn { moved~to~preamble }
+ {
+ The~key~'\l_keys_key_str'~*must*~now~be~used~with~
+ \token_to_str:N \PitonOptions`in~the~preamble~of~your~
+ document.\\
+ That~key~will~be~ignored.
+ }
+\__piton_msg_new:nn { Unknown~key~for~package }
+ {
Unknown~key.\\
You~have~used~the~key~'\l_keys_key_str'~but~the~only~keys~available~here~
- are~'beamer',~'comment-latex',~'escape-inside',~'footnote',~'footnotehyper'~and~
- 'math-comments'.~Other~keys~are~available~in~\token_to_str:N \PitonOptions.\\
+ are~'beamer',~'footnote',~'footnotehyper'.~Other~keys~are~available~in~
+ \token_to_str:N \PitonOptions.\\
That~key~will~be~ignored.
}
\ProcessKeysOptions { piton / package }
-\begingroup
-\cs_new_protected:Npn \__piton_set_escape_char:nn #1 #2
- {
- \lua_now:n { piton_begin_escape = "#1" }
- \lua_now:n { piton_end_escape = "#2" }
- }
-\cs_generate_variant:Nn \__piton_set_escape_char:nn { x x }
-\__piton_set_escape_char:xx
- { \tl_head:V \c__piton_escape_inside_tl }
- { \tl_tail:V \c__piton_escape_inside_tl }
-\endgroup
-\@ifclassloaded { beamer } { \bool_set_true:N \c__piton_beamer_bool } { }
-\bool_if:NT \c__piton_beamer_bool { \lua_now:n { piton_beamer = true } }
+\@ifclassloaded { beamer } { \bool_gset_true:N \g__piton_beamer_bool } { }
+\@ifpackageloaded { beamerarticle } { \bool_gset_true:N \g__piton_beamer_bool } { }
+\bool_if:NT \g__piton_beamer_bool { \lua_now:n { piton_beamer = true } }
\hook_gput_code:nnn { begindocument } { . }
{
\@ifpackageloaded { xcolor }
@@ -85,13 +104,13 @@
{ }
{ \msg_fatal:nn { piton } { xcolor~not~loaded } }
}
-\msg_new:nnn { piton } { xcolor~not~loaded }
+\__piton_msg_new:nn { xcolor~not~loaded }
{
xcolor~not~loaded \\
The~package~'xcolor'~is~required~by~'piton'.\\
This~error~is~fatal.
}
-\msg_new:nnn { piton } { footnote~with~footnotehyper~package }
+\__piton_msg_new:nn { footnote~with~footnotehyper~package }
{
Footnote~forbidden.\\
You~can't~use~the~option~'footnote'~because~the~package~
@@ -101,7 +120,7 @@
of~the~package~footnotehyper.\\
If~you~go~on,~the~package~footnote~won't~be~loaded.
}
-\msg_new:nnn { piton } { footnotehyper~with~footnote~package }
+\__piton_msg_new:nn { footnotehyper~with~footnote~package }
{
You~can't~use~the~option~'footnotehyper'~because~the~package~
footnote~has~already~been~loaded.~
@@ -110,10 +129,10 @@
of~the~package~footnote.\\
If~you~go~on,~the~package~footnotehyper~won't~be~loaded.
}
-\bool_if:NT \c__piton_footnote_bool
+\bool_if:NT \g__piton_footnote_bool
{
\@ifclassloaded { beamer }
- { \bool_set_false:N \c__piton_footnote_bool }
+ { \bool_gset_false:N \g__piton_footnote_bool }
{
\@ifpackageloaded { footnotehyper }
{ \__piton_error:n { footnote~with~footnotehyper~package } }
@@ -120,19 +139,23 @@
{ \usepackage { footnote } }
}
}
-\bool_if:NT \c__piton_footnotehyper_bool
+\bool_if:NT \g__piton_footnotehyper_bool
{
\@ifclassloaded { beamer }
- { \bool_set_false:N \c__piton_footnote_bool }
+ { \bool_gset_false:N \g__piton_footnote_bool }
{
\@ifpackageloaded { footnote }
{ \__piton_error:n { footnotehyper~with~footnote~package } }
{ \usepackage { footnotehyper } }
- \bool_set_true:N \c__piton_footnote_bool
+ \bool_gset_true:N \g__piton_footnote_bool
}
}
+\lua_now:n { piton = piton~or { } }
\str_new:N \l__piton_language_str
\str_set:Nn \l__piton_language_str { python }
+\bool_new:N \l__piton_in_PitonOptions_bool
+\bool_new:N \l__piton_in_PitonInputFile_bool
+\bool_new:N \g__piton_in_document_bool
\int_new:N \l__piton_nb_lines_int
\int_new:N \l__piton_nb_non_empty_lines_int
\int_new:N \g__piton_line_int
@@ -141,6 +164,9 @@
\int_set:Nn \l__piton_splittable_int { 100 }
\clist_new:N \l__piton_bg_color_clist
\tl_new:N \l__piton_prompt_bg_color_tl
+\str_new:N \l__piton_begin_range_str
+\str_new:N \l__piton_end_range_str
+\str_new:N \l__piton_file_name_str
\int_new:N \g__piton_env_int
\bool_new:N \l__piton_show_spaces_bool
\bool_new:N \l__piton_break_lines_in_Piton_bool
@@ -194,12 +220,12 @@
}
\@esphack
}
- { \msg_error:nn { piton } { label~with~lines~numbers } }
+ { \__piton_error:n { label~with~lines~numbers } }
}
-\cs_new_protected:Npn \__piton_open_brace:
- { \directlua { piton.open_brace() } }
-\cs_new_protected:Npn \__piton_close_brace:
- { \directlua { piton.close_brace() } }
+\cs_new_protected:Npn \__piton_marker_beginning:n #1 { }
+\cs_new_protected:Npn \__piton_marker_end:n #1 { }
+\cs_new_protected:Npn \__piton_open_brace: { \directlua { piton.open_brace() } }
+\cs_new_protected:Npn \__piton_close_brace: { \directlua { piton.close_brace() } }
\tl_new:N \g__piton_begin_line_hook_tl
\cs_new_protected:Npn \__piton_prompt:
{
@@ -246,9 +272,22 @@
\skip_horizontal:N \l__piton_left_margin_dim
\bool_if:NT \l__piton_line_numbers_bool
{
- \bool_if:NF \l__piton_all_line_numbers_bool
- { \tl_if_eq:nnF { #1 } { \PitonStyle {Prompt}{} } }
+ \bool_if:nF
+ {
+ \str_if_eq_p:nn { #1 } { \PitonStyle {Prompt}{} }
+ &&
+ \l__piton_skip_empty_lines_bool
+ }
+ { \int_gincr:N \g__piton_visual_line_int}
+
+ \bool_if:nT
+ {
+ ! \str_if_eq_p:nn { #1 } { \PitonStyle {Prompt}{} }
+ ||
+ ( ! \l__piton_skip_empty_lines_bool && \l__piton_label_empty_lines_bool )
+ }
\__piton_print_number:
+
}
\clist_if_empty:NF \l__piton_bg_color_clist
{
@@ -321,9 +360,9 @@
{ \l__piton_nb_lines_int - \g__piton_line_int } > \l__piton_splittable_int
{
\egroup
- \bool_if:NT \c__piton_footnote_bool { \end { savenotes } }
+ \bool_if:NT \g__piton_footnote_bool { \end { savenotes } }
\par \mode_leave_vertical: % \newline
- \bool_if:NT \c__piton_footnote_bool { \begin { savenotes } }
+ \bool_if:NT \g__piton_footnote_bool { \begin { savenotes } }
\vtop \bgroup
}
}
@@ -355,10 +394,108 @@
{ \hbox { ~ } }
}
\bool_new:N \l__piton_line_numbers_bool
-\bool_new:N \l__piton_all_line_numbers_bool
+\bool_new:N \l__piton_skip_empty_lines_bool
+\bool_set_true:N \l__piton_skip_empty_lines_bool
+\bool_new:N \l__piton_line_numbers_absolute_bool
+\bool_new:N \l__piton_label_empty_lines_bool
+\bool_set_true:N \l__piton_label_empty_lines_bool
+\int_new:N \l__piton_number_lines_start_int
\bool_new:N \l__piton_resume_bool
+\keys_define:nn { PitonOptions / marker }
+ {
+ beginning .code:n = \cs_set:Nn \__piton_marker_beginning:n { #1 } ,
+ beginning .value_required:n = true ,
+ end .code:n = \cs_set:Nn \__piton_marker_end:n { #1 } ,
+ end .value_required:n = true ,
+ include-lines .bool_set:N = \l__piton_marker_include_lines_bool ,
+ include-lines .default:n = true ,
+ unknown .code:n = \__piton_error:n { Unknown~key~for~marker }
+ }
+\keys_define:nn { PitonOptions / line-numbers }
+ {
+ true .code:n = \bool_set_true:N \l__piton_line_numbers_bool ,
+ false .code:n = \bool_set_false:N \l__piton_line_numbers_bool ,
+
+ start .code:n =
+ \bool_if:NTF \l__piton_in_PitonOptions_bool
+ { Invalid~key }
+ {
+ \bool_set_true:N \l__piton_line_numbers_bool
+ \int_set:Nn \l__piton_number_lines_start_int { #1 }
+ } ,
+ start .value_required:n = true ,
+
+ skip-empty-lines .code:n =
+ \bool_if:NF \l__piton_in_PitonOptions_bool
+ { \bool_set_true:N \l__piton_line_numbers_bool }
+ \str_if_eq:nnTF { #1 } { false }
+ { \bool_set_false:N \l__piton_skip_empty_lines_bool }
+ { \bool_set_true:N \l__piton_skip_empty_lines_bool } ,
+ skip-empty-lines .default:n = true ,
+
+ label-empty-lines .code:n =
+ \bool_if:NF \l__piton_in_PitonOptions_bool
+ { \bool_set_true:N \l__piton_line_numbers_bool }
+ \str_if_eq:nnTF { #1 } { false }
+ { \bool_set_false:N \l__piton_label_empty_lines_bool }
+ { \bool_set_true:N \l__piton_label_empty_lines_bool } ,
+ label-empty-lines .default:n = true ,
+
+ absolute .code:n =
+ \bool_if:NTF \l__piton_in_PitonOptions_bool
+ { \bool_set_true:N \l__piton_line_numbers_absolute_bool }
+ { \bool_set_true:N \l__piton_line_numbers_bool }
+ \bool_if:NT \l__piton_in_PitonInputFile_bool
+ {
+ \bool_set_true:N \l__piton_line_numbers_absolute_bool
+ \bool_set_false:N \l__piton_skip_empty_lines_bool
+ }
+ \bool_lazy_or:nnF
+ \l__piton_in_PitonInputFile_bool
+ \l__piton_in_PitonOptions_bool
+ { \__piton_error:n { Invalid~key } } ,
+ absolute .value_forbidden:n = true ,
+
+ resume .code:n =
+ \bool_set_true:N \l__piton_resume_bool
+ \bool_if:NF \l__piton_in_PitonOptions_bool
+ { \bool_set_true:N \l__piton_line_numbers_bool } ,
+ resume .value_forbidden:n = true ,
+
+ sep .dim_set:N = \l__piton_numbers_sep_dim ,
+ sep .value_required:n = true ,
+
+ unknown .code:n = \__piton_error:n { Unknown~key~for~line-numbers }
+ }
\keys_define:nn { PitonOptions }
{
+ begin-escape .code:n =
+ \lua_now:e { piton.begin_escape = "\lua_escape:n{#1}" } ,
+ begin-escape .value_required:n = true ,
+ begin-escape .usage:n = preamble ,
+
+ end-escape .code:n =
+ \lua_now:e { piton.end_escape = "\lua_escape:n{#1}" } ,
+ end-escape .value_required:n = true ,
+ end-escape .usage:n = preamble ,
+
+ begin-escape-math .code:n =
+ \lua_now:e { piton.begin_escape_math = "\lua_escape:n{#1}" } ,
+ begin-escape-math .value_required:n = true ,
+ begin-escape-math .usage:n = preamble ,
+
+ end-escape-math .code:n =
+ \lua_now:e { piton.end_escape_math = "\lua_escape:n{#1}" } ,
+ end-escape-math .value_required:n = true ,
+ end-escape-math .usage:n = preamble ,
+
+ comment-latex .code:n = \lua_now:n { comment_latex = "#1" } ,
+ comment-latex .value_required:n = true ,
+ comment-latex .usage:n = preamble ,
+
+ math-comments .bool_set:N = \g__piton_math_comments_bool ,
+ math-comments .default:n = true ,
+ math-comments .usage:n = preamble ,
language .code:n =
\str_set:Nx \l__piton_language_str { \str_lowercase:n { #1 } } ,
language .value_required:n = true ,
@@ -370,14 +507,19 @@
env-gobble .value_forbidden:n = true ,
tabs-auto-gobble .code:n = \int_set:Nn \l__piton_gobble_int { -3 } ,
tabs-auto-gobble .value_forbidden:n = true ,
- line-numbers .bool_set:N = \l__piton_line_numbers_bool ,
- line-numbers .default:n = true ,
- all-line-numbers .code:n =
- \bool_set_true:N \l__piton_line_numbers_bool
- \bool_set_true:N \l__piton_all_line_numbers_bool ,
- all-line-numbers .value_forbidden:n = true ,
- resume .bool_set:N = \l__piton_resume_bool ,
- resume .value_forbidden:n = true ,
+
+ marker .code:n =
+ \bool_lazy_or:nnTF
+ \l__piton_in_PitonInputFile_bool
+ \l__piton_in_PitonOptions_bool
+ { \keys_set:nn { PitonOptions / marker } { #1 } }
+ { \__piton_error:n { Invalid~key } } ,
+ marker .value_required:n = true ,
+
+ line-numbers .code:n =
+ \keys_set:nn { PitonOptions / line-numbers } { #1 } ,
+ line-numbers .default:n = true ,
+
splittable .int_set:N = \l__piton_splittable_int ,
splittable .default:n = 1 ,
background-color .clist_set:N = \l__piton_bg_color_clist ,
@@ -384,7 +526,8 @@
background-color .value_required:n = true ,
prompt-background-color .tl_set:N = \l__piton_prompt_bg_color_tl ,
prompt-background-color .value_required:n = true ,
- width .code:n =
+
+ width .code:n =
\str_if_eq:nnTF { #1 } { min }
{
\bool_set_true:N \l__piton_width_min_bool
@@ -394,7 +537,8 @@
\bool_set_false:N \l__piton_width_min_bool
\dim_set:Nn \l__piton_width_dim { #1 }
} ,
- width .value_required:n = true ,
+ width .value_required:n = true ,
+
left-margin .code:n =
\str_if_eq:nnTF { #1 } { auto }
{
@@ -406,8 +550,7 @@
\bool_set_false:N \l__piton_left_margin_auto_bool
} ,
left-margin .value_required:n = true ,
- numbers-sep .dim_set:N = \l__piton_numbers_sep_dim ,
- numbers-sep .value_required:n = true ,
+
tab-size .code:n = \__piton_set_tab_tl:n { #1 } ,
tab-size .value_required:n = true ,
show-spaces .bool_set:N = \l__piton_show_spaces_bool ,
@@ -428,17 +571,68 @@
continuation-symbol .value_required:n = true ,
continuation-symbol-on-indentation .tl_set:N = \l__piton_csoi_tl ,
continuation-symbol-on-indentation .value_required:n = true ,
- unknown .code:n =
- \msg_error:nn { piton } { Unknown~key~for~PitonOptions }
+
+ first-line .code:n = \__piton_in_PitonInputFile:n
+ { \int_set:Nn \l__piton_first_line_int { #1 } } ,
+ first-line .value_required:n = true ,
+
+ last-line .code:n = \__piton_in_PitonInputFile:n
+ { \int_set:Nn \l__piton_last_line_int { #1 } } ,
+ last-line .value_required:n = true ,
+
+ begin-range .code:n = \__piton_in_PitonInputFile:n
+ { \str_set:Nn \l__piton_begin_range_str { #1 } } ,
+ begin-range .value_required:n = true ,
+
+ end-range .code:n = \__piton_in_PitonInputFile:n
+ { \str_set:Nn \l__piton_end_range_str { #1 } } ,
+ end-range .value_required:n = true ,
+
+ range .code:n = \__piton_in_PitonInputFile:n
+ {
+ \str_set:Nn \l__piton_begin_range_str { #1 }
+ \str_set:Nn \l__piton_end_range_str { #1 }
+ } ,
+ range .value_required:n = true ,
+
+ resume .meta:n = line-numbers/resume ,
+
+ unknown .code:n = \__piton_error:n { Unknown~key~for~PitonOptions } ,
+
+ % deprecated
+ all-line-numbers .code:n =
+ \bool_set_true:N \l__piton_line_numbers_bool
+ \bool_set_false:N \l__piton_skip_empty_lines_bool ,
+ all-line-numbers .value_forbidden:n = true ,
+
+ % deprecated
+ numbers-sep .dim_set:N = \l__piton_numbers_sep_dim ,
+ numbers-sep .value_required:n = true
}
-\NewDocumentCommand \PitonOptions { } { \keys_set:nn { PitonOptions } }
+\cs_new_protected:Npn \__piton_in_PitonInputFile:n #1
+ {
+ \bool_if:NTF \l__piton_in_PitonInputFile_bool
+ { #1 }
+ { \__piton_error:n { Invalid~key } }
+ }
+\NewDocumentCommand \PitonOptions { m }
+ {
+ \bool_set_true:N \l__piton_in_PitonOptions_bool
+ \keys_set:nn { PitonOptions } { #1 }
+ \bool_set_false:N \l__piton_in_PitonOptions_bool
+ }
+\hook_gput_code:nnn { begindocument } { . }
+ { \bool_gset_true:N \g__piton_in_document_bool }
\int_new:N \g__piton_visual_line_int
\cs_new_protected:Npn \__piton_print_number:
{
- \int_gincr:N \g__piton_visual_line_int
\hbox_overlap_left:n
{
- { \color { gray } \footnotesize \int_to_arabic:n \g__piton_visual_line_int }
+ {
+ \color { gray }
+ \footnotesize
+ \int_to_arabic:n \g__piton_visual_line_int
+ }
\skip_horizontal:N \l__piton_numbers_sep_dim
}
}
@@ -589,13 +783,6 @@
\dim_zero:N \parindent
\cs_set_eq:NN \label \__piton_label:n
}
-\keys_define:nn { PitonInputFile }
- {
- first-line .int_set:N = \l__piton_first_line_int ,
- first-line .value_required:n = true ,
- last-line .int_set:N = \l__piton_last_line_int ,
- last-line .value_required:n = true ,
- }
\cs_new_protected:Npn \__piton_compute_left_margin:nn #1 #2
{
\bool_lazy_and:nnT \l__piton_left_margin_auto_bool \l__piton_line_numbers_bool
@@ -603,12 +790,8 @@
\hbox_set:Nn \l_tmpa_box
{
\footnotesize
- \bool_if:NTF \l__piton_all_line_numbers_bool
+ \bool_if:NTF \l__piton_skip_empty_lines_bool
{
- \int_to_arabic:n
- { \g__piton_visual_line_int + \l__piton_nb_lines_int }
- }
- {
\lua_now:n
{ piton.#1(token.scan_argument()) }
{ #2 }
@@ -615,6 +798,10 @@
\int_to_arabic:n
{ \g__piton_visual_line_int + \l__piton_nb_non_empty_lines_int }
}
+ {
+ \int_to_arabic:n
+ { \g__piton_visual_line_int + \l__piton_nb_lines_int }
+ }
}
\dim_set:Nn \l__piton_left_margin_dim
{ \box_wd:N \l_tmpa_box + \l__piton_numbers_sep_dim + 0.1 em }
@@ -663,7 +850,7 @@
\__piton_compute_width:
\ttfamily
\dim_zero:N \parskip % added 2023/07/06
- \bool_if:NT \c__piton_footnote_bool { \begin { savenotes } }
+ \bool_if:NT \g__piton_footnote_bool { \begin { savenotes } }
\vtop \bgroup
\lua_now:e
{
@@ -677,7 +864,7 @@
{ ##1 }
\vspace { 2.5 pt }
\egroup
- \bool_if:NT \c__piton_footnote_bool { \end { savenotes } }
+ \bool_if:NT \g__piton_footnote_bool { \end { savenotes } }
\bool_if:NT \l__piton_width_min_bool \__piton_width_to_aux:
\end { #1 }
\__piton_write_aux:
@@ -686,6 +873,8 @@
{
#3
\__piton_pre_env:
+ \int_compare:nNnT \l__piton_number_lines_start_int > 0
+ { \int_gset:Nn \g__piton_visual_line_int { \l__piton_number_lines_start_int - 1 } }
\group_begin:
\tl_map_function:nN
{ \ \\ \{ \} \$ \& \# \^ \_ \% \~ \^^I }
@@ -695,11 +884,11 @@
{ #4 }
\AddToHook { env / #1 / begin } { \char_set_catcode_other:N \^^M }
}
-\bool_if:NTF \c__piton_beamer_bool
+\bool_if:NTF \g__piton_beamer_bool
{
\NewPitonEnvironment { Piton } { d < > O { } }
{
- \PitonOptions { #2 }
+ \keys_set:nn { PitonOptions } { #2 }
\IfValueTF { #1 }
{ \begin { uncoverenv } < #1 > }
{ \begin { uncoverenv } }
@@ -706,8 +895,9 @@
}
{ \end { uncoverenv } }
}
- { \NewPitonEnvironment { Piton } { O { } }
- { \PitonOptions { #1 } }
+ {
+ \NewPitonEnvironment { Piton } { O { } }
+ { \keys_set:nn { PitonOptions } { #1 } }
{ }
}
\NewDocumentCommand { \PitonInputFile } { d < > O { } m }
@@ -714,46 +904,96 @@
{
\file_if_exist:nTF { #3 }
{ \__piton_input_file:nnn { #1 } { #2 } { #3 } }
- { \msg_error:nnn { piton } { unknown~file } { #3 } }
+ { \msg_error:nnn { piton } { Unknown~file } { #3 } }
}
\cs_new_protected:Npn \__piton_input_file:nnn #1 #2 #3
{
+ \str_set:Nn \l__piton_file_name_str { #3 }
\tl_if_novalue:nF { #1 }
{
- \bool_if:NTF \c__piton_beamer_bool
+ \bool_if:NTF \g__piton_beamer_bool
{ \begin { uncoverenv } < #1 > }
- { \msg_error:nn { piton } { overlay~without~beamer } }
+ { \__piton_error:n { overlay~without~beamer } }
}
\group_begin:
\int_zero_new:N \l__piton_first_line_int
\int_zero_new:N \l__piton_last_line_int
\int_set_eq:NN \l__piton_last_line_int \c_max_int
- \keys_set:nn { PitonInputFile } { #2 }
+ \bool_set_true:N \l__piton_in_PitonInputFile_bool
+ \keys_set:nn { PitonOptions } { #2 }
+ \bool_if:NT \l__piton_line_numbers_absolute_bool
+ { \bool_set_false:N \l__piton_skip_empty_lines_bool }
+ \bool_if:nTF
+ {
+ (
+ \int_compare_p:nNn \l__piton_first_line_int > 0
+ || \int_compare_p:nNn \l__piton_last_line_int < \c_max_int
+ )
+ && ! \str_if_empty_p:N \l__piton_begin_range_str
+ }
+ {
+ \__piton_error:n { bad~range~specification }
+ \int_zero:N \l__piton_first_line_int
+ \int_set_eq:NN \l__piton_last_line_int \c_max_int
+ }
+ {
+ \str_if_empty:NF \l__piton_begin_range_str
+ {
+ \__piton_compute_range:
+ \bool_lazy_or:nnT
+ \l__piton_marker_include_lines_bool
+ { ! \str_if_eq_p:NN \l__piton_begin_range_str \l__piton_end_range_str }
+ {
+ \int_decr:N \l__piton_first_line_int
+ \int_incr:N \l__piton_last_line_int
+ }
+ }
+ }
\__piton_pre_env:
+ \bool_if:NT \l__piton_line_numbers_absolute_bool
+ { \int_gset:Nn \g__piton_visual_line_int { \l__piton_first_line_int - 1 } }
+ \int_compare:nNnT \l__piton_number_lines_start_int > 0
+ {
+ \int_gset:Nn \g__piton_visual_line_int
+ { \l__piton_number_lines_start_int - 1 }
+ }
+ \int_compare:nNnT \g__piton_visual_line_int < 0
+ { \int_gzero:N \g__piton_visual_line_int }
\mode_if_vertical:TF \mode_leave_vertical: \newline
- \lua_now:n { piton.CountLinesFile(token.scan_argument()) } { #3 }
+ \lua_now:e { piton.CountLinesFile('\l__piton_file_name_str') }
\__piton_compute_left_margin:nn { CountNonEmptyLinesFile } { #3 }
\__piton_compute_width:
\ttfamily
- \bool_if:NT \c__piton_footnote_bool { \begin { savenotes } }
+ \bool_if:NT \g__piton_footnote_bool { \begin { savenotes } }
\vtop \bgroup
\lua_now:e
{
piton.ParseFile(
- '\l__piton_language_str',
- token.scan_argument() ,
+ '\l__piton_language_str' ,
+ '\l__piton_file_name_str' ,
\int_use:N \l__piton_first_line_int ,
\int_use:N \l__piton_last_line_int )
}
- { #3 }
\egroup
- \bool_if:NT \c__piton_footnote_bool { \end { savenotes } }
+ \bool_if:NT \g__piton_footnote_bool { \end { savenotes } }
\bool_if:NT \l__piton_width_min_bool \__piton_width_to_aux:
\group_end:
\tl_if_novalue:nF { #1 }
- { \bool_if:NT \c__piton_beamer_bool { \end { uncoverenv } } }
+ { \bool_if:NT \g__piton_beamer_bool { \end { uncoverenv } } }
\__piton_write_aux:
}
+\cs_new_protected:Npn \__piton_compute_range:
+ {
+ \str_set:Nx \l_tmpa_str { \__piton_marker_beginning:n \l__piton_begin_range_str }
+ \str_set:Nx \l_tmpb_str { \__piton_marker_end:n \l__piton_end_range_str }
+ \exp_args:NnV \regex_replace_all:nnN { \\\# } \c_hash_str \l_tmpa_str
+ \exp_args:NnV \regex_replace_all:nnN { \\\# } \c_hash_str \l_tmpb_str
+ \lua_now:e
+ {
+ piton.ComputeRange
+ ( '\l_tmpa_str' , '\l_tmpb_str' , '\l__piton_file_name_str' )
+ }
+ }
\NewDocumentCommand { \PitonStyle } { m } { \use:c { pitonStyle #1 } }
\NewDocumentCommand { \SetPitonStyle } { } { \keys_set:nn { piton / Styles } }
\cs_new_protected:Npn \__piton_math_scantokens:n #1
@@ -812,7 +1052,7 @@
ParseAgain.noCR .tl_set:c = pitonStyle ParseAgain.noCR ,
ParseAgain.noCR .value_required:n = true ,
unknown .code:n =
- \msg_error:nn { piton } { Unknown~key~for~SetPitonStyle }
+ \__piton_error:n { Unknown~key~for~SetPitonStyle }
}
\clist_gput_left:Nn \g__piton_styles_clist { String }
\clist_gsort:Nn \g__piton_styles_clist
@@ -853,7 +1093,7 @@
ParseAgain.noCR = \__piton_piton_no_cr:n ,
ParseAgain = \__piton_piton:n ,
}
-\bool_if:NT \c__piton_math_comments_bool { \SetPitonStyle { Comment.Math } }
+\bool_if:NT \g__piton_math_comments_bool { \SetPitonStyle { Comment.Math } }
\cs_new_protected:Npn \__piton_identifier:n #1
{ \cs_if_exist_use:c { PitonIdentifier _ \l__piton_language_str _ #1 } { #1 } }
\keys_define:nn { PitonOptions }
@@ -903,7 +1143,7 @@
\token_to_str:N \piton\ but~there~is~no~environment~
{piton}.~This~error~is~fatal.
}
-\msg_new:nnn { piton } { Unknown~key~for~SetPitonStyle }
+\__piton_msg_new:nn { Unknown~key~for~SetPitonStyle }
{
The~style~'\l_keys_key_str'~is~unknown.\\
This~key~will~be~ignored.\\
@@ -910,15 +1150,65 @@
The~available~styles~are~(in~alphabetic~order):~
\clist_use:Nnnn \g__piton_styles_clist { ~and~ } { ,~ } { ~and~ }.
}
-\msg_new:nnn { piton } { syntax~error }
+\__piton_msg_new:nn { Invalid~key }
{
+ Wrong~use~of~key.\\
+ You~can't~use~the~key~'\l_keys_key_str'~here.\\
+ That~key~will~be~ignored.
+ }
+\__piton_msg_new:nn { Unknown~key~for~line-numbers }
+ {
+ Unknown~key. \\
+ The~key~'line-numbers / \l_keys_key_str'~is~unknown.\\
+ The~available~keys~of~the~family~'line-numbers'~are~(in~
+ alphabetic~order):~
+ absolute,~false,~label-empty-lines,~resume,~skip-empty-lines,~
+ sep,~start~and~true.\\
+ That~key~will~be~ignored.
+ }
+\__piton_msg_new:nn { Unknown~key~for~marker }
+ {
+ Unknown~key. \\
+ The~key~'marker / \l_keys_key_str'~is~unknown.\\
+ The~available~keys~of~the~family~'marker'~are~(in~
+ alphabetic~order):~ beginning,~end~and~include-lines.\\
+ That~key~will~be~ignored.
+ }
+\__piton_msg_new:nn { bad~range~specification }
+ {
+ Incompatible~keys.\\
+ You~can't~specify~the~range~of~lines~to~include~by~using~both~
+ markers~and~explicit~number~of~lines.\\
+ Your~whole~file~'\l__piton_file_name_str'~will~be~included.
+ }
+\__piton_msg_new:nn { syntax~error }
+ {
Your~code~is~not~syntactically~correct.\\
It~won't~be~printed~in~the~PDF~file.
}
\NewDocumentCommand \PitonSyntaxError { }
- { \msg_error:nn { piton } { syntax~error } }
-\msg_new:nnn { piton } { unknown~file }
+ { \__piton_error:n { syntax~error } }
+\__piton_msg_new:nn { begin~marker~not~found }
{
+ Marker~not~found.\\
+ The~range~'\l__piton_begin_range_str'~provided~to~the~
+ command~\token_to_str:N \PitonInputFile\ has~not~been~found.~
+ The~whole~file~'\l__piton_file_name_str'~will~be~inserted.
+ }
+\__piton_msg_new:nn { end~marker~not~found }
+ {
+ Marker~not~found.\\
+ The~marker~of~end~of~the~range~'\l__piton_end_range_str'~
+ provided~to~the~command~\token_to_str:N \PitonInputFile\
+ has~not~been~found.~The~file~'\l__piton_file_name_str'~will~
+ be~inserted~till~the~end.
+ }
+\NewDocumentCommand \PitonBeginMarkerNotFound { }
+ { \__piton_error:n { begin~marker~not~found } }
+\NewDocumentCommand \PitonEndMarkerNotFound { }
+ { \__piton_error:n { end~marker~not~found } }
+\__piton_msg_new:nn { Unknown~file }
+ {
Unknown~file. \\
The~file~'#1'~is~unknown.\\
Your~command~\token_to_str:N \PitonInputFile\ will~be~discarded.
@@ -932,7 +1222,6 @@
}
{
The~available~keys~are~(in~alphabetic~order):~
- all-line-numbers,~
auto-gobble,~
background-color,~
break-lines,~
@@ -941,6 +1230,7 @@
continuation-symbol,~
continuation-symbol-on-indentation,~
end-of-broken-line,~
+ end-range,~
env-gobble,~
gobble,~
identifiers,~
@@ -947,7 +1237,8 @@
indent-broken-lines,~
language,~
left-margin,~
- line-numbers,~
+ line-numbers/,~
+ marker/,~
prompt-background-color,~
resume,~
show-spaces,~
@@ -956,14 +1247,13 @@
tabs-auto-gobble,~
tab-size~and~width.
}
-\msg_new:nnn { piton } { label~with~lines~numbers }
+\__piton_msg_new:nn { label~with~lines~numbers }
{
You~can't~use~the~command~\token_to_str:N \label\
- because~the~key~'line-numbers'~(or~'all-line-numbers')~
- is~not~active.\\
+ because~the~key~'line-numbers'~is~not~active.\\
If~you~go~on,~that~command~will~ignored.
}
-\msg_new:nnn { piton } { cr~not~allowed }
+\__piton_msg_new:nn { cr~not~allowed }
{
You~can't~put~any~carriage~return~in~the~argument~
of~a~command~\c_backslash_str
@@ -972,7 +1262,7 @@
corresponding~environment.\\
That~error~is~fatal.
}
-\msg_new:nnn { piton } { overlay~without~beamer }
+\__piton_msg_new:nn { overlay~without~beamer }
{
You~can't~use~an~argument~<...>~for~your~command~
\token_to_str:N \PitonInputFile\ because~you~are~not~
@@ -979,1200 +1269,11 @@
in~Beamer.\\
If~you~go~on,~that~argument~will~be~ignored.
}
-\msg_new:nnn { Piton } { Python~error }
+\__piton_msg_new:nn { Python~error }
{ A~Python~error~has~been~detected. }
-\ExplSyntaxOff
-\RequirePackage{luacode}
-\begin{luacode*}
-piton = piton or { }
-if piton.comment_latex == nil then piton.comment_latex = ">" end
-piton.comment_latex = "#" .. piton.comment_latex
-function piton.open_brace ()
- tex.sprint("{")
-end
-function piton.close_brace ()
- tex.sprint("}")
-end
-local P, S, V, C, Ct, Cc = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc
-local Cf, Cs , Cg , Cmt , Cb = lpeg.Cf, lpeg.Cs, lpeg.Cg , lpeg.Cmt , lpeg.Cb
-local R = lpeg.R
-local function Q(pattern)
- return Ct ( Cc ( luatexbase.catcodetables.CatcodeTableOther ) * C ( pattern ) )
-end
-local function L(pattern)
- return Ct ( C ( pattern ) )
-end
-local function Lc(string)
- return Cc ( { luatexbase.catcodetables.expl , string } )
-end
-local function K(style, pattern)
- return
- Lc ( "{\\PitonStyle{" .. style .. "}{" )
- * Q ( pattern )
- * Lc ( "}}" )
-end
-local function WithStyle(style,pattern)
- return
- Ct ( Cc "Open" * Cc ( "{\\PitonStyle{" .. style .. "}{" ) * Cc "}}" )
- * pattern
- * Ct ( Cc "Close" )
-end
-local Escape =
- P(piton_begin_escape)
- * L ( ( 1 - P(piton_end_escape) ) ^ 1 )
- * P(piton_end_escape)
-lpeg.locale(lpeg)
-local alpha, digit = lpeg.alpha, lpeg.digit
-local space = P " "
-local letter = alpha + P "_"
- + P "â" + P "à" + P "ç" + P "é" + P "è" + P "ê" + P "ë" + P "ï" + P "î"
- + P "ô" + P "û" + P "ü" + P "Â" + P "À" + P "Ç" + P "É" + P "È" + P "Ê"
- + P "Ë" + P "Ï" + P "Î" + P "Ô" + P "Û" + P "Ü"
+\hook_gput_code:nnn { begindocument } { . }
+ { \lua_now:e { require("piton.lua") } }
-local alphanum = letter + digit
-local identifier = letter * alphanum ^ 0
-local Identifier = K ( 'Identifier' , identifier)
-local Number =
- K ( 'Number' ,
- ( digit^1 * P "." * digit^0 + digit^0 * P "." * digit^1 + digit^1 )
- * ( S "eE" * S "+-" ^ -1 * digit^1 ) ^ -1
- + digit^1
- )
-local Word
-if piton_begin_escape ~= ''
-then Word = Q ( ( ( 1 - space - P(piton_begin_escape) - P(piton_end_escape) )
- - S "'\"\r[()]" - digit ) ^ 1 )
-else Word = Q ( ( ( 1 - space ) - S "'\"\r[()]" - digit ) ^ 1 )
-end
-local Space = ( Q " " ) ^ 1
-
-local SkipSpace = ( Q " " ) ^ 0
-
-local Punct = Q ( S ".,:;!" )
-
-local Tab = P "\t" * Lc ( '\\l__piton_tab_tl' )
-local SpaceIndentation = Lc ( '\\__piton_an_indentation_space:' ) * ( Q " " )
-local Delim = Q ( S "[()]" )
-local VisualSpace = space * Lc "\\l__piton_space_tl"
-local Beamer = P ( false )
-local BeamerBeginEnvironments = P ( true )
-local BeamerEndEnvironments = P ( true )
-if piton_beamer
-then
- local BeamerNamesEnvironments =
- P "uncoverenv" + P "onlyenv" + P "visibleenv" + P "invisibleenv"
- + P "alertenv" + P "actionenv"
- BeamerBeginEnvironments =
- ( space ^ 0 *
- L
- (
- P "\\begin{" * BeamerNamesEnvironments * "}"
- * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1
- )
- * P "\r"
- ) ^ 0
- BeamerEndEnvironments =
- ( space ^ 0 *
- L ( P "\\end{" * BeamerNamesEnvironments * P "}" )
- * P "\r"
- ) ^ 0
- function OneBeamerEnvironment(name,lpeg)
- return
- Ct ( Cc "Open"
- * C (
- P ( "\\begin{" .. name .. "}" )
- * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
- )
- * Cc ( "\\end{" .. name .. "}" )
- )
- * (
- C ( ( 1 - P ( "\\end{" .. name .. "}" ) ) ^ 0 )
- / ( function (s) return lpeg : match(s) end )
- )
- * P ( "\\end{" .. name .. "}" ) * Ct ( Cc "Close" )
- end
-end
-local languages = { }
-local Operator =
- K ( 'Operator' ,
- P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":="
- + P "//" + P "**" + S "-~+/*%=<>&.@|"
- )
-
-local OperatorWord =
- K ( 'Operator.Word' , P "in" + P "is" + P "and" + P "or" + P "not" )
-
-local Keyword =
- K ( 'Keyword' ,
- P "as" + P "assert" + P "break" + P "case" + P "class" + P "continue"
- + P "def" + P "del" + P "elif" + P "else" + P "except" + P "exec"
- + P "finally" + P "for" + P "from" + P "global" + P "if" + P "import"
- + P "lambda" + P "non local" + P "pass" + P "return" + P "try"
- + P "while" + P "with" + P "yield" + P "yield from" )
- + K ( 'Keyword.Constant' ,P "True" + P "False" + P "None" )
-
-local Builtin =
- K ( 'Name.Builtin' ,
- P "__import__" + P "abs" + P "all" + P "any" + P "bin" + P "bool"
- + P "bytearray" + P "bytes" + P "chr" + P "classmethod" + P "compile"
- + P "complex" + P "delattr" + P "dict" + P "dir" + P "divmod"
- + P "enumerate" + P "eval" + P "filter" + P "float" + P "format"
- + P "frozenset" + P "getattr" + P "globals" + P "hasattr" + P "hash"
- + P "hex" + P "id" + P "input" + P "int" + P "isinstance" + P "issubclass"
- + P "iter" + P "len" + P "list" + P "locals" + P "map" + P "max"
- + P "memoryview" + P "min" + P "next" + P "object" + P "oct" + P "open"
- + P "ord" + P "pow" + P "print" + P "property" + P "range" + P "repr"
- + P "reversed" + P "round" + P "set" + P "setattr" + P "slice" + P "sorted"
- + P "staticmethod" + P "str" + P "sum" + P "super" + P "tuple" + P "type"
- + P "vars" + P "zip" )
-
-local Exception =
- K ( 'Exception' ,
- P "ArithmeticError" + P "AssertionError" + P "AttributeError"
- + P "BaseException" + P "BufferError" + P "BytesWarning" + P "DeprecationWarning"
- + P "EOFError" + P "EnvironmentError" + P "Exception" + P "FloatingPointError"
- + P "FutureWarning" + P "GeneratorExit" + P "IOError" + P "ImportError"
- + P "ImportWarning" + P "IndentationError" + P "IndexError" + P "KeyError"
- + P "KeyboardInterrupt" + P "LookupError" + P "MemoryError" + P "NameError"
- + P "NotImplementedError" + P "OSError" + P "OverflowError"
- + P "PendingDeprecationWarning" + P "ReferenceError" + P "ResourceWarning"
- + P "RuntimeError" + P "RuntimeWarning" + P "StopIteration"
- + P "SyntaxError" + P "SyntaxWarning" + P "SystemError" + P "SystemExit"
- + P "TabError" + P "TypeError" + P "UnboundLocalError" + P "UnicodeDecodeError"
- + P "UnicodeEncodeError" + P "UnicodeError" + P "UnicodeTranslateError"
- + P "UnicodeWarning" + P "UserWarning" + P "ValueError" + P "VMSError"
- + P "Warning" + P "WindowsError" + P "ZeroDivisionError"
- + P "BlockingIOError" + P "ChildProcessError" + P "ConnectionError"
- + P "BrokenPipeError" + P "ConnectionAbortedError" + P "ConnectionRefusedError"
- + P "ConnectionResetError" + P "FileExistsError" + P "FileNotFoundError"
- + P "InterruptedError" + P "IsADirectoryError" + P "NotADirectoryError"
- + P "PermissionError" + P "ProcessLookupError" + P "TimeoutError"
- + P "StopAsyncIteration" + P "ModuleNotFoundError" + P "RecursionError" )
-
-local RaiseException = K ( 'Keyword' , P "raise" ) * SkipSpace * Exception * Q ( P "(" )
-
-local Decorator = K ( 'Name.Decorator' , P "@" * letter^1 )
-local DefClass =
- K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier )
-local ImportAs =
- K ( 'Keyword' , P "import" )
- * Space
- * K ( 'Name.Namespace' ,
- identifier * ( P "." * identifier ) ^ 0 )
- * (
- ( Space * K ( 'Keyword' , P "as" ) * Space
- * K ( 'Name.Namespace' , identifier ) )
- +
- ( SkipSpace * Q ( P "," ) * SkipSpace
- * K ( 'Name.Namespace' , identifier ) ) ^ 0
- )
-local FromImport =
- K ( 'Keyword' , P "from" )
- * Space * K ( 'Name.Namespace' , identifier )
- * Space * K ( 'Keyword' , P "import" )
-local PercentInterpol =
- K ( 'String.Interpol' ,
- P "%"
- * ( P "(" * alphanum ^ 1 * P ")" ) ^ -1
- * ( S "-#0 +" ) ^ 0
- * ( digit ^ 1 + P "*" ) ^ -1
- * ( P "." * ( digit ^ 1 + P "*" ) ) ^ -1
- * ( S "HlL" ) ^ -1
- * S "sdfFeExXorgiGauc%"
- )
-local SingleShortString =
- WithStyle ( 'String.Short' ,
- Q ( P "f'" + P "F'" )
- * (
- K ( 'String.Interpol' , P "{" )
- * K ( 'Interpol.Inside' , ( 1 - S "}':" ) ^ 0 )
- * Q ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1
- * K ( 'String.Interpol' , P "}" )
- +
- VisualSpace
- +
- Q ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 )
- ) ^ 0
- * Q ( P "'" )
- +
- Q ( P "'" + P "r'" + P "R'" )
- * ( Q ( ( P "\\'" + 1 - S " '\r%" ) ^ 1 )
- + VisualSpace
- + PercentInterpol
- + Q ( P "%" )
- ) ^ 0
- * Q ( P "'" ) )
-
-local DoubleShortString =
- WithStyle ( 'String.Short' ,
- Q ( P "f\"" + P "F\"" )
- * (
- K ( 'String.Interpol' , P "{" )
- * Q ( ( 1 - S "}\":" ) ^ 0 , 'Interpol.Inside' )
- * ( K ( 'String.Interpol' , P ":" ) * Q ( (1 - S "}:\"") ^ 0 ) ) ^ -1
- * K ( 'String.Interpol' , P "}" )
- +
- VisualSpace
- +
- Q ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 )
- ) ^ 0
- * Q ( P "\"" )
- +
- Q ( P "\"" + P "r\"" + P "R\"" )
- * ( Q ( ( P "\\\"" + 1 - S " \"\r%" ) ^ 1 )
- + VisualSpace
- + PercentInterpol
- + Q ( P "%" )
- ) ^ 0
- * Q ( P "\"" ) )
-
-local ShortString = SingleShortString + DoubleShortString
-local balanced_braces =
- P { "E" ,
- E =
- (
- P "{" * V "E" * P "}"
- +
- ShortString
- +
- ( 1 - S "{}" )
- ) ^ 0
- }
-if piton_beamer
-then
- Beamer =
- L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 )
- +
- Ct ( Cc "Open"
- * C (
- (
- P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
- + P "\\invisible" + P "\\action"
- )
- * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
- * P "{"
- )
- * Cc "}"
- )
- * ( C ( balanced_braces ) / (function (s) return MainLoopPython:match(s) end ) )
- * P "}" * Ct ( Cc "Close" )
- + OneBeamerEnvironment ( "uncoverenv" , MainLoopPython )
- + OneBeamerEnvironment ( "onlyenv" , MainLoopPython )
- + OneBeamerEnvironment ( "visibleenv" , MainLoopPython )
- + OneBeamerEnvironment ( "invisibleenv" , MainLoopPython )
- + OneBeamerEnvironment ( "alertenv" , MainLoopPython )
- + OneBeamerEnvironment ( "actionenv" , MainLoopPython )
- +
- L (
- ( P "\\alt" )
- * P "<" * (1 - P ">") ^ 0 * P ">"
- * P "{"
- )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}{" )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}" )
- +
- L (
- ( P "\\temporal" )
- * P "<" * (1 - P ">") ^ 0 * P ">"
- * P "{"
- )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}{" )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}{" )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}" )
-end
-local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\__piton_prompt:' ) ) ^ -1
-local Prompt = K ( 'Prompt' , ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1 )
-local EOL =
- P "\r"
- *
- (
- ( space^0 * -1 )
- +
- Ct (
- Cc "EOL"
- *
- Ct (
- Lc "\\__piton_end_line:"
- * BeamerEndEnvironments
- * BeamerBeginEnvironments
- * PromptHastyDetection
- * Lc "\\__piton_newline: \\__piton_begin_line:"
- * Prompt
- )
- )
- )
- *
- SpaceIndentation ^ 0
-local SingleLongString =
- WithStyle ( 'String.Long' ,
- ( Q ( S "fF" * P "'''" )
- * (
- K ( 'String.Interpol' , P "{" )
- * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "'''" ) ^ 0 )
- * Q ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1
- * K ( 'String.Interpol' , P "}" )
- +
- Q ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 )
- +
- EOL
- ) ^ 0
- +
- Q ( ( S "rR" ) ^ -1 * P "'''" )
- * (
- Q ( ( 1 - P "'''" - S "\r%" ) ^ 1 )
- +
- PercentInterpol
- +
- P "%"
- +
- EOL
- ) ^ 0
- )
- * Q ( P "'''" ) )
-
-local DoubleLongString =
- WithStyle ( 'String.Long' ,
- (
- Q ( S "fF" * P "\"\"\"" )
- * (
- K ( 'String.Interpol', P "{" )
- * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 )
- * Q ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1
- * K ( 'String.Interpol' , P "}" )
- +
- Q ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 )
- +
- EOL
- ) ^ 0
- +
- Q ( ( S "rR" ) ^ -1 * P "\"\"\"" )
- * (
- Q ( ( 1 - P "\"\"\"" - S "%\r" ) ^ 1 )
- +
- PercentInterpol
- +
- P "%"
- +
- EOL
- ) ^ 0
- )
- * Q ( P "\"\"\"" )
- )
-local LongString = SingleLongString + DoubleLongString
-local StringDoc =
- K ( 'String.Doc' , P "\"\"\"" )
- * ( K ( 'String.Doc' , (1 - P "\"\"\"" - P "\r" ) ^ 0 ) * EOL
- * Tab ^ 0
- ) ^ 0
- * K ( 'String.Doc' , ( 1 - P "\"\"\"" - P "\r" ) ^ 0 * P "\"\"\"" )
-local CommentMath =
- P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$"
-
-local Comment =
- WithStyle ( 'Comment' ,
- Q ( P "#" )
- * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 )
- * ( EOL + -1 )
-local CommentLaTeX =
- P(piton.comment_latex)
- * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces"
- * L ( ( 1 - P "\r" ) ^ 0 )
- * Lc "}}"
- * ( EOL + -1 )
-local expression =
- P { "E" ,
- E = ( P "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * P "'"
- + P "\"" * (P "\\\"" + 1 - S "\"\r" ) ^ 0 * P "\""
- + P "{" * V "F" * P "}"
- + P "(" * V "F" * P ")"
- + P "[" * V "F" * P "]"
- + ( 1 - S "{}()[]\r," ) ) ^ 0 ,
- F = ( P "{" * V "F" * P "}"
- + P "(" * V "F" * P ")"
- + P "[" * V "F" * P "]"
- + ( 1 - S "{}()[]\r\"'" ) ) ^ 0
- }
-local Param =
- SkipSpace * Identifier * SkipSpace
- * (
- K ( 'InitialValues' , P "=" * expression )
- + Q ( P ":" ) * SkipSpace * K ( 'Name.Type' , letter ^ 1 )
- ) ^ -1
-local Params = ( Param * ( Q "," * Param ) ^ 0 ) ^ -1
-local DefFunction =
- K ( 'Keyword' , P "def" )
- * Space
- * K ( 'Name.Function.Internal' , identifier )
- * SkipSpace
- * Q ( P "(" ) * Params * Q ( P ")" )
- * SkipSpace
- * ( Q ( P "->" ) * SkipSpace * K ( 'Name.Type' , identifier ) ) ^ -1
- * K ( 'ParseAgain' , ( 1 - S ":\r" )^0 )
- * Q ( P ":" )
- * ( SkipSpace
- * ( EOL + CommentLaTeX + Comment ) -- in all cases, that contains an EOL
- * Tab ^ 0
- * SkipSpace
- * StringDoc ^ 0 -- there may be additionnal docstrings
- ) ^ -1
-local ExceptionInConsole = Exception * Q ( ( 1 - P "\r" ) ^ 0 ) * EOL
-local MainPython =
- EOL
- + Space
- + Tab
- + Escape
- + CommentLaTeX
- + Beamer
- + LongString
- + Comment
- + ExceptionInConsole
- + Delim
- + Operator
- + OperatorWord * ( Space + Punct + Delim + EOL + -1 )
- + ShortString
- + Punct
- + FromImport
- + RaiseException
- + DefFunction
- + DefClass
- + Keyword * ( Space + Punct + Delim + EOL + -1 )
- + Decorator
- + Builtin * ( Space + Punct + Delim + EOL + -1 )
- + Identifier
- + Number
- + Word
-MainLoopPython =
- ( ( space^1 * -1 )
- + MainPython
- ) ^ 0
-local python = P ( true )
-
-python =
- Ct (
- ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1
- * BeamerBeginEnvironments
- * PromptHastyDetection
- * Lc '\\__piton_begin_line:'
- * Prompt
- * SpaceIndentation ^ 0
- * MainLoopPython
- * -1
- * Lc '\\__piton_end_line:'
- )
-languages['python'] = python
-local Delim = Q ( P "[|" + P "|]" + S "[()]" )
-local Punct = Q ( S ",:;!" )
-local cap_identifier = R "AZ" * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0
-local Constructor = K ( 'Name.Constructor' , cap_identifier )
-local ModuleType = K ( 'Name.Type' , cap_identifier )
-local identifier =
- ( R "az" + P "_") * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0
-local Identifier = K ( 'Identifier' , identifier )
-local expression_for_fields =
- P { "E" ,
- E = ( P "{" * V "F" * P "}"
- + P "(" * V "F" * P ")"
- + P "[" * V "F" * P "]"
- + P "\"" * (P "\\\"" + 1 - S "\"\r" )^0 * P "\""
- + P "'" * ( P "\\'" + 1 - S "'\r" )^0 * P "'"
- + ( 1 - S "{}()[]\r;" ) ) ^ 0 ,
- F = ( P "{" * V "F" * P "}"
- + P "(" * V "F" * P ")"
- + P "[" * V "F" * P "]"
- + ( 1 - S "{}()[]\r\"'" ) ) ^ 0
- }
-local OneFieldDefinition =
- ( K ( 'KeyWord' , P "mutable" ) * SkipSpace ) ^ -1
- * K ( 'Name.Field' , identifier ) * SkipSpace
- * Q ":" * SkipSpace
- * K ( 'Name.Type' , expression_for_fields )
- * SkipSpace
-
-local OneField =
- K ( 'Name.Field' , identifier ) * SkipSpace
- * Q "=" * SkipSpace
- * ( C ( expression_for_fields ) / ( function (s) return LoopOCaml:match(s) end ) )
- * SkipSpace
-
-local Record =
- Q "{" * SkipSpace
- *
- (
- OneFieldDefinition * ( Q ";" * SkipSpace * OneFieldDefinition ) ^ 0
- +
- OneField * ( Q ";" * SkipSpace * OneField ) ^ 0
- )
- *
- Q "}"
-local DotNotation =
- (
- K ( 'Name.Module' , cap_identifier )
- * Q "."
- * ( Identifier + Constructor + Q "(" + Q "[" + Q "{" )
-
- +
- Identifier
- * Q "."
- * K ( 'Name.Field' , identifier )
- )
- * ( Q "." * K ( 'Name.Field' , identifier ) ) ^ 0
-local Operator =
- K ( 'Operator' ,
- P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":="
- + P "||" + P "&&" + P "//" + P "**" + P ";;" + P "::" + P "->"
- + P "+." + P "-." + P "*." + P "/."
- + S "-~+/*%=<>&@|"
- )
-
-local OperatorWord =
- K ( 'Operator.Word' ,
- P "and" + P "asr" + P "land" + P "lor" + P "lsl" + P "lxor"
- + P "mod" + P "or" )
-
-local Keyword =
- K ( 'Keyword' ,
- P "assert" + P "as" + P "begin" + P "class" + P "constraint" + P "done"
- + P "downto" + P "do" + P "else" + P "end" + P "exception" + P "external"
- + P "for" + P "function" + P "functor" + P "fun" + P "if"
- + P "include" + P "inherit" + P "initializer" + P "in" + P "lazy" + P "let"
- + P "match" + P "method" + P "module" + P "mutable" + P "new" + P "object"
- + P "of" + P "open" + P "private" + P "raise" + P "rec" + P "sig"
- + P "struct" + P "then" + P "to" + P "try" + P "type"
- + P "value" + P "val" + P "virtual" + P "when" + P "while" + P "with" )
- + K ( 'Keyword.Constant' , P "true" + P "false" )
-
-local Builtin =
- K ( 'Name.Builtin' , P "not" + P "incr" + P "decr" + P "fst" + P "snd" )
-local Exception =
- K ( 'Exception' ,
- P "Division_by_zero" + P "End_of_File" + P "Failure"
- + P "Invalid_argument" + P "Match_failure" + P "Not_found"
- + P "Out_of_memory" + P "Stack_overflow" + P "Sys_blocked_io"
- + P "Sys_error" + P "Undefined_recursive_module" )
-local Char =
- K ( 'String.Short' , P "'" * ( ( 1 - P "'" ) ^ 0 + P "\\'" ) * P "'" )
-local balanced_braces =
- P { "E" ,
- E =
- (
- P "{" * V "E" * P "}"
- +
- P "\"" * ( 1 - S "\"" ) ^ 0 * P "\"" -- OCaml strings
- +
- ( 1 - S "{}" )
- ) ^ 0
- }
-if piton_beamer
-then
- Beamer =
- L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 )
- +
- Ct ( Cc "Open"
- * C (
- (
- P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
- + P "\\invisible" + P "\\action"
- )
- * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
- * P "{"
- )
- * Cc "}"
- )
- * ( C ( balanced_braces ) / (function (s) return MainLoopOCaml:match(s) end ) )
- * P "}" * Ct ( Cc "Close" )
- + OneBeamerEnvironment ( "uncoverenv" , MainLoopOCaml )
- + OneBeamerEnvironment ( "onlyenv" , MainLoopOCaml )
- + OneBeamerEnvironment ( "visibleenv" , MainLoopOCaml )
- + OneBeamerEnvironment ( "invisibleenv" , MainLoopOCaml )
- + OneBeamerEnvironment ( "alertenv" , MainLoopOCaml )
- + OneBeamerEnvironment ( "actionenv" , MainLoopOCaml )
- +
- L (
- ( P "\\alt" )
- * P "<" * (1 - P ">") ^ 0 * P ">"
- * P "{"
- )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}{" )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}" )
- +
- L (
- ( P "\\temporal" )
- * P "<" * (1 - P ">") ^ 0 * P ">"
- * P "{"
- )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}{" )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}{" )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}" )
-end
-local EOL =
- P "\r"
- *
- (
- ( space^0 * -1 )
- +
- Ct (
- Cc "EOL"
- *
- Ct (
- Lc "\\__piton_end_line:"
- * BeamerEndEnvironments
- * BeamerBeginEnvironments
- * PromptHastyDetection
- * Lc "\\__piton_newline: \\__piton_begin_line:"
- * Prompt
- )
- )
- )
- *
- SpaceIndentation ^ 0
-local ocaml_string =
- Q ( P "\"" )
- * (
- VisualSpace
- +
- Q ( ( 1 - S " \"\r" ) ^ 1 )
- +
- EOL
- ) ^ 0
- * Q ( P "\"" )
-local String = WithStyle ( 'String.Long' , ocaml_string )
-local ext = ( R "az" + P "_" ) ^ 0
-local open = "{" * Cg(ext, 'init') * "|"
-local close = "|" * C(ext) * "}"
-local closeeq =
- Cmt ( close * Cb('init'),
- function (s, i, a, b) return a==b end )
-local QuotedStringBis =
- WithStyle ( 'String.Long' ,
- (
- VisualSpace
- +
- Q ( ( 1 - S " \r" ) ^ 1 )
- +
- EOL
- ) ^ 0 )
-
-local QuotedString =
- C ( open * ( 1 - closeeq ) ^ 0 * close ) /
- ( function (s) return QuotedStringBis : match(s) end )
-local Comment =
- WithStyle ( 'Comment' ,
- P {
- "A" ,
- A = Q "(*"
- * ( V "A"
- + Q ( ( 1 - P "(*" - P "*)" - S "\r$\"" ) ^ 1 ) -- $
- + ocaml_string
- + P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" -- $
- + EOL
- ) ^ 0
- * Q "*)"
- } )
-local balanced_parens =
- P { "E" ,
- E =
- (
- P "(" * V "E" * P ")"
- +
- ( 1 - S "()" )
- ) ^ 0
- }
-local Argument =
- K ( 'Identifier' , identifier )
- + Q "(" * SkipSpace
- * K ( 'Identifier' , identifier ) * SkipSpace
- * Q ":" * SkipSpace
- * K ( 'Name.Type' , balanced_parens ) * SkipSpace
- * Q ")"
-local DefFunction =
- K ( 'Keyword' , P "let open" )
- * Space
- * K ( 'Name.Module' , cap_identifier )
- +
- K ( 'Keyword' , P "let rec" + P "let" + P "and" )
- * Space
- * K ( 'Name.Function.Internal' , identifier )
- * Space
- * (
- Q "=" * SkipSpace * K ( 'Keyword' , P "function" )
- +
- Argument
- * ( SkipSpace * Argument ) ^ 0
- * (
- SkipSpace
- * Q ":"
- * K ( 'Name.Type' , ( 1 - P "=" ) ^ 0 )
- ) ^ -1
- )
-local DefModule =
- K ( 'Keyword' , P "module" ) * Space
- *
- (
- K ( 'Keyword' , P "type" ) * Space
- * K ( 'Name.Type' , cap_identifier )
- +
- K ( 'Name.Module' , cap_identifier ) * SkipSpace
- *
- (
- Q "(" * SkipSpace
- * K ( 'Name.Module' , cap_identifier ) * SkipSpace
- * Q ":" * SkipSpace
- * K ( 'Name.Type' , cap_identifier ) * SkipSpace
- *
- (
- Q "," * SkipSpace
- * K ( 'Name.Module' , cap_identifier ) * SkipSpace
- * Q ":" * SkipSpace
- * K ( 'Name.Type' , cap_identifier ) * SkipSpace
- ) ^ 0
- * Q ")"
- ) ^ -1
- *
- (
- Q "=" * SkipSpace
- * K ( 'Name.Module' , cap_identifier ) * SkipSpace
- * Q "("
- * K ( 'Name.Module' , cap_identifier ) * SkipSpace
- *
- (
- Q ","
- *
- K ( 'Name.Module' , cap_identifier ) * SkipSpace
- ) ^ 0
- * Q ")"
- ) ^ -1
- )
- +
- K ( 'Keyword' , P "include" + P "open" )
- * Space * K ( 'Name.Module' , cap_identifier )
-local TypeParameter = K ( 'TypeParameter' , P "'" * alpha * # ( 1 - P "'" ) )
-MainOCaml =
- EOL
- + Space
- + Tab
- + Escape
- + Beamer
- + TypeParameter
- + String + QuotedString + Char
- + Comment
- + Delim
- + Operator
- + Punct
- + FromImport
- + Exception
- + DefFunction
- + DefModule
- + Record
- + Keyword * ( Space + Punct + Delim + EOL + -1 )
- + OperatorWord * ( Space + Punct + Delim + EOL + -1 )
- + Builtin * ( Space + Punct + Delim + EOL + -1 )
- + DotNotation
- + Constructor
- + Identifier
- + Number
- + Word
-
-LoopOCaml = MainOCaml ^ 0
-
-MainLoopOCaml =
- ( ( space^1 * -1 )
- + MainOCaml
- ) ^ 0
-local ocaml = P ( true )
-
-ocaml =
- Ct (
- ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1
- * BeamerBeginEnvironments
- * Lc ( '\\__piton_begin_line:' )
- * SpaceIndentation ^ 0
- * MainLoopOCaml
- * -1
- * Lc ( '\\__piton_end_line:' )
- )
-languages['ocaml'] = ocaml
-local Operator =
- K ( 'Operator' ,
- P "!=" + P "==" + P "<<" + P ">>" + P "<=" + P ">="
- + P "||" + P "&&" + S "-~+/*%=<>&.@|!"
- )
-
-local Keyword =
- K ( 'Keyword' ,
- P "alignas" + P "asm" + P "auto" + P "break" + P "case" + P "catch"
- + P "class" + P "const" + P "constexpr" + P "continue"
- + P "decltype" + P "do" + P "else" + P "enum" + P "extern"
- + P "for" + P "goto" + P "if" + P "nexcept" + P "private" + P "public"
- + P "register" + P "restricted" + P "return" + P "static" + P "static_assert"
- + P "struct" + P "switch" + P "thread_local" + P "throw" + P "try"
- + P "typedef" + P "union" + P "using" + P "virtual" + P "volatile"
- + P "while"
- )
- + K ( 'Keyword.Constant' ,
- P "default" + P "false" + P "NULL" + P "nullptr" + P "true"
- )
-
-local Builtin =
- K ( 'Name.Builtin' ,
- P "alignof" + P "malloc" + P "printf" + P "scanf" + P "sizeof"
- )
-
-local Type =
- K ( 'Name.Type' ,
- P "bool" + P "char" + P "char16_t" + P "char32_t" + P "double"
- + P "float" + P "int" + P "int8_t" + P "int16_t" + P "int32_t"
- + P "int64_t" + P "long" + P "short" + P "signed" + P "unsigned"
- + P "void" + P "wchar_t"
- )
-
-local DefFunction =
- Type
- * Space
- * K ( 'Name.Function.Internal' , identifier )
- * SkipSpace
- * # P "("
-local DefClass =
- K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier )
-local String =
- WithStyle ( 'String.Long' ,
- Q "\""
- * ( VisualSpace
- + K ( 'String.Interpol' ,
- P "%" * ( S "difcspxXou" + P "ld" + P "li" + P "hd" + P "hi" )
- )
- + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 )
- ) ^ 0
- * Q "\""
- )
-local balanced_braces =
- P { "E" ,
- E =
- (
- P "{" * V "E" * P "}"
- +
- String
- +
- ( 1 - S "{}" )
- ) ^ 0
- }
-if piton_beamer
-then
- Beamer =
- L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 )
- +
- Ct ( Cc "Open"
- * C (
- (
- P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible"
- + P "\\invisible" + P "\\action"
- )
- * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1
- * P "{"
- )
- * Cc "}"
- )
- * ( C ( balanced_braces ) / (function (s) return MainLoopC:match(s) end ) )
- * P "}" * Ct ( Cc "Close" )
- + OneBeamerEnvironment ( "uncoverenv" , MainLoopC )
- + OneBeamerEnvironment ( "onlyenv" , MainLoopC )
- + OneBeamerEnvironment ( "visibleenv" , MainLoopC )
- + OneBeamerEnvironment ( "invisibleenv" , MainLoopC )
- + OneBeamerEnvironment ( "alertenv" , MainLoopC )
- + OneBeamerEnvironment ( "actionenv" , MainLoopC )
- +
- L (
- ( P "\\alt" )
- * P "<" * (1 - P ">") ^ 0 * P ">"
- * P "{"
- )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}{" )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}" )
- +
- L (
- ( P "\\temporal" )
- * P "<" * (1 - P ">") ^ 0 * P ">"
- * P "{"
- )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}{" )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}{" )
- * K ( 'ParseAgain.noCR' , balanced_braces )
- * L ( P "}" )
-end
-local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\__piton_prompt:' ) ) ^ -1
-local Prompt = K ( 'Prompt' , ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1 )
-local EOL =
- P "\r"
- *
- (
- ( space^0 * -1 )
- +
- Ct (
- Cc "EOL"
- *
- Ct (
- Lc "\\__piton_end_line:"
- * BeamerEndEnvironments
- * BeamerBeginEnvironments
- * PromptHastyDetection
- * Lc "\\__piton_newline: \\__piton_begin_line:"
- * Prompt
- )
- )
- )
- *
- SpaceIndentation ^ 0
-local Preproc =
- K ( 'Preproc' , P "#" * (1 - P "\r" ) ^ 0 ) * ( EOL + -1 )
-local CommentMath =
- P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$"
-
-local Comment =
- WithStyle ( 'Comment' ,
- Q ( P "//" )
- * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 )
- * ( EOL + -1 )
-
-local LongComment =
- WithStyle ( 'Comment' ,
- Q ( P "/*" )
- * ( CommentMath + Q ( ( 1 - P "*/" - S "$\r" ) ^ 1 ) + EOL ) ^ 0
- * Q ( P "*/" )
- ) -- $
-local CommentLaTeX =
- P(piton.comment_latex)
- * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces"
- * L ( ( 1 - P "\r" ) ^ 0 )
- * Lc "}}"
- * ( EOL + -1 )
-local MainC =
- EOL
- + Space
- + Tab
- + Escape
- + CommentLaTeX
- + Beamer
- + Preproc
- + Comment + LongComment
- + Delim
- + Operator
- + String
- + Punct
- + DefFunction
- + DefClass
- + Type * ( Q ( "*" ) ^ -1 + Space + Punct + Delim + EOL + -1 )
- + Keyword * ( Space + Punct + Delim + EOL + -1 )
- + Builtin * ( Space + Punct + Delim + EOL + -1 )
- + Identifier
- + Number
- + Word
-MainLoopC =
- ( ( space^1 * -1 )
- + MainC
- ) ^ 0
-languageC =
- Ct (
- ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1
- * BeamerBeginEnvironments
- * PromptHastyDetection
- * Lc '\\__piton_begin_line:'
- * Prompt
- * SpaceIndentation ^ 0
- * MainLoopC
- * -1
- * Lc '\\__piton_end_line:'
- )
-languages['c'] = languageC
-function piton.Parse(language,code)
- local t = languages[language] : match ( code )
- if t == nil
- then
- tex.sprint("\\PitonSyntaxError")
- return -- to exit in force the function
- end
- local left_stack = {}
- local right_stack = {}
- for _ , one_item in ipairs(t)
- do
- if one_item[1] == "EOL"
- then
- for _ , s in ipairs(right_stack)
- do tex.sprint(s)
- end
- for _ , s in ipairs(one_item[2])
- do tex.tprint(s)
- end
- for _ , s in ipairs(left_stack)
- do tex.sprint(s)
- end
- else
- if one_item[1] == "Open"
- then
- tex.sprint( one_item[2] )
- table.insert(left_stack,one_item[2])
- table.insert(right_stack,one_item[3])
- else
- if one_item[1] == "Close"
- then
- tex.sprint( right_stack[#right_stack] )
- left_stack[#left_stack] = nil
- right_stack[#right_stack] = nil
- else
- tex.tprint(one_item)
- end
- end
- end
- end
-end
-function piton.ParseFile(language,name,first_line,last_line)
- local s = ''
- local i = 0
- for line in io.lines(name)
- do i = i + 1
- if i >= first_line
- then s = s .. '\r' .. line
- end
- if i >= last_line then break end
- end
- if string.byte(s,1) == 13
- then if string.byte(s,2) == 239
- then if string.byte(s,3) == 187
- then if string.byte(s,4) == 191
- then s = string.sub(s,5,-1)
- end
- end
- end
- end
- piton.Parse(language,s)
-end
-function piton.ParseBis(language,code)
- local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( code )
- return piton.Parse(language,s)
-end
-function piton.ParseTer(language,code)
- local s = ( Cs ( ( P '\\__piton_breakable_space:' / ' ' + 1 ) ^ 0 ) )
- : match ( code )
- return piton.Parse(language,s)
-end
-local function gobble(n,code)
- function concat(acc,new_value)
- return acc .. new_value
- end
- if n==0
- then return code
- else
- return Cf (
- Cc ( "" ) *
- ( 1 - P "\r" ) ^ (-n) * C ( ( 1 - P "\r" ) ^ 0 )
- * ( C ( P "\r" )
- * ( 1 - P "\r" ) ^ (-n)
- * C ( ( 1 - P "\r" ) ^ 0 )
- ) ^ 0 ,
- concat
- ) : match ( code )
- end
-end
-local function add(acc,new_value)
- return acc + new_value
-end
-local AutoGobbleLPEG =
- ( space ^ 0 * P "\r" ) ^ -1
- * Cf (
- (
- ( P " " ) ^ 0 * P "\r"
- +
- Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add )
- * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 * P "\r"
- ) ^ 0
- *
- ( Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add )
- * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 ,
- math.min
- )
-local TabsAutoGobbleLPEG =
- ( space ^ 0 * P "\r" ) ^ -1
- * Cf (
- (
- ( P "\t" ) ^ 0 * P "\r"
- +
- Cf ( Cc(0) * ( P "\t" * Cc(1) ) ^ 0 , add )
- * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 * P "\r"
- ) ^ 0
- *
- ( Cf ( Cc(0) * ( P "\t" * Cc(1) ) ^ 0 , add )
- * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 ,
- math.min
- )
-local EnvGobbleLPEG =
- ( ( 1 - P "\r" ) ^ 0 * P "\r" ) ^ 0
- * Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add ) * -1
-function piton.GobbleParse(language,n,code)
- if n==-1
- then n = AutoGobbleLPEG : match(code)
- else if n==-2
- then n = EnvGobbleLPEG : match(code)
- else if n==-3
- then n = TabsAutoGobbleLPEG : match(code)
- end
- end
- end
- piton.Parse(language,gobble(n,code))
-end
-function piton.CountLines(code)
- local count = 0
- for i in code : gmatch ( "\r" ) do count = count + 1 end
- tex.sprint(
- luatexbase.catcodetables.expl ,
- '\\int_set:Nn \\l__piton_nb_lines_int {' .. count .. '}' )
-end
-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__piton_nb_non_empty_lines_int {' .. count .. '}' )
-end
-function piton.CountLinesFile(name)
- local count = 0
- for line in io.lines(name) do count = count + 1 end
- tex.sprint(
- luatexbase.catcodetables.expl ,
- '\\int_set:Nn \\l__piton_nb_lines_int {' .. count .. '}' )
-end
-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__piton_nb_non_empty_lines_int {' .. count .. '}' )
-end
-\end{luacode*}
-
\endinput
%%
%% End of file `piton.sty'.
More information about the tex-live-commits
mailing list.