texlive[65835] Master/texmf-dist: piton (14feb23)

commits+karl at tug.org commits+karl at tug.org
Tue Feb 14 21:41:38 CET 2023


Revision: 65835
          http://tug.org/svn/texlive?view=revision&revision=65835
Author:   karl
Date:     2023-02-14 21:41:38 +0100 (Tue, 14 Feb 2023)
Log Message:
-----------
piton (14feb23)

Modified Paths:
--------------
    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

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-02-14 20:41:19 UTC (rev 65834)
+++ trunk/Master/texmf-dist/doc/lualatex/piton/piton-french.tex	2023-02-14 20:41:38 UTC (rev 65835)
@@ -21,6 +21,7 @@
 \usepackage{tabularx}
 \usepackage{booktabs}
 \usepackage{tcolorbox}
+\usepackage{luacolor,lua-ul}
 
 \usepackage{caption}
 
@@ -201,8 +202,7 @@
 non équilibrées.
 
 \smallskip
-\colorbox{yellow!50}{\textbf{Nouveau 1.3}}\enskip La commande |\|␣ insère un espace. Elle peut être utilisée si on
-veut insérer plusieurs espaces successifs.
+La commande |\|␣ insère un espace. Elle peut être utilisée si on veut insérer plusieurs espaces successifs.
 
 \smallskip
 Les autres caractères (y compris |#|, |^|, |_|, |&|, |$| % $
@@ -298,21 +298,26 @@
 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 égale à la valeur courante de |\linewidth|).
+produits par |\PitonInputFile| (ce fond a une largeur égale à la valeur courante de |\linewidth|). La clé
+|background-color| accepte une couleur définie «à la volée», c'est-à-dire que l'on peut écrire par exemple
+|background-color = [cmyk]{0.1,0.05,0,0}|
 
-\colorbox{yellow!50}{\textbf{Nouveau 1.3}}\enskip La clé |background-color| accepte une couleur définie «à la
-volée», c'est-à-dire que l'on peut écrire par exemple |background-color = [cmyk]{0.1,0.05,0,0}|
+\smallskip
+\colorbox{yellow!50}{\textbf{Nouveau 1.4}}\enskip La clé |background-color| accepte aussi en argument une
+\emph{liste} de couleurs. Les lignes sont alors coloriées de manière cyclique avec ces couleurs.
 
-\item \colorbox{yellow!50}{\textbf{Nouveau 1.3}}\enskip Avec la clé \Definition{prompt-background-color},
-\pkg{piton} ajoute un fond coloré aux lignes débutant par le prompt «|>>>|» (et sa continuation «|...|»)
-caractéristique des consoles Python avec boucle \textsc{repl} (\emph{read-only-eval loop}). Pour un exemple
-d'utilisation de cette clé, voir la partie \ref{pythonrepl} p.~\pageref{pythonrepl}
+\emph{Exemple} : |\PitonOptions{background-color = {gray!5,white}}|
 
-\item \colorbox{yellow!50}{\textbf{Modification 1.2}}\enskip En activant la clé \Definition{show-spaces-in-strings}, les
-espaces dans les chaînes courtes (c'est-à-dire celles délimitées par |'| ou |"|) sont matérialisés par le caractère
-␣ (U+2423 : \textsc{open box}). Bien sûr, le caractère U+2423 doit être présent dans la fonte mono-chasse
-utilisée.\footnote{L'extension \pkg{piton} utilise simplement la fonte mono-chasse courante. Pour la changer, le
-  mieux est d'utiliser |\setmonofont| de \pkg{fontspec}.}\par\nobreak
+\item Avec la clé \Definition{prompt-background-color}, \pkg{piton} ajoute un fond coloré aux lignes débutant par
+le prompt «|>>>|» (et sa continuation «|...|») caractéristique des consoles Python avec boucle \textsc{repl}
+(\emph{read-only-eval loop}). Pour un exemple d'utilisation de cette clé, voir la partie \ref{pythonrepl}
+p.~\pageref{pythonrepl}.
+
+\item En activant la clé \Definition{show-spaces-in-strings}, les espaces dans les chaînes courtes (c'est-à-dire
+celles délimitées par |'| ou |"|) sont matérialisés par le caractère ␣ (U+2423 : \textsc{open box}). Bien sûr, le
+caractère U+2423 doit être présent dans la fonte mono-chasse utilisée.\footnote{L'extension \pkg{piton} utilise
+  simplement la fonte mono-chasse courante. Pour la changer, le mieux est d'utiliser |\setmonofont| de
+  \pkg{fontspec}.}\par\nobreak
 %
 \begingroup
 \PitonOptions{show-spaces-in-strings}
@@ -402,21 +407,21 @@
 
 \bigskip
 Voici un exemple qui change le style utilisé pour le nom d'une fonction Python, au moment de sa définition
-(c'est-à-dire après le mot-clé |def|).
+(c'est-à-dire après le mot-clé |def|). Elle utilise la commande |\highLight| de \pkg{lua-ul} (qui nécessite aussi
+le chargement de \pkg{luacolor}).
 
 \begin{Verbatim}
 \SetPitonStyle
-  { Name.Function = \bfseries \setlength{\fboxsep}{1pt}\colorbox{yellow!50} }
+  { Name.Function = \bfseries \hightLight[red!50] }
 \end{Verbatim}
 
-Dans cet exemple, |\colorbox{yellow!50}| doit être considéré comme le nom d'une fonction LaTeX qui prend exactement
-un argument, puisque, habituellement, elle est utilisée avec la syntaxe 
-|\colorbox{yellow!50}{|\texttt{\slshape text}|}|. 
+Ici, |\highLight[red!50]| doit être considéré comme le nom d'une fonction LaTeX qui prend exactement un argument,
+puisque, habituellement, elle est utilisée avec |\highLight[red!50]{|\texttt{\slshape text}|}|.
 
 \medskip
 \begingroup
 \SetPitonStyle 
-  { Name.Function = \bfseries \setlength{\fboxsep}{1pt}\colorbox{yellow!50} }
+  { Name.Function = \bfseries \highLight[red!50] }
 Avec ce réglage, on obtient : \piton{def cube(x) : return x * x * x }
 \endgroup
 
@@ -462,15 +467,23 @@
           global, if, import, lambda, non local,
           pass, raise, return, try, while,
           with, yield, yield from.\\
-  \bottomrule
+\bottomrule
 \end{tabularx}
 \end{table}
 
+\bigskip
+\colorbox{yellow!50}{\textbf{Nouveau 1.4}}\enskip La commande |\PitonStyle| prend en argument le nom d'un style
+et permet de récupérer la valeur (en tant que liste d'instructions LaTeX) de ce style.
 
+\smallskip
+Par exemple, on peut écrire, dans le texte courant, |{\PitonStyle{Keyword}{function}}| et on aura 
+le mot {\PitonStyle{Keyword}{function}} formaté comme un mot-clé.
 
+\smallskip
+La syntaxe |{\PitonStyle{|\textsl{\texttt{style}}|}{...}}| est nécessaire pour pouvoir tenir compte à la fois des commandes
+semi-globales et des commandes à argument présentes dans la valeur courante du style \texttt{\textsl{style}}.
 
 
-
 \subsection{Définition de nouveaux environnements}
 
 \label{NewPitonEnvironment}
@@ -497,13 +510,13 @@
 
 \bigskip
 Si on souhaite un environnement |{Python}| qui compose le code inclus dans une boîte de \pkg{tcolorbox}, on peut
-écrire:
+écrire (à condition, bien entendu, d'avoir chargé l'extension \pkg{tcolorbox}):
 
-\begin{verbatim}
+\begin{Verbatim}
 \NewPitonEnvironment{Python}{}
   {\begin{tcolorbox}}
   {\end{tcolorbox}}
-\end{verbatim}
+\end{Verbatim}
 
 \bigskip
 Avec ce nouvel environnement |{Python}|, on peut écrire : 
@@ -529,6 +542,126 @@
 
 \section{Fonctionnalités avancées}
 
+
+\subsection{Mise en évidence d'identificateurs}
+
+\colorbox{yellow!50}{\textbf{Nouveau 1.4}}
+
+On peut demander le changement de formatage de certains identificateurs avec la clé |identifiers| de
+|\PitonOptions|.  
+
+\smallskip
+Cette clé prend en argument une valeur au format suivant : 
+
+\quad |{ noms = |\textsl{\ttfamily noms}|, style = |\textsl{\ttfamily instructions}| }|
+
+\begin{itemize}
+\item \textsl{\ttfamily noms} est une liste de noms d'identificateurs (séparés par des virgules) ; 
+
+\item \textsl{\ttfamily instructions} est une liste d'instructions LaTeX de formatage du même type que les styles
+précédemment définis (cf.~\ref{styles} p.~\pageref{styles}).
+\end{itemize}
+
+\emph{Attention} : Seuls les identifiants peuvent voir leur formatage affecté. Les mots-clés et les noms de
+fonctions prédéfinies ne seront pas affectés, même s'ils figurent dans la liste \textsl{\ttfamily noms}.
+
+\begin{Verbatim}
+\PitonOptions 
+  {
+    ~emphase#identifiers@ = 
+     {
+       ~emphase#names@ = { l1 , l2 } , 
+       ~emphase#style@ = \color{red} 
+     }
+  }
+
+\begin{Piton}
+def tri(l):
+    """Tri par segmentation"""
+    if len(l) <= 1:
+        return l
+    else:
+        a = l[0]
+        l1 = [ x for x in l[1:] if x < a  ]
+        l2 = [ x for x in l[1:] if x >= a ]
+        return tri(l1) + [a] + tri(l2)
+\end{Piton}
+\end{Verbatim}
+
+
+\bigskip
+
+\begingroup
+
+\PitonOptions 
+  {
+    identifiers = 
+     {
+       names = { l1 , l2 } , 
+       style = \color{red} 
+     }
+  }
+
+\begin{Piton}
+def tri(l):
+    """Tri par segmentation"""
+    if len(l) <= 1:
+        return l
+    else:
+        a = l[0]
+        l1 = [ x for x in l[1:] if x < a  ]
+        l2 = [ x for x in l[1:] if x >= a ]
+        return tri(l1) + [a] + tri(l2)
+\end{Piton}
+
+\endgroup
+
+\bigskip
+En utilisant la clé |identifiers|, on peut ajouter de nouvelles fonctions prédéfinies (ou de nouveaux mots-clés,
+etc.) qui seront détectées par \pkg{piton}.
+
+
+\begin{Verbatim}
+\PitonOptions 
+  {
+    ~emphase#identifiers@ = 
+     {
+       names = { cos, sin, tan, floor, ceil, trunc, pow, exp, ln, factorial } , 
+       style = \PitonStyle{Name.Builtin}
+     }
+  }
+
+\begin{Piton}
+from math import *
+cos(pi/2) 
+factorial(5)
+ceil(-2.3) 
+floor(5.4) 
+\end{Piton}
+\end{Verbatim}
+
+\begingroup
+
+\PitonOptions 
+  {
+    identifiers = 
+     {
+       names = { cos, sin, tan, floor, ceil, trunc, pow, exp, ln, factorial } , 
+       style = \PitonStyle{Name.Builtin}
+     }
+  }
+
+\begin{Piton}
+from math import *
+cos(pi/2) 
+factorial(5)
+ceil(-2.3) 
+floor(5.4) 
+\end{Piton}
+
+
+\endgroup
+
 \subsection{Les échappements vers LaTeX}
 
 L'extension \pkg{piton} propose plusieurs mécanismes d'échappement vers LaTeX :
@@ -585,12 +718,12 @@
 \end{itemize}
 
 
-\bigskip
-\colorbox{yellow!50}{\textbf{Nouveau 1.3}}\enskip 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.)}
+\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.)}
 
 
 
@@ -638,7 +771,8 @@
 
 \medskip
 Dans le code suivant, qui est une programmation récursive de la factorielle, on décide de surligner en jaune
-l'instruction qui contient l'appel récursif.
+l'instruction qui contient l'appel récursif. Cet exemple utilise la commande |\highLight| de \pkg{lua-ul} (cette
+extension requiert aussi l'extension \pkg{luacolor}).
 \begin{Verbatim}
 \begin{Piton}
 def fact(n):
@@ -645,7 +779,7 @@
     if n==0:
         return 1
     else:
-        ~emphase#$\colorbox{yellow!50}{$@return n*fact(n-1)~emphase#$}$@
+        ~emphase#$\highLight{$@return n*fact(n-1)~emphase#$}$@
 \end{Piton}
 \end{Verbatim}
 
@@ -654,14 +788,54 @@
     if n==0:
         return 1
     else:
-        $\colorbox{yellow!50}{$return n*fact(n-1)$}$
+        $\highLight{$return n*fact(n-1)$}$
 \end{Piton}
 
 \bigskip
+En fait, dans le cas présent, il serait sans doute plus habile d'utiliser la commande |\@highLight| de
+\pkg{lua-ul}: cette commande bascule vers un fond jaune jusqu'à la fin du groupe TeX courant. Comme le nom de cette
+commande contient le caractère |@|, il convient de lui donner un synonyme sans caractère |@| pour pouvoir
+l'utiliser directement dans |{Piton}|.
+
+\begingroup
+\fvset{commandchars=\~\#\+,formatcom=\color{gray}}
+\begin{Verbatim}
+\makeatletter
+~emphase#\let\Jaune\@highLight+
+\makeatother
+\end{Verbatim}
+\endgroup
+
+\begin{Verbatim}
+\begin{Piton}
+def fact(n):
+    if n==0:
+        return 1
+    else:
+        ~emphase#$\Jaune$@return n*fact(n-1)
+\end{Piton}
+\end{Verbatim}
+
+\makeatletter
+\let\Jaune\@highLight
+\makeatother
+
+
+\begin{Piton}
+def fact(n):
+    if n==0:
+        return 1
+    else:
+        $\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 |#>|).
+appelé dans ce document «commentaire LaTeX», il suffit de le faire débuter par |#>|).
 
 
 
@@ -713,12 +887,13 @@
 \medskip
 Néanmoins, il y a deux restrictions pour le contenu des arguments obligatoires de ces commandes.
 \begin{itemize}
-\item les accolades dans les arguments obligatoires de ces commandes doivent être équilibrées (cependant, les
+\item Les accolades dans les arguments obligatoires de ces commandes doivent être équilibrées (cependant, les
 accolades présentes dans des chaînes courtes\footnote{Les chaînes courtes de Python sont les chaînes (string)
   délimitées par les caractères \texttt{'} ou \texttt{"} non triplés. En Python, les chaînes de caractères courtes
-  ne peuvent pas s'étendre sur plusieurs lignes de code.} de Python ne sont pas prises en compte) ;
-\item l'argument obligatoire ne doit pas contenir \textbf{aucun retour à la ligne} (s'il y en a, une erreur
-fatale est levée). 
+  ne peuvent pas s'étendre sur plusieurs lignes de code.} de Python ne sont pas prises en compte).
+\item L'argument obligatoire ne doit contenir \textbf{aucun retour à la ligne} (s'il y en a, une erreur
+fatale est levée). Pour les éléments de plusieurs lignes, on pourra utiliser les environnements correspondants
+(voir ci-dessous).
 \end{itemize}
 
 \medskip
@@ -747,21 +922,23 @@
 \end{document}
 \end{Verbatim}
 
-Dans l'exemple précédent, les accolades des deux chaînes de caractères Python |"{"| et |"}"| sont correctement interprétées (sans aucun
-caractère d'échappement).
+Dans l'exemple précédent, les accolades des deux chaînes de caractères Python |"{"| et |"}"| sont correctement
+interprétées (sans aucun caractère d'échappement).
 
 
+
 \bigskip
 \subsubsection{Environnements de Beamer reconnus dans \{Piton\} et \textbackslash PitonInputFile}
 
 Quand \pkg{piton} est utilisé dans la classe \pkg{beamer}, les environnements suivants de Beamer sont directement
 reconnus dans les environnements |{Piton}| (ainsi que dans les listings composés par la commande |\PitonInputFile|
-même si c'est sans doute moins utile).: |{uncoverenv}|, |{onlyenv}|, |{visibleenv}| et |{invisibleenv}|.
+même si c'est sans doute moins utile) : |{actionenv}|, |{alertenv}|, |{invisibleenv}|, |{onlyenv}|, |{uncoverenv}|
+et |{visibleenv}|.
 
+
 \medskip
 Il y a néanmoins une restriction : ces environnements doivent englober des \emph{lignes entières de code Python}.
 
-\pagebreak
 
 \medskip
 On peut par exemple écrire :
@@ -784,8 +961,42 @@
 
 
 
+\vspace{1cm}
+\textbf{Remarque à propos de la commande \textbackslash alert et de l'environnement \{alertenv\} de Beamer}\par\nobreak
 
+\smallskip
+Beamer propose un moyen aisé de changer la couleur utilisée par l'environnement |{alertenv}| (et par la commande
+|\alert| qui s'appuie dessus). Par exemple, on peut écrire:
 
+\begin{Verbatim}
+\setbeamercolor{~emphase#alerted text@}{fg=blue} 
+\end{Verbatim}
+
+Néanmoins, dans le cas d'une utilisation à l'intérieur d'un environnement |{Piton}| un tel réglage n'est sans doute
+pas pertinent, puisque, justement, \pkg{piton} va (le plus souvent) changer la couleur des élements selon leur
+valeur lexicale. On préfèrera sans doute un environnement |{alertenv}| qui change la couleur de fond des
+éléments à mettre en évidence.
+
+\smallskip
+Voici un code qui effectuera ce travail en mettant un fond jaune. Ce code utilise la commande |\@highLight| de
+l'extension \pkg{lua-ul} (cette extension nécessite elle-même l'extension \pkg{luacolor}).
+
+\begingroup
+\fvset{commandchars=\~\#\+,formatcom=\color{gray}}
+\begin{Verbatim}
+\setbeamercolor{alerted text}{bg=yellow!50}
+\makeatletter
+\AddToHook{env/Piton/begin}
+  {\renewenvironment<>{alertenv}{\only~#1{~emphase#\@highLight+[alerted text.bg]}}{}}
+\makeatother
+\end{Verbatim}
+\endgroup
+
+Ce code redéfinit localement l'environnement |{alertenv}| à l'intérieur de l'environnement |{Piton}| (on rappelle
+que la commande |\alert| s'appuie sur cet environnement |{alertenv}|). 
+
+
+
 \bigskip
 \subsection{Coupure des pages et des lignes}
 
@@ -848,7 +1059,7 @@
 \end{itemize}
 
 \bigskip
-Le code suivant a été composé dans une |{minipage}| de largeur 12~cm avec le réglage suivant : 
+Le code suivant a été composé dans une |{minipage}| standard de LaTeX de largeur 12~cm avec le réglage suivant :  
 
 \begin{Verbatim}
 \PitonOptions{break-lines,indent-broken-lines,background-color=gray!15}
@@ -1195,7 +1406,9 @@
 \emph{DejaVu Sans Mono}\footnote{Voir: \url{https://dejavu-fonts.github.io}} spécifiée avec la commande
   |\setmonofont| de \pkg{fontspec}.
 
+Ce réglage utilise la commande |\highLight| de \pkg{lua-ul} (cette extension nécessite elle-même l'extension \pkg{luacolor}).
 
+
 \begin{Verbatim}
 \setmonofont[Scale=0.85]{DejaVu Sans Mono}
 
@@ -1207,7 +1420,7 @@
     Operator = , 
     Operator.Word = \bfseries ,
     Name.Builtin = ,
-    Name.Function = \bfseries \colorbox{gray!20} ,
+    Name.Function = \bfseries \highLight[gray!20] ,
     Comment = \color{gray} ,
     Comment.LaTeX = \normalfont \color{gray},
     Keyword = \bfseries ,
@@ -1232,7 +1445,7 @@
     Operator = , 
     Operator.Word = \bfseries ,
     Name.Builtin = ,
-    Name.Function = \bfseries \colorbox{gray!20} ,
+    Name.Function = \bfseries \highLight[gray!20] ,
     Comment = \color{gray} ,
     Comment.LaTeX = \normalfont \color{gray},
     Keyword = \bfseries ,
@@ -1281,7 +1494,7 @@
 
 \begin{Verbatim}
 \ExplSyntaxOn
-\NewDocumentEnvironment { ~emphase#PitonExecute@ } { ! O { } } 
+\NewDocumentEnvironment { ~emphase#PitonExecute@ } { ! O { } }  % le ! est obligatoire 
   { 
     \PyLTVerbatimEnv
     \begin{pythonq} 
@@ -1313,7 +1526,7 @@
     \end{pythonq}
     \directlua
       {
-        tex.print("\\PitonOptions{~#1}")
+        tex.print("\\PitonOptions{#1}")
         tex.print("\\begin{Piton}")
         tex.print(pyluatex.get_last_code())
         tex.print("\\end{Piton}")
@@ -1355,7 +1568,7 @@
 
 L'environnement |{pythonrepl}| de \pkg{pyluatex} passe son contenu à Python et renvoie ce que l'on obtient quand on
 fournit ce code à une boucle \textsc{repl} (\emph{read-eval-print loop}) de Python. On obtient un entrelacement
-d'instructions précédées par le prompt |>>>| de Python et des valeurs renovées par Python (et de ce qui a été
+d'instructions précédées par le prompt |>>>| de Python et des valeurs renvoyées par Python (et de ce qui a été
 demandé d'être affiché avec des \piton{print} de Python).
 
 \medskip
@@ -1365,10 +1578,11 @@
 
 
 \medskip
-Voici la programmation d'un environnement |{PitonREPL}| qui effectue ce travail.
+Voici la programmation d'un environnement |{PitonREPL}| qui effectue ce travail (pour des raisons techniques, le
+|!| est ici obligatoire dans la signature de l'environnement).
 
 \begin{Verbatim}
-\NewDocumentEnvironment { PitonREPL } { ! O { } }
+\NewDocumentEnvironment { PitonREPL } { ! O { } } % le ! est obligatoire
  { 
    \PitonOptions
      { background-color=white,
@@ -1396,16 +1610,16 @@
 \medskip
 \begin{Verbatim}
 ~emphase#\begin{PitonREPL}@
-def valeur_absolue(x):
-    "Renvoie la valeur absolue de x"
-    if x > 0:
-       return x
-    else:
-       return -x
+    def valeur_absolue(x):
+        "Renvoie la valeur absolue de x"
+        if x > 0:
+           return x
+        else:
+           return -x
 
-valeur_absolue(-3)
-valeur_absolue(0)
-valeur_absolue(5)
+    valeur_absolue(-3)
+    valeur_absolue(0)
+    valeur_absolue(5)
 ~emphase#\end{PitonREPL}@
 \end{Verbatim}
 
@@ -1431,20 +1645,78 @@
 
 
 \begin{PitonREPL}
-def valeur_absolue(x):
-    "Renvoie la valeur absolue de x"
-    if x > 0:
-       return x
-    else:
-       return -x
+    def valeur_absolue(x):
+        "Renvoie la valeur absolue de x"
+        if x > 0:
+           return x
+        else:
+           return -x
 
-valeur_absolue(-3)
-valeur_absolue(0)
-valeur_absolue(5)
+    valeur_absolue(-3)
+    valeur_absolue(0)
+    valeur_absolue(5)
 \end{PitonREPL}
 
 
+\bigskip
+En fait, il est possible de ne pas faire afficher les prompts eux-mêmes (c'est-à-dire les chaînes de caractères
+|>>>| et |...|). En effet, \pkg{piton} propose un style pour ces éléments, qui est appelé |Prompt|. Par défaut, la
+valeur de ce style est vide, ce qui fait qu'aucune action n'est exécutée sur ces éléments qui sont donc affichés
+tels quels. En fournissant comme valeur une fonction qui se contente de gober son argument, on peut demander à ce
+qu'ils ne soient pas affichés.
 
+\bigskip
+\begin{savenotes}
+\begin{Verbatim}
+\NewDocumentCommand{\Gobe}{m}{}#~color#black@~footnote#On a défini ici une fonction ~texttt#~string~Gobe@ mais, en fait, elle existe déjà en L3 sous le nom ~texttt#~string~use~_none:n at .@@
+\SetPitonStyle{ ~emphase#Prompt = \Gobe@ }
+\end{Verbatim}
+\end{savenotes}
+
+
+
+
+\NewDocumentCommand{\Gobe}{m}{}
+\ExplSyntaxOn
+\SetPitonStyle{ Prompt = \use_none:n }
+\ExplSyntaxOff
+
+\bigskip
+L'exemple précédent donne alors :
+
+\medskip
+\begin{Verbatim}
+~emphase#\begin{PitonREPL}@
+    def valeur_absolue(x):
+        "Renvoie la valeur absolue de x"
+        if x > 0:
+           return x
+        else:
+           return -x
+
+    valeur_absolue(-3)
+    valeur_absolue(0)
+    valeur_absolue(5)
+~emphase#\end{PitonREPL}@
+\end{Verbatim}
+
+
+
+\begin{PitonREPL}
+    def valeur_absolue(x):
+        "Renvoie la valeur absolue de x"
+        if x > 0:
+           return x
+        else:
+           return -x
+
+    valeur_absolue(-3)
+    valeur_absolue(0)
+    valeur_absolue(5)
+\end{PitonREPL}
+
+
+
 \section*{Autre documentation}
 
 Le document |piton.pdf| (fourni avec l'extension \pkg{piton}) contient une traduction anglaise de la
@@ -1451,4 +1723,6 @@
 documentation ici présente, ainsi que le code source commenté et un historique des versions. 
 
 
+\tableofcontents
+
 \end{document}
\ No newline at end of file

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-02-14 20:41:19 UTC (rev 65834)
+++ trunk/Master/texmf-dist/source/lualatex/piton/piton.dtx	2023-02-14 20:41:38 UTC (rev 65835)
@@ -15,8 +15,8 @@
 %
 % \fi
 % \iffalse
-\def\myfileversion{1.3}
-\def\myfiledate{2023/01/29}
+\def\myfileversion{1.4}
+\def\myfiledate{2023/02/14}
 %
 %
 %<*batchfile> 
@@ -26,7 +26,7 @@
 \usedir{tex/latex/cascade}
 \preamble
 
-Copyright (C) 2023 by F. Pantigny
+Copyright (C) 2022-2023 by F. Pantigny
 -----------------------------------
 
 This file may be distributed and/or modified under the
@@ -51,7 +51,7 @@
 \geometry{left=2.8cm,right=2.8cm,top=2.5cm,bottom=2.5cm,papersize={21cm,29.7cm}}
 \usepackage{fontspec}
 \usepackage[dvipsnames]{xcolor}
-\usepackage{caption,tabularx,tcolorbox}
+\usepackage{caption,tabularx,tcolorbox,luacolor,lua-ul}
 \def\emphase{\bgroup\color{RoyalPurple}\let\next=}
 \fvset{commandchars=\~\#\@,formatcom=\color{gray}}
 \captionsetup{labelfont = bf}
@@ -206,8 +206,8 @@
 % balanced.
 %
 % \smallskip
-% \colorbox{yellow!50}{\textbf{New 1.3}}\enskip The command |\|␣ inserts a
-% space. It may be used in order to insert several consecutive spaces.
+% The command |\|␣ inserts a space. It may be used in order to insert several
+% consecutive spaces. 
 %
 % \smallskip
 % The other characters (including |#|, |^|, |_|, |&|, |$| and |@|)
@@ -318,28 +318,35 @@
 % environments |{Piton}| and the listings produced by |\PitonInputFile| (that
 % background has a width of |\linewidth|).
 %
-% \colorbox{yellow!50}{\textbf{New 1.3}}\enskip The key |background-color|
-% accepts a color defined «on the fly». For example, it's possible to write
-% |background-color = [cmyk]{0.1,0.05,0,0}|.
+% \smallskip
+% \colorbox{yellow!50}{\textbf{New 1.4}}\enskip The key |background-color|
+% supports also as value a \emph{list} of colors. In this case, the successive
+% rows are colored by using the colors of the list in a cyclic way.
 %
-% \item \colorbox{yellow!50}{\textbf{New 1.3}}\enskip With the key
-% \Definition{prompt-background-color}, \pkg{piton} adds a color background to
-% the lines beginning with the prompt ``|>>>|'' (and its continuation ``|...|'')
-% charactéristic of the Python consoles with \textsc{repl} (\emph{read-eval-print loop}).
+% \emph{Example} : |\PitonOptions{background-color = {gray!5,white}}|
 %
-% \item \colorbox{yellow!50}{\textbf{Modified 1.2}}\enskip When the key
-% \Definition{show-spaces-in-strings} is activated, the spaces in the short strings (that
-% is to say those delimited by |'| or |"|) are replaced by the character~␣
-% (U+2423 : \textsc{open box}). Of course, that character~U+2423 must be present
-% in the monospaced font which is used.\footnote{The package \pkg{piton} simply
-% uses the current monospaced font. The best way to change that font is to use
-% the command \texttt{\textbackslash setmonofont} of
-% \pkg{fontspec}.}\par\nobreak \begingroup \PitonOptions{show-spaces-in-strings}
-% Example : \piton|my_string = 'Very good answer'| \endgroup
 %
-% With the key \Definition{show-spaces}, all the spaces are replaced by U+2423 (and no line
-% break can occur on those ``visible spaces'', even when the key |break-lines|
-% is in force).
+% The key |background-color| accepts a color defined «on the fly». For example,
+% it's possible to write |background-color = [cmyk]{0.1,0.05,0,0}|.
+%
+% \item With the key \Definition{prompt-background-color}, \pkg{piton} adds a
+% color background to the lines beginning with the prompt ``|>>>|'' (and its
+% continuation ``|...|'') characteristic of the Python consoles with
+% \textsc{repl} (\emph{read-eval-print loop}).
+%
+% \item When the key \Definition{show-spaces-in-strings} is activated, the
+% spaces in the short strings (that is to say those delimited by |'| or |"|) are
+% replaced by the character~␣ (U+2423 : \textsc{open box}). Of course, that
+% character~U+2423 must be present in the monospaced font which is
+% used.\footnote{The package \pkg{piton} simply uses the current monospaced
+% font. The best way to change that font is to use the command
+% \texttt{\textbackslash setmonofont} of \pkg{fontspec}.}\par\nobreak
+% \begingroup \PitonOptions{show-spaces-in-strings} Example : 
+% \piton|my_string = 'Very good answer'| \endgroup
+%
+% With the key \Definition{show-spaces}, all the spaces are replaced by U+2423
+% (and no line break can occur on those ``visible spaces'', even when the key
+% |break-lines| is in force).
 % \end{itemize}
 %
 % \bigskip
@@ -420,21 +427,22 @@
 % 
 % \bigskip
 % Here an example which changes the style used to highlight, in the definition
-% of a Python function, the name of the function which is defined.
+% of a Python function, the name of the function which is defined. That code
+% uses the command |\highLight| of \pkg{lua-ul} (that package requires also the
+% package \pkg{luacolor}).
 %
 % \begin{verbatim}
-% \SetPitonStyle 
-%   { Name.Function = \bfseries \setlength{\fboxsep}{1pt}\colorbox{yellow!50} }
+% \SetPitonStyle{ Name.Function = \bfseries \highLight[red!50] }
 % \end{verbatim}
 %
-% In that example, |\colorbox{yellow!50}| must be considered as the name of a
+% In that example, |\highLight[red!50]| must be considered as the name of a
 % LaTeX command which takes in exactly one argument, since, usually, it is used
-% with the syntax |\colorbox{yellow!50}{...}|.
+% with |\highLight[red!50]{...}|.
 %
 % \medskip
 % \begingroup
 % \SetPitonStyle 
-%   { Name.Function = \bfseries \setlength{\fboxsep}{1pt}\colorbox{yellow!50} }
+%   { Name.Function = \bfseries \highLight[red!50] }
 % With that setting, we will have : \piton{def cube(x) : return x * x * x }
 % \endgroup
 % 
@@ -444,8 +452,21 @@
 % \pkg{manni} de Pygments.\footnote{See:
 % \url{https://pygments.org/styles/}. Remark that, by default, Pygments provides for its style \pkg{manni} a colored background whose color is the HTML color \texttt{\#F0F3F3}. It's possible to have the same color in \texttt{\{Pion\}} with the instruction \texttt{\textbackslash PitonOptions\{background-color = [HTML]\{F0F3F3\}\}}.}
 %
+% \bigskip
+% \colorbox{yellow!50}{\textbf{New 1.4}}\enskip The command |\PitonStyle| takes
+% in as argument the name of a style and allows to retrieve the value (as a list
+% of LaTeX instructions) of that style.
 %
+% \smallskip
+% For example, it's possible to write |{\PitonStyle{Keyword}{function}}| and we
+% will have the word {\PitonStyle{Keyword}{function}} formatted as a keyword.
 %
+% \smallskip
+% The syntax |{\PitonStyle{|\textsl{\texttt{style}}|}{...}}| is mandatory in
+% order to be able to deal both with the semi-global commands and the commands
+% with arguments which may be present in the definition of the style
+% \texttt{\textsl{style}}. 
+%
 % \begin{table}[b]
 % \centering
 % \caption{Usage of the different styles}
@@ -521,7 +542,8 @@
 % 
 % \bigskip
 % If one wishes to format Python code in a box of \pkg{tcolorbox}, it's possible
-% to define an environment |{Python}| with the following code: 
+% to define an environment |{Python}| with the following code (of course, the
+% package \pkg{tcolorbox} must be loaded).
 %
 %\begin{verbatim}
 % \NewPitonEnvironment{Python}{}
@@ -553,6 +575,129 @@
 %
 % \section{Advanced features}
 %
+% \subsection{Highlighting some identifiers}
+%
+% \colorbox{yellow!50}{\textbf{New 1.4}} It's possible to require a changement
+% of formating for some identifiers with the key |identifiers| of
+% |\PitonOptions|.
+%
+% \smallskip
+% That key takes in as argument a value of the following format:
+%
+% \quad |{ names = |\textsl{\ttfamily names}|, style = |\textsl{\ttfamily
+% instructions}| }|
+%
+% \begin{itemize}
+% \item \textsl{\ttfamily names} is a (comma-separated) list of identifiers
+% names; 
+%
+% \item \textsl{\ttfamily instructions} is a list of LaTeX instructions of the
+% same type that \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 names is
+% in the list |\textsl{\ttfamily names}|.
+% 
+% \begin{Verbatim}
+% \PitonOptions 
+%   {
+%     ~emphase#identifiers@ = 
+%      {
+%        ~emphase#names@ = { l1 , l2 } , 
+%        ~emphase#style@ = \color{red} 
+%      }
+%   }
+%
+% \begin{Piton}
+% def tri(l):
+%     """Segmentation sort"""
+%     if len(l) <= 1:
+%         return l
+%     else:
+%         a = l[0]
+%         l1 = [ x for x in l[1:] if x < a  ]
+%         l2 = [ x for x in l[1:] if x >= a ]
+%         return tri(l1) + [a] + tri(l2)
+% \end{Piton}
+% \end{Verbatim}
+%
+%
+% \bigskip
+%
+% \begingroup
+%
+% \PitonOptions 
+%   {
+%     identifiers = 
+%      {
+%        names = { l1 , l2 } , 
+%        style = \color{red} 
+%      }
+%   }
+%
+% \begin{Piton}
+% def tri(l):
+%     """Segmentation sort"""
+%     if len(l) <= 1:
+%         return l
+%     else:
+%         a = l[0]
+%         l1 = [ x for x in l[1:] if x < a  ]
+%         l2 = [ x for x in l[1:] if x >= a ]
+%         return tri(l1) + [a] + tri(l2)
+% \end{Piton}
+%
+% \endgroup
+% 
+% \bigskip
+% By using the key |identifier|, it's possible to add other built-in functions
+% (or other new keywords, etc.) that will be detected by \pkg{piton}.
+%
+%
+% \begin{Verbatim}
+% \PitonOptions 
+%   {
+%     ~emphase#identifiers@ = 
+%      {
+%        names = { cos, sin, tan, floor, ceil, trunc, pow, exp, ln, factorial } , 
+%        style = \PitonStyle{Name.Builtin}
+%      }
+%   }
+%
+% \begin{Piton}
+% from math import *
+% cos(pi/2) 
+% factorial(5)
+% ceil(-2.3) 
+% floor(5.4) 
+% \end{Piton}
+% \end{Verbatim}
+%
+% \begingroup
+%
+% \PitonOptions 
+%   {
+%     identifiers = 
+%      {
+%        names = { cos, sin, tan, floor, ceil, trunc, pow, exp, ln, factorial } , 
+%        style = \PitonStyle{Name.Builtin}
+%      }
+%   }
+%
+% \begin{Piton}
+% from math import *
+% cos(pi/2) 
+% factorial(5)
+% ceil(-2.3) 
+% floor(5.4) 
+% \end{Piton}
+%
+%
+% \endgroup
+%
+%
 % \subsection{Mechanisms to escape to LaTeX}
 %
 % The package \pkg{piton} provides several mechanisms for escaping to LaTeX:
@@ -608,15 +753,14 @@
 % \end{itemize}
 %
 % \bigskip
-% \colorbox{yellow!50}{\textbf{New 1.3}}\enskip 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 possible to refer to a number of
-% line with the command |\label| used in a LaTeX comment.\footnote{That feature
-% is implemented by using a redefinition of the standard command
-% \texttt{\textbackslash label} in the environments \texttt{\{Piton\}}.
-% Therefore, incompatibilities may occur with extensions which redefine
-% (globally) that command \texttt{\textbackslash label} (for example: \pkg{varioref},
-% \pkg{refcheck}, \pkg{showlabels}, etc.)}
+% 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
+% possible to refer to a number of line with the command |\label| used in a
+% LaTeX comment.\footnote{That feature is implemented by using a redefinition of
+% the standard command \texttt{\textbackslash label} in the environments
+% \texttt{\{Piton\}}. Therefore, incompatibilities may occur with extensions
+% which redefine (globally) that command \texttt{\textbackslash label} (for
+% example: \pkg{varioref}, \pkg{refcheck}, \pkg{showlabels}, etc.)}
 %
 % \subsubsection{The key ``math-comments''}
 %
@@ -666,7 +810,8 @@
 % \medskip
 % In the following code, which is a recursive programmation of the mathematical
 % factorial, we decide to highlight in yellow the instruction which contains the
-% recursive call. 
+% recursive call. That example uses the command |\highLight| of \pkg{lua-ul}
+% (that package requires itself the package \pkg{luacolor}).
 % \begin{Verbatim}
 % \begin{Piton}
 % def fact(n):
@@ -673,7 +818,7 @@
 %     if n==0:
 %         return 1
 %     else:
-%         ~emphase#$\colorbox{yellow!50}{$@return n*fact(n-1)~emphase#$}$@
+%         ~emphase#$\highLight{$@return n*fact(n-1)~emphase#$}$@
 % \end{Piton}
 % \end{Verbatim}
 %
@@ -682,11 +827,50 @@
 %     if n==0:
 %         return 1
 %     else:
-%         $\colorbox{yellow!50}{$return n*fact(n-1)$}$
+%         $\highLight{$return n*fact(n-1)$}$
 %    \end{Piton}
 %         
 % \bigskip
+% In fact, in that case, it's probably easier to use the command |\@highLight|
+% of \pkg{lua-ul}: that command sets a yellow background until the end of the
+% current TeX group. Since the name of that command contains the character |@|,
+% it's necessary to define a synonym without |@| in order to be able to use it
+% directly in |{Piton}|.
+% \begingroup
+% \fvset{commandchars=\~\#\+,formatcom=\color{gray}}
+% \begin{Verbatim}
+% \makeatletter
+% ~emphase#\let\Yellow\@highLight+
+% \makeatother
+% \end{Verbatim}
+% \endgroup
 %
+% \begin{Verbatim}
+% \begin{Piton}
+% def fact(n):
+%     if n==0:
+%         return 1
+%     else:
+%         ~emphase#$\Yellow$@return n*fact(n-1)
+% \end{Piton}
+% \end{Verbatim}
+%
+% \makeatletter
+% \let\Yellow\@highLight
+% \makeatother
+%
+%
+% \begin{Piton}
+% def fact(n):
+%     if n==0:
+%         return 1
+%     else:
+%         $\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
@@ -752,7 +936,8 @@
 % the characters \texttt{"} and not \texttt{'''} nor \texttt{"""}. In Python,
 % the short strings can't extend on several lines.} of Python are not considered.
 % \item The must be \textbf{no carriage return} in the mandatory arguments of the
-% command (if there is, a fatal error will be raised).
+% command (if there is, a fatal error will be raised). For multi-lines elements,
+% one should consider the corresponding environments (see below).
 % \end{itemize}
 % 
 % \medskip
@@ -786,13 +971,16 @@
 % In the previous example, the braces in the Python strings |"{"| and |"}"| are
 % correctly interpreted (without any escape character).
 % 
+% 
+%
+%
 % \bigskip
 % \subsubsection{Environments of Beamer allowed in \{Piton\} and \textbackslash PitonInputFile}
 %
 % When \pkg{piton} is used in the class \pkg{beamer}, the following environments
 % of Beamer are directly detected in the environments |{Piton}| (and in the
-% listings processed by |\PitonInputFile|): |{uncoverenv}|, |{onlyenv}|,
-% |{visibleenv}| and |{invisibleenv}|.
+% listings processed by |\PitonInputFile|): |{actionenv}|, |{alertenv}|,
+% |{invisibleenv}|, |{onlyenv}|, |{uncoverenv}| and |{visibleenv}|.
 %
 % However, there is a restriction: these environments must contain only \emph{whole
 % lines of Python code} in their body.
@@ -817,6 +1005,45 @@
 % \end{Verbatim}
 %
 %
+% \vspace{1cm}
+% \textbf{Remark concerning the command \textbackslash alert and the environment
+% \{alertenv\} of Beamer}\par\nobreak
+%
+% \smallskip
+% Beamer provides an easy way to change the color used by the environment
+% |{alertenv}| (and by the command |\alert| which relies upon it) to highlight
+% its argument. Here is an example:
+%
+% \begin{Verbatim}
+% \setbeamercolor{~emphase#alerted text@}{fg=blue} 
+% \end{Verbatim}
+%
+% However, when used inside an environment |{Piton}|, such tuning will probably
+% not be the best choice because \pkg{piton} will, by design, change (most of
+% the time) the color the different elements of text. One may prefer an environment
+% |{alertenv}| that will change the background color for the elements to be
+% hightlighted. 
+%
+% \smallskip
+% Here is a code that will do that job and add a yellow background. That code
+% uses the command |\@highLight| of \pkg{lua-ul} (that extension requires also
+% the package \pkg{luacolor}).
+%
+% \begingroup
+% \fvset{commandchars=\~\#\+,formatcom=\color{gray}}
+% \begin{Verbatim}
+% \setbeamercolor{alerted text}{bg=yellow!50}
+% \makeatletter
+% \AddToHook{env/Piton/begin}
+%   {\renewenvironment<>{alertenv}{\only~#1{~emphase#\@highLight+[alerted text.bg]}}{}}
+% \makeatother
+% \end{Verbatim}
+% \endgroup
+%
+% That code redefines locally the environment |{alertenv}| within the
+% environments |{Piton}| (we recall that the command |\alert| relies upon that
+% environment |{alertenv}|).
+%
 % \subsection{Page breaks and line breaks}
 %
 % \label{breakable}
@@ -862,10 +1089,6 @@
 % \item The key |break-lines| is a conjonction of the two previous keys.
 % \end{itemize}
 % 
-% \medskip
-% \colorbox{yellow!50}{\textbf{Nouveau 1.2}}\enskip Depuis la version 1.2, la
-% clé |break-lines| autorise les coupures de lignes dans |\piton{...}| et pas
-% seulement dans |{Piton}|. 
 
 % \bigskip 
 % The package \pkg{piton} provides also several keys to control the appearance
@@ -889,8 +1112,8 @@
 %
 %
 % \bigskip
-% The following code has been composed in a |{minipage}| of width 12~cm with the
-% following tuning:
+% The following code has been composed in a standard LaTeX |{minipage}| of width
+% 12~cm with the following tuning:
 %
 % \begin{Verbatim}
 % \PitonOptions{break-lines,indent-broken-lines,background-color=gray!15}
@@ -1255,6 +1478,8 @@
 % \url{https://dejavu-fonts.github.io}} specified by the command |\setmonofont| of 
 % \pkg{fontspec}. 
 %
+% That tuning uses the command |\highLight| of \pkg{lua-ul} (that package
+% requires itself the package \pkg{luacolor}).
 %
 % \begin{Verbatim}
 % \setmonofont[Scale=0.85]{DejaVu Sans Mono}
@@ -1267,7 +1492,7 @@
 %     Operator = , 
 %     Operator.Word = \bfseries ,
 %     Name.Builtin = ,
-%     Name.Function = \bfseries \colorbox{gray!20} ,
+%     Name.Function = \bfseries \highLight[gray!20] ,
 %     Comment = \color{gray} ,
 %     Comment.LaTeX = \normalfont \color{gray},
 %     Keyword = \bfseries ,
@@ -1293,7 +1518,7 @@
 %     Operator.Word = \bfseries ,
 %     Operator = , 
 %     Name.Builtin = ,
-%     Name.Function = \bfseries \colorbox{gray!20} ,
+%     Name.Function = \bfseries \highLight[gray!20] ,
 %     Comment = \color{gray} ,
 %     Comment.LaTeX = \normalfont \color{gray} ,
 %     Keyword = \bfseries ,
@@ -1336,12 +1561,13 @@
 %
 % Here is, for example, an environment |{PitonExecute}| which formats a Python
 % listing (with \pkg{piton}) but display also the output of the execution of the
-% code with Python. 
+% code with Python (for technical reasons, the |!| is mandatory in the signature
+% of the environment).
 %
 %
 % \begin{Verbatim}
 % \ExplSyntaxOn
-% \NewDocumentEnvironment { ~emphase#PitonExecute@ } { ! O { } } 
+% \NewDocumentEnvironment { ~emphase#PitonExecute@ } { ! O { } } % the ! is mandatory 
 %   { 
 %     \PyLTVerbatimEnv
 %     \begin{pythonq} 
@@ -1373,7 +1599,7 @@
 %     \end{pythonq}
 %     \directlua
 %       {
-%         tex.print("\\PitonOptions{~#1}")
+%         tex.print("\\PitonOptions{#1}")
 %         tex.print("\\begin{Piton}")
 %         tex.print(pyluatex.get_last_code())
 %         tex.print("\\end{Piton}")
@@ -1400,7 +1626,7 @@
 % listing and to send back to LaTeX as output that code \emph{with interlaced LaTeX
 % instructions of formatting}.
 %
-% In fact, all that job is done by a \textsc{lpeg} called |SyntaxPython|. That
+% In fact, all that job is done by a \textsc{lpeg} called |python|. That
 % \textsc{lpeg}, when matched against the string of a Python listing,
 % returns as capture a Lua table containing data to send to LaTeX. 
 % The only thing to do after will be to apply |tex.tprint| to each element of
@@ -1418,7 +1644,7 @@
 %     return x%2
 % \end{Piton}
 %
-% The capture returned by the \pkg{lpeg} |SyntaxPython| against that code is the
+% The capture returned by the \pkg{lpeg} |python| against that code is the
 % Lua table containing the following elements :
 %
 % \bigskip
@@ -1714,6 +1940,14 @@
 % \bigskip
 % \subsubsection{Parameters and technical definitions}
 %
+% The following string will contain the name of the informatic language
+% considered (the initial value is |python|).
+%
+%    \begin{macrocode}
+\str_new:N \l_@@_language_str
+\str_set:Nn \l_@@_language_str { python }
+%    \end{macrocode}
+% 
 % We will compute (with Lua) the numbers of lines of the Python code and store
 % it in the following counter.
 %    \begin{macrocode}
@@ -1757,7 +1991,7 @@
 % \medskip
 % The following string corresponds to the key |background-color| of |\PitonOptions|.
 %    \begin{macrocode}
-\str_new:N \l_@@_bg_color_tl
+\clist_new:N \l_@@_bg_color_clist
 %    \end{macrocode}
 %
 % \medskip
@@ -1767,7 +2001,7 @@
 % to require a background for these lines of code (and the other lines of code
 % will have the standard background color specified by |background-color|).
 %    \begin{macrocode}
-\str_new:N \l_@@_prompt_bg_color_tl
+\tl_new:N \l_@@_prompt_bg_color_tl
 %    \end{macrocode}
 % 
 % \medskip
@@ -1954,7 +2188,7 @@
 \cs_new_protected:Npn \@@_prompt: 
   { 
     \tl_gset:Nn \g_@@_begin_line_hook_tl
-      { \tl_set:NV \l_@@_bg_color_tl \l_@@_prompt_bg_color_tl } 
+      { \clist_set:NV \l_@@_bg_color_clist \l_@@_prompt_bg_color_tl } 
   }
 %    \end{macrocode}
 % 
@@ -2009,7 +2243,7 @@
     \bool_if:NTF \l_@@_slim_bool
       { \hcoffin_set:Nn \l_tmpa_coffin }
       { 
-        \str_if_empty:NTF \l_@@_bg_color_tl
+        \clist_if_empty:NTF \l_@@_bg_color_clist
           { 
             \vcoffin_set:Nnn \l_tmpa_coffin 
               { \dim_eval:n { \linewidth - \l_@@_left_margin_dim } } 
@@ -2035,7 +2269,7 @@
               { \tl_if_empty:nF { #1 } }
               \@@_print_number:
           }
-        \tl_if_empty:NF \l_@@_bg_color_tl 
+        \clist_if_empty:NF \l_@@_bg_color_clist 
           { \skip_horizontal:n { 0.5 em } }
         \coffin_typeset:Nnnnn \l_tmpa_coffin T l \c_zero_dim \c_zero_dim 
       }  
@@ -2047,7 +2281,7 @@
       { \dim_gset:Nn \g_@@_width_dim { \box_wd:N \l_tmpa_box } }
     \box_set_dp:Nn \l_tmpa_box { \box_dp:N \l_tmpa_box + 1.25 pt } 
     \box_set_ht:Nn \l_tmpa_box { \box_ht:N \l_tmpa_box + 1.25 pt } 
-    \str_if_empty:NTF \l_@@_bg_color_tl
+    \clist_if_empty:NTF \l_@@_bg_color_clist
       { \box_use_drop:N \l_tmpa_box }
       {
         \vbox_top:n 
@@ -2054,7 +2288,7 @@
           { 
             \hbox:n
               { 
-                \@@_color:V \l_@@_bg_color_tl
+                \@@_color:N \l_@@_bg_color_clist
                 \vrule height \box_ht:N \l_tmpa_box 
                        depth \box_dp:N \l_tmpa_box 
                        width \l_@@_width_on_aux_dim
@@ -2071,11 +2305,30 @@
 %    \end{macrocode}
 %
 % \bigskip
-% The following command |\@@_color:n| will accept both |\@@_color:n { red!15 }|
-% and |\@@_color:n { [rgb]{0.9,0.9,0}}|.
+% The command |\@@_color:N| will take in as argument a reference to a
+% comma-separated list of colors. A color will be picked by using the value of
+% |\g_@@_line_int| (modulo the number of colors in the list).
 %    \begin{macrocode}
-\cs_set_protected:Npn \@@_color:n #1
+\cs_set_protected:Npn \@@_color:N #1 
   {
+    \int_set:Nn \l_tmpa_int { \clist_count:N #1 }
+    \int_set:Nn \l_tmpb_int { \int_mod:nn \g_@@_line_int \l_tmpa_int + 1 }
+    \tl_set:Nx \l_tmpa_tl { \clist_item:Nn #1 \l_tmpb_int }
+    \tl_if_eq:NnTF \l_tmpa_tl { none }
+%    \end{macrocode}
+% By setting |\l_@@_width_on_aux_dim| to zero, the colored rectangle will be
+% drawn with zero width and, thus, it will be a mere strut (and we need that strut).
+%    \begin{macrocode}
+      { \dim_zero:N \l_@@_width_on_aux_dim }
+      { \exp_args:NV \@@_color_i:n \l_tmpa_tl }
+  }
+%    \end{macrocode}
+%
+% The following command |\@@_color:n| will accept both the instruction
+% |\@@_color:n { red!15 }| and the instruction |\@@_color:n { [rgb]{0.9,0.9,0} }|.
+%    \begin{macrocode}
+\cs_set_protected:Npn \@@_color_i:n #1
+  {
     \tl_if_head_eq_meaning:nNTF { #1 } [ 
       { 
         \tl_set:Nn \l_tmpa_tl { #1 }
@@ -2121,7 +2374,7 @@
               \l_@@_continuation_symbol_tl 
             } 
             \skip_horizontal:n { 0.3 em }  
-            \tl_if_empty:NF \l_@@_bg_color_tl 
+            \clist_if_empty:NF \l_@@_bg_color_clist 
               { \skip_horizontal:n { 0.5 em } }
           }  
         \bool_if:NT \l_@@_indent_broken_lines_bool
@@ -2161,6 +2414,8 @@
 %    \begin{macrocode}
 \keys_define:nn { PitonOptions }
   {
+    language         .str_set:N         = \l_@@_language_str ,
+    language         .value_required:n  = true ,
     gobble           .int_set:N         = \l_@@_gobble_int , 
     gobble           .value_required:n  = true ,
     auto-gobble      .code:n            = \int_set:Nn \l_@@_gobble_int { -1 } , 
@@ -2179,10 +2434,10 @@
     resume           .value_forbidden:n = true ,
     splittable       .int_set:N         = \l_@@_splittable_int ,
     splittable       .default:n         = 1 , 
-    background-color .str_set:N         = \l_@@_bg_color_tl ,
+    background-color .clist_set:N       = \l_@@_bg_color_clist ,
     background-color .value_required:n  = true ,
-    prompt-background-color .str_set:N         = \l_@@_prompt_bg_color_tl ,
-    prompt-background-color .value_required:n  = true ,
+    prompt-background-color .tl_set:N         = \l_@@_prompt_bg_color_tl ,
+    prompt-background-color .value_required:n = true ,
     slim             .bool_set:N        = \l_@@_slim_bool ,
     slim             .default:n         = true ,
     left-margin      .code:n =
@@ -2279,7 +2534,7 @@
   {
     \bool_if:NT \l_@@_slim_bool
       {
-        \tl_if_empty:NF \l_@@_bg_color_tl
+        \clist_if_empty:NF \l_@@_bg_color_clist
           {
             \tl_gput_right:Nx \g_@@_aux_tl
               {
@@ -2319,7 +2574,11 @@
     \cs_set_protected:Npn \@@_begin_line: { }
     \cs_set_protected:Npn \@@_end_line: { }
     \tl_set:Nx \l_tmpa_tl 
-      { \lua_now:n { piton.ParseBis(token.scan_string()) } { #1 } }
+      { 
+        \lua_now:e 
+          { piton.ParseBis('\l_@@_language_str',token.scan_string()) }
+          { #1 } 
+      }
     \bool_if:NTF \l_@@_show_spaces_bool
       { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
 %    \end{macrocode}
@@ -2345,7 +2604,11 @@
     \cs_set_protected:Npn \@@_begin_line: { }
     \cs_set_protected:Npn \@@_end_line: { }
     \tl_set:Nx \l_tmpa_tl 
-      { \lua_now:n { piton.Parse(token.scan_string()) } { #1 } }
+      { 
+        \lua_now:e 
+          { piton.Parse('\l_@@_language_str',token.scan_string()) } 
+          { #1 } 
+      }
     \bool_if:NT \l_@@_show_spaces_bool
       { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
     \l_tmpa_tl 
@@ -2373,11 +2636,19 @@
       \l_@@_break_lines_in_Piton_bool
       {
         \tl_set:Nx \l_tmpa_tl 
-          { \lua_now:n { piton.ParseTer(token.scan_string()) } { #1 } }
+          { 
+            \lua_now:e 
+              { piton.ParseTer('\l_@@_language_str',token.scan_string()) } 
+              { #1 } 
+          }
       }
       {
         \tl_set:Nx \l_tmpa_tl 
-          { \lua_now:n { piton.Parse(token.scan_string()) } { #1 } }
+          { 
+            \lua_now:e 
+              { piton.Parse('\l_@@_language_str',token.scan_string()) }
+              { #1 } 
+          }
       }
     \bool_if:NT \l_@@_show_spaces_bool
       { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
@@ -2402,11 +2673,19 @@
       \l_@@_break_lines_in_Piton_bool
       {
         \tl_set:Nx \l_tmpa_tl 
-          { \lua_now:n { piton.ParseTer(token.scan_string()) } { #1 } }
+          { 
+            \lua_now:e 
+              { piton.ParseTer('\l_@@_language_str',token.scan_string()) } 
+              { #1 }
+          } 
       }
       {
         \tl_set:Nx \l_tmpa_tl 
-          { \lua_now:n { piton.Parse(token.scan_string()) } { #1 } }
+          { 
+            \lua_now:e 
+              { piton.Parse('\l_@@_language_str',token.scan_string()) }
+              { #1 } 
+          }
       }
     \bool_if:NT \l_@@_show_spaces_bool
       { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
@@ -2505,7 +2784,7 @@
       \vtop \bgroup 
       \lua_now:e
         { 
-          piton.ParseFile(token.scan_argument() ,
+          piton.ParseFile('\l_@@_language_str',token.scan_argument() ,
            \int_use:N \l_@@_first_line_int , 
            \int_use:N \l_@@_last_line_int ) 
         } 
@@ -2587,7 +2866,11 @@
             \lua_now:e 
               { 
                 piton.GobbleParse
-                  ( \int_use:N \l_@@_gobble_int , token.scan_argument() ) 
+                  ( 
+                    '\l_@@_language_str' , 
+                    \int_use:N \l_@@_gobble_int , 
+                    token.scan_argument() 
+                  ) 
               } 
               { ##1 }
             \vspace { 2.5 pt } 
@@ -2718,6 +3001,8 @@
     Name.Class       .value_required:n = true ,
     Name.Builtin     .tl_set:c = pitonStyle Name.Builtin , 
     Name.Builtin     .value_required:n = true ,
+    TypeParameter    .tl_set:c = pitonStyle TypeParameter , 
+    TypeParameter    .value_required:n = true ,
     Name.Type        .tl_set:c = pitonStyle Name.Type , 
     Name.Type        .value_required:n = true ,
     Operator         .tl_set:c = pitonStyle Operator , 
@@ -2724,14 +3009,18 @@
     Operator         .value_required:n = true ,
     Operator.Word    .tl_set:c = pitonStyle Operator.Word , 
     Operator.Word    .value_required:n = true ,
-    Post.Function    .tl_set:c = pitonStyle Post.Function , 
-    Post.Function    .value_required:n = true ,
     Exception        .tl_set:c = pitonStyle Exception ,
     Exception        .value_required:n = true ,
     Comment.LaTeX    .tl_set:c = pitonStyle Comment.LaTeX ,
     Comment.LaTeX    .value_required:n = true ,
-    Beamer           .tl_set:c = pitonStyle Beamer ,
-    Beamer           .value_required:n = true ,
+    Identifier       .tl_set:c = pitonStyle Identifier ,
+    Comment.LaTeX    .value_required:n = true ,
+    ParseAgain.noCR  .tl_set:c = pitonStyle ParseAgain.noCR ,
+    ParseAgain.noCR  .value_required:n = true ,
+    ParseAgain       .tl_set:c = pitonStyle ParseAgain , 
+    ParseAgain       .value_required:n = true ,
+    Prompt           .tl_set:c = pitonStyle Prompt , 
+    Prompt           .value_required:n = true ,
     unknown          .code:n = 
       \msg_error:nn { piton } { Unknown~key~for~SetPitonStyle }
   }
@@ -2749,6 +3038,7 @@
     Comment.LaTeX,~
     Dict.Value,~
     Exception,~
+    Identifier,~
     InitialValues,~ 
     Keyword,~
     Keyword.Constant,~
@@ -2760,6 +3050,7 @@
     Number,~
     Operator,~
     Operator.Word,~
+    Prompt,~
     String,~
     String.Doc,~
     String.Long,~
@@ -2797,12 +3088,16 @@
     InitialValues    = \@@_piton:n ,
     Dict.Value       = \@@_piton:n ,
     Interpol.Inside  = \color{black}\@@_piton:n ,
-    Beamer           = \@@_piton_no_cr:n , 
-    Post.Function    = \@@_piton:n ,
+    TypeParameter    = \color[HTML]{008800} \itshape ,
+    Identifier       = \@@_identifier:n , 
+    Prompt           = , 
+    ParseAgain.noCR  = \@@_piton_no_cr:n , 
+    ParseAgain       = \@@_piton:n ,
   }
 %    \end{macrocode}
-% The last styles |Beamer| and |Post.Function| should be considered as 
-% ``internal style'' (not available for the final user).
+% The last styles |ParseAgain.noCR| and |ParseAgain| should be considered as 
+% ``internal style'' (not available for the final user). However, maybe we will
+% change that and document these styles for the final user (why not?).
 %
 % \medskip
 % If the key |math-comments| has been used at load-time, we change the style
@@ -2810,11 +3105,49 @@
 % 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 \c_@@_math_comments_bool { \SetPitonStyle { Comment.Math } }
 %    \end{macrocode}
 % 
 % \bigskip
+% \subsubsection{Highlighting some identifiers}
+% 
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_identifier:n #1
+  { \cs_if_exist_use:c { PitonIdentifier #1 } { #1 } }
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+\keys_define:nn { PitonOptions }
+  { identifiers .code:n = \@@_set_identifiers:n { #1 } }
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+\keys_define:nn { Piton / identifiers }
+  {
+    names .clist_set:N = \l_@@_identifiers_names_tl ,
+    style .tl_set:N    = \l_@@_style_tl ,
+  }
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_set_identifiers:n #1
+  {
+    \clist_clear_new:N \l_@@_identifiers_names_tl 
+    \tl_clear_new:N \l_@@_style_tl 
+    \keys_set:nn { Piton / identifiers } { #1 }
+    \clist_map_inline:Nn \l_@@_identifiers_names_tl 
+      {
+        \tl_set_eq:cN 
+          { PitonIdentifier ##1 }
+          \l_@@_style_tl
+      }
+  }
+%    \end{macrocode}
+% 
+% \bigskip
 % \subsubsection{Security}
 %
 %     \begin{macrocode}
@@ -2854,7 +3187,9 @@
     end-of-broken-line,~
     env-gobble,~
     gobble,~
+    identifiers,~
     indent-broken-lines,~
+    language,~
     left-margin,~
     line-numbers,~
     prompt-background-color,~
@@ -2914,7 +3249,7 @@
 % 
 %
 % \bigskip
-% The Lua code will be loaded via a |{luacode*}| environment. Thei environment
+% The Lua code will be loaded via a |{luacode*}| environment. The environment
 % is by itself a Lua block and the local declarations will be local to that
 % block. All the global functions (used by the L3 parts of the implementation)
 % will be put in a Lua table |piton|.
@@ -2929,18 +3264,17 @@
 if piton.comment_latex == nil then piton.comment_latex = ">" end 
 piton.comment_latex = "#" .. piton.comment_latex 
 %    \end{macrocode}
-% 
-% 
+%
 % \bigskip
 % \subsubsection{Special functions dealing with LPEG}
 %
-% 
 % \medskip
 % We will use the Lua library \pkg{lpeg} which is built in LuaTeX. That's why we
 % define first aliases for several functions of that library.
 %    \begin{macrocode}
 local P, S, V, C, Ct, Cc = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc
-local Cf, Cs = lpeg.Cf, lpeg.Cs
+local Cf, Cs , Cg , Cmt , Cb = lpeg.Cf, lpeg.Cs, lpeg.Cg , lpeg.Cmt , lpeg.Cb
+local R = lpeg.R
 %    \end{macrocode}
 % 
 %
@@ -3034,13 +3368,6 @@
 %    \end{macrocode}
 %
 % \bigskip
-% \subsubsection{The LPEG SyntaxPython}
-%
-% 
-% \bigskip
-% 
-%
-% \bigskip
 % \paragraph{The basic syntactic LPEG}
 %
 %    \begin{macrocode}
@@ -3072,7 +3399,7 @@
 % On the other hand, the \textsc{lpeg} |Identifier| (with a capital) also returns
 % a \emph{capture}.
 %    \begin{macrocode}
-local Identifier = K ( identifier )
+local Identifier = K ( identifier , 'Identifier' )
 %    \end{macrocode}
 %
 % \bigskip
@@ -3135,6 +3462,20 @@
 %    \end{macrocode}
 % 
 % \bigskip
+% The following \textsc{lpeg} catches a space (U+0020) and replace it by
+% |\l_@@_space_tl|. It will be used in the strings. Usually,
+% |\l_@@_space_tl| will contain a space and therefore there won't be difference.
+% However, when the key |show-spaces-in-strings| is in force, |\\l_@@_space_tl| will
+% contain ␣ (U+2423) in order to visualize the spaces.
+%    \begin{macrocode}
+local VisualSpace = space * Lc "\\l_@@_space_tl" 
+%    \end{macrocode}
+% 
+%
+% \bigskip
+% \subsubsection{The LPEG python}
+% 
+% \bigskip
 % Some strings of length 2 are explicit because we want the corresponding
 % ligatures available in some fonts such as \emph{Fira Code} to be active.
 %    \begin{macrocode}
@@ -3173,7 +3514,7 @@
   'Name.Builtin' )
 
 local Exception =
-  K ( "ArithmeticError" + P "AssertionError" + P "AttributeError"
+  K ( 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"
@@ -3292,7 +3633,7 @@
 %
 % 
 % \bigskip
-% First, we define \textsc{lpeg} for the interpolations in the f-strings. Here
+% We have also to deal with the interpolations in the f-strings. Here
 % is an example of a f-string with an interpolation and a format
 % instruction\footnote{There is no special \pkg{piton} style for the formatting
 % instruction (after the colon): the style which will be applied will be the
@@ -3301,68 +3642,8 @@
 %
 % \piton{f'Total price: {total+1:.2f} €'}
 %
-% \medskip
-% The following \textsc{lpeg} |SingleShortInterpol| (and the three variants)
-% will catch the whole interpolation, included the braces, that is to say, in
-% the previous example:\enskip |{total+1:.2f}|
-% 
-% \medskip
-%   \begin{macrocode}
-local SingleShortInterpol =
-    K ( P "{" , 'String.Interpol')
-  * K ( ( 1 - S "}':" ) ^ 0 , 'Interpol.Inside' )
-  * K ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1
-  * K ( P "}" , 'String.Interpol' )
-
-local DoubleShortInterpol =
-    K ( P "{" , 'String.Interpol' )
-  * K ( ( 1 - S "}\":" ) ^ 0 , 'Interpol.Inside' )
-  * ( K ( P ":" , 'String.Interpol' ) * K ( (1 - S "}:\"") ^ 0 ) ) ^ -1
-  * K ( P "}" , 'String.Interpol' )
-
-local SingleLongInterpol =
-    K ( P "{" , 'String.Interpol' )
-  * K ( ( 1 - S "}:\r" - P "'''" ) ^ 0 , 'Interpol.Inside' )
-  * K ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1
-  * K ( P "}" , 'String.Interpol' )
-
-local DoubleLongInterpol =
-    K ( P "{" , 'String.Interpol' )
-  * K ( ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 , 'Interpol.Inside' )
-  * K ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1
-  * K ( P "}" , 'String.Interpol' )
-%    \end{macrocode}
 %
-% 
 % \bigskip
-% The following \textsc{lpeg} catches a space (U+0020) and replace it by
-% |\l_@@_space_tl|. It will be used in the short strings. Usually,
-% |\l_@@_space_tl| will contain a space and therefore there won't be difference.
-% However, when the key |show-spaces-in-strings| is in force, |\\l_@@_space_tl| will
-% contain ␣ (U+2423) in order to visualize the spaces.
-%    \begin{macrocode}
-local VisualSpace = space * Lc "\\l_@@_space_tl" 
-%    \end{macrocode}
-%
-% \bigskip
-% Now, we define \textsc{lpeg} for the parts of the strings which are \emph{not}
-% in the interpolations.
-%
-%    \begin{macrocode}
-local SingleShortPureString = 
-  ( VisualSpace + K ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 ) ) ^ 1 
-
-local DoubleShortPureString = 
-  ( VisualSpace + K ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 ) ) ^ 1
-
-local SingleLongPureString = 
-  K ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 )
-
-local DoubleLongPureString = 
-  K ( ( 1 - P "\"\"\"" - S " {}\"\r" ) ^ 1 )
-%    \end{macrocode}
-%
-% \bigskip
 % The interpolations beginning by |%| (even though there is more modern
 % technics now in Python).
 %    \begin{macrocode}
@@ -3393,7 +3674,16 @@
 % First, we deal with the f-strings of Python, which are prefixed by |f| or |F|.
 %    \begin{macrocode}
          K ( P "f'" + P "F'" ) 
-         * ( SingleShortInterpol + SingleShortPureString ) ^ 0 
+         * ( 
+             K ( P "{" , 'String.Interpol')
+              * K ( ( 1 - S "}':" ) ^ 0 , 'Interpol.Inside' )
+              * K ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1
+              * K ( P "}" , 'String.Interpol' )
+             + 
+             VisualSpace 
+             + 
+             K ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 )
+           ) ^ 0 
          * K ( P "'" )
        + 
 %    \end{macrocode}
@@ -3413,7 +3703,16 @@
   Lc ( "{\\PitonStyle{String.Short}{" )
    * (
          K ( P "f\"" + P "F\"" ) 
-         * ( DoubleShortInterpol + DoubleShortPureString ) ^ 0 
+         * ( 
+             K ( P "{" , 'String.Interpol' )
+               * K ( ( 1 - S "}\":" ) ^ 0 , 'Interpol.Inside' )
+               * ( K ( P ":" , 'String.Interpol' ) * K ( (1 - S "}:\"") ^ 0 ) ) ^ -1
+               * K ( P "}" , 'String.Interpol' )
+             + 
+             VisualSpace 
+             + 
+             K ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 ) 
+            ) ^ 0
          * K ( P "\"" )
        +
          K ( P "\"" + P "r\"" + P "R\"" ) 
@@ -3440,11 +3739,13 @@
 %    \begin{macrocode}
 local BalancedBraces =
   P { "E" ,
-       E = ( ShortString + ( 1 - S "{}" ) ) ^ 0
-           *  
-           ( 
-              P "{" * V "E" * P "}" 
-              * ( ShortString + ( 1 - S "{}" ) ) ^ 0 
+       E = 
+           (
+             P "{" * V "E" * P "}" 
+             + 
+             ShortString  
+             + 
+             ( 1 - S "{}" ) 
            ) ^ 0 
     }
 %    \end{macrocode}
@@ -3458,6 +3759,7 @@
 local BeamerEndEnvironments = P ( true ) 
 local BeamerNamesEnvironments =
   P "uncoverenv" + P "onlyenv" + P "visibleenv" + P "invisibleenv" 
+  + P "alertenv" + P "actionenv"
 
 %    \end{macrocode}
 % 
@@ -3483,7 +3785,7 @@
       ) 
       *
       L ( ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 * P "{" )
-      * K ( BalancedBraces , 'Beamer' ) 
+      * K ( BalancedBraces , 'ParseAgain.noCR' ) 
       * L ( P "}" )
     +  
       L ( 
@@ -3494,9 +3796,9 @@
           * P "<" * (1 - P ">") ^ 0 * P ">" 
           * P "{" 
         )
-      * K ( BalancedBraces , 'Beamer' ) 
+      * K ( BalancedBraces , 'ParseAgain.noCR' ) 
       * L ( P "}{" )
-      * K ( BalancedBraces , 'Beamer' ) 
+      * K ( BalancedBraces , 'ParseAgain.noCR' ) 
       * L ( P "}" )
     +  
       L ( 
@@ -3507,11 +3809,11 @@
           * P "<" * (1 - P ">") ^ 0 * P ">" 
           * P "{" 
         )
-      * K ( BalancedBraces , 'Beamer' ) 
+      * K ( BalancedBraces , 'ParseAgain.noCR' ) 
       * L ( P "}{" )
-      * K ( BalancedBraces , 'Beamer' ) 
+      * K ( BalancedBraces , 'ParseAgain.noCR' ) 
       * L ( P "}{" )
-      * K ( BalancedBraces , 'Beamer' ) 
+      * K ( BalancedBraces , 'ParseAgain.noCR' ) 
       * L ( P "}" )
 %    \end{macrocode}
 % Now for the environemnts.
@@ -3538,15 +3840,18 @@
 %
 % \bigskip
 % The following LPEG will detect the Python prompts when the user is typesetting
-% an interactive session of Python (directly or throught |{pyconsole}| of
+% an interactive session of Python (directly or through |{pyconsole}| of
 % \pkg{pyluatex}). 
 %    \begin{macrocode}
-local Prompt = ( # ( P ">>>" + P "..." )  * Lc ( '\\@@_prompt:' ) ) ^ -1 
+local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\@@_prompt:' ) ) ^ -1 
 %    \end{macrocode}
 % We remind that the marker |#| of LPEG specifies that the pattern will be
 % detected but won't consume any character.
 %
-%
+%    \begin{macrocode}
+local Prompt = K ( ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1 , 'Prompt' ) 
+%    \end{macrocode}
+%    
 % \bigskip
 % The following \textsc{lpeg} |EOL| is for the end of lines.
 %    \begin{macrocode}
@@ -3569,8 +3874,9 @@
     Lc ( '\\@@_end_line:' ) 
     * BeamerEndEnvironments 
     * BeamerBeginEnvironments 
+    * PromptHastyDetection
+    * Lc ( '\\@@_newline: \\@@_begin_line:' )
     * Prompt
-    * Lc ( '\\@@_newline: \\@@_begin_line:' )
   ) 
   *
   SpaceIndentation ^ 0
@@ -3589,8 +3895,9 @@
 % delimit the argument of the command \texttt{\textbackslash @@\_begin\_line:}}.
 %    \begin{macrocode}
     Lc ( '\\@@_end_line:' )  
-    * Prompt
+    * PromptHastyDetection
     * Lc ( '\\@@_newline: \\@@_begin_line:' )
+    * Prompt 
   ) 
   *
   SpaceIndentation ^ 0
@@ -3597,44 +3904,43 @@
 end 
 %    \end{macrocode}
 %
+% \bigskip
+%    \begin{macrocode}
+function EOL_for_style ( s ) 
+   return Lc "}}" * EOL * Lc ( "{\\PitonStyle{" .. s .. "}{" ) 
+end 
+%    \end{macrocode}
 % 
 % \bigskip
 % \paragraph{The long strings}
 % 
 % 
-% \bigskip
-% Of course, it's more complicated for ``longs strings'' because, by definition,
-% in Python, those strings may be broken by an end on line (which is catched by
-% the \textsc{lpeg} |EOL|).
 %    \begin{macrocode}
 local SingleLongString =
   Lc "{\\PitonStyle{String.Long}{" 
    * (
          K ( S "fF" * P "'''" )
-         * ( SingleLongInterpol + SingleLongPureString ) ^ 0
-         * Lc "}}" 
          * (
-             EOL
+             K ( P "{" , 'String.Interpol' )
+               * K ( ( 1 - S "}:\r" - P "'''" ) ^ 0 , 'Interpol.Inside' )
+               * K ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1
+               * K ( P "}" , 'String.Interpol' )
              + 
-             Lc "{\\PitonStyle{String.Long}{" 
-             * ( SingleLongInterpol + SingleLongPureString ) ^ 0
-             * Lc "}}"
-             * EOL
+             K ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 )
+             + 
+             EOL_for_style 'String.Long'
            ) ^ 0 
-         * Lc "{\\PitonStyle{String.Long}{" 
-         * ( SingleLongInterpol + SingleLongPureString ) ^ 0
        +
-         K ( ( S "rR" ) ^ -1  * P "'''" 
-             * ( 1 - P "'''" - P "\r" ) ^ 0 ) 
-         * Lc "}}" 
+         K ( ( S "rR" ) ^ -1  * P "'''" )
          * (
-             Lc "{\\PitonStyle{String.Long}{" 
-             * K ( ( 1 - P "'''" - P "\r" ) ^ 0 )  
-             * Lc "}}" 
-             * EOL
+             K ( ( 1 - P "'''" - S "\r%" ) ^ 1 )  
+             + 
+             PercentInterpol
+             +
+             P "%"
+             +
+             EOL_for_style 'String.Long'
            ) ^ 0 
-         * Lc "{\\PitonStyle{String.Long}{" 
-         * K ( ( 1 - P "'''" - P "\r" ) ^ 0 )
       )
    * K ( P "'''" )
    * Lc "}}" 
@@ -3644,30 +3950,27 @@
   Lc "{\\PitonStyle{String.Long}{" 
    * (
          K ( S "fF" * P "\"\"\"" )
-         * ( DoubleLongInterpol + DoubleLongPureString ) ^ 0
-         * Lc "}}" 
          * (
-             EOL
+             K ( P "{" , 'String.Interpol' )
+               * K ( ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 , 'Interpol.Inside' )
+               * K ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1
+               * K ( P "}" , 'String.Interpol' )
              + 
-             Lc "{\\PitonStyle{String.Long}{" 
-             * ( DoubleLongInterpol + DoubleLongPureString ) ^ 0
-             * Lc "}}" 
-             * EOL
+             K ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 ) 
+             + 
+             EOL_for_style 'String.Long'
            ) ^ 0 
-         * Lc "{\\PitonStyle{String.Long}{" 
-         * ( DoubleLongInterpol + DoubleLongPureString ) ^ 0
        +
-         K ( ( S "rR" ) ^ -1  * P "\"\"\""
-              * ( 1 - P "\"\"\"" - P "\r" ) ^ 0 ) 
-         * Lc "}}" 
+         K ( ( S "rR" ) ^ -1  * P "\"\"\"" )
          * (
-             Lc "{\\PitonStyle{String.Long}{" 
-             * K ( ( 1 - P "\"\"\"" - P "\r" ) ^ 0 )
-             * Lc "}}" 
-             * EOL
+             K ( ( 1 - P "\"\"\"" - S "%\r" ) ^ 1 )  
+             + 
+             PercentInterpol 
+             + 
+             P "%"
+             + 
+             EOL_for_style 'String.Long'
            ) ^ 0 
-         * Lc "{\\PitonStyle{String.Long}{" 
-         * K ( ( 1 - P "\"\"\"" - P "\r" ) ^ 0 )
       )
    * K ( P "\"\"\"" )
    * Lc "}}" 
@@ -3794,12 +4097,12 @@
   * SkipSpace
   * ( K ( P "->" ) * SkipSpace * K ( identifier , 'Name.Type' ) ) ^ -1
 %    \end{macrocode}
-% Here, we need a \pkg{piton} style |Post.Function| which will be linked to
+% Here, we need a \pkg{piton} style |ParseAgain| which will be linked to
 % |\@@_piton:n| (that means that the capture will be parsed once again by
 % \pkg{piton}). We could avoid that kind of trick by using a non-terminal of a
 % grammar but we have probably here a better legibility.
 %    \begin{macrocode}
-  * K ( ( 1 - S ":\r" )^0 , 'Post.Function' ) 
+  * K ( ( 1 - S ":\r" )^0 , 'ParseAgain' ) 
   * K ( P ":" )
   * ( SkipSpace
       * ( EOL + CommentLaTeX + Comment ) -- in all cases, that contains an EOL
@@ -3851,8 +4154,6 @@
   * K ( P "}" )
 %    \end{macrocode}
 %
-%
-% \bigskip
 % \paragraph{Miscellaneous}
 % 
 %    \begin{macrocode}
@@ -3885,7 +4186,6 @@
      + ShortString
      + Punct
      + FromImport
-     + ImportAs
      + RaiseException 
      + DefFunction
      + DefClass 
@@ -3906,49 +4206,416 @@
 % will be used as marker in order to delimit the argument of the command
 % \texttt{\textbackslash @@\_begin\_line:}}.
 %    \begin{macrocode}
-local SyntaxPython = P ( true ) 
+local python = P ( true ) 
 
-function piton.defSyntaxPython()
-  SyntaxPython =
-    Ct (
-         ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 
-         * BeamerBeginEnvironments 
-         * Prompt
-         * Lc ( '\\@@_begin_line:' ) 
-         * SpaceIndentation ^ 0 
-         * MainLoop
-         * -1 
-         * Lc ( '\\@@_end_line:' )
-       )
+python =
+  Ct (
+       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 
+       * BeamerBeginEnvironments 
+       * PromptHastyDetection
+       * Lc ( '\\@@_begin_line:' ) 
+       * Prompt 
+       * SpaceIndentation ^ 0 
+       * MainLoop
+       * -1 
+       * Lc ( '\\@@_end_line:' )
+     )
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+local languages = { }
+languages['python'] = python
+%    \end{macrocode}
+%
+% % \bigskip
+% \subsubsection{The LPEG ocaml}
+% 
+%    \begin{macrocode}
+local Punct = K ( S ",:;!" )
+%    \end{macrocode}
+% 
+%    \begin{macrocode}
+local identifier = 
+  ( R "az" + R "AZ" + P "_") * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 
+
+local Identifier = K ( identifier )
+
+local Operator = 
+  K ( P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" 
+      + P "||" + P "&&" + P "//" + P "**" + P ";;" + P "::" + P "->" 
+      + P "+." + P "-." + P "*." + P "/." 
+      + S "-~+/*%=<>&@|" 
+      , 
+      'Operator'
+    )
+
+local OperatorWord = 
+  K ( P "and" + P "asr" + P "land" + P "lor" + P "lsl" + P "lxor" 
+      + P "mod" + P "or" , 
+      'Operator.Word') 
+
+local Keyword = 
+  K ( P "as" + P "assert" + P "begin" + P "class" + P "constraint" + P "done" 
+  + P "do" + P "downto" + P "else" + P "end" + P "exception" + P "external" 
+  + P "false" + P "for" + P "function" + P "fun" + P "functor" + P "if" 
+  + P "in" + P "include" + P "inherit" + P "initializer" + 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 "true" + P "try" + P "type" 
+  + P "value" + P "val" + P "virtual" + P "when" + P "while" + P "with" ,
+  'Keyword' ) 
+  + K ( P "true" + P "false" , 'Keyword.Constant' )  
+
+
+local Builtin = 
+  K (   P "not" + P "incr" + P "decr" + P "fst" + P "snd" 
+      + P "String.length" 
+      + P "List.tl" + P "List.hd" + P "List.mem" + P "List.exists" 
+      + P "List.for_all" + P "List.filter" + P "List.length" + P "List.map" 
+      + P "List.iter" 
+      + P "Array.length" + P "Array.make" + P "Array.make_matrix" 
+      + P "Array.init" + P "Array.copy" + P "Array.copy" + P "Array.mem" 
+      + P "Array.exists" + P "Array.for_all" + P "Array.map" + P "Array.iter" 
+      + P "Queue.create" + P "Queue.is_empty" + P "Queue.push" + P "Queue.pop" 
+      + P "Stack.create" + P "Stack.is_empty" + P "Stack.push" + P "Stack.pop" 
+      + P "Hashtbl.create" + P "Hashtbl.add" + P "Hashtbl.remove" 
+      + P "Hashtbl.mem" + P "Hashtbl.find" + P "Hashtbl.find_opt" 
+      + P "Hashtbl.iter"  
+      , 'Name.Builtin' )
+%    \end{macrocode}
+% 
+% \bigskip
+% The following exceptions are exceptions in the standard library of OCaml (Stdlib).
+%    \begin{macrocode}
+local Exception =
+  K ( 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" ,
+  'Exception' )
+%    \end{macrocode}
+%
+% 
+% \paragraph{The characters in OCaml}
+%
+%    \begin{macrocode}
+local Char = 
+  K ( P "'" * ( ( 1 - P "'" ) ^ 0 + P "\\'" ) * P "'" , 'String.Short' ) 
+%    \end{macrocode}
+% 
+%
+% \bigskip
+% \paragraph{Beamer}
+%
+%    \begin{macrocode}
+local BalancedBraces =
+  P { "E" ,
+       E = 
+           (
+             P "{" * V "E" * P "}" 
+             + 
+             P "\"" * ( 1 - S "\"" ) ^ 0 * P "\""  -- OCaml strings
+             + 
+             ( 1 - S "{}" ) 
+           ) ^ 0 
+    }
+%    \end{macrocode}
+%
+% 
+%    \begin{macrocode}
+if piton_beamer 
+then
+  Beamer =
+      L  ( P "\\pause" * ( P "[" * (1 - P "]") ^ 0 * P "]" ) ^ -1 ) 
+    + 
+      (   P "\\uncover"   * Lc ( '\\@@_beamer_command:n{uncover}' ) 
+        + P "\\only"      * Lc ( '\\@@_beamer_command:n{only}' ) 
+        + P "\\alert"     * Lc ( '\\@@_beamer_command:n{alert}' ) 
+        + P "\\visible"   * Lc ( '\\@@_beamer_command:n{visible}' ) 
+        + P "\\invisible" * Lc ( '\\@@_beamer_command:n{invisible}' ) 
+        + P "\\action"    * Lc ( '\\@@_beamer_command:n{action}' ) 
+      ) 
+      *
+      L ( ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 * P "{" )
+      * K ( BalancedBraces , 'ParseAgain.noCR' ) 
+      * L ( P "}" )
+    +  
+      L ( 
+          ( P "\\alt" )
+          * P "<" * (1 - P ">") ^ 0 * P ">" 
+          * P "{" 
+        )
+      * K ( BalancedBraces , 'ParseAgain.noCR' ) 
+      * L ( P "}{" )
+      * K ( BalancedBraces , 'ParseAgain.noCR' ) 
+      * L ( P "}" )
+    +  
+      L ( 
+          ( P "\\temporal" )
+          * P "<" * (1 - P ">") ^ 0 * P ">" 
+          * P "{" 
+        )
+      * K ( BalancedBraces , 'ParseAgain.noCR' ) 
+      * L ( P "}{" )
+      * K ( BalancedBraces , 'ParseAgain.noCR' ) 
+      * L ( P "}{" )
+      * K ( BalancedBraces , 'ParseAgain.noCR' ) 
+      * L ( P "}" )
+  BeamerBeginEnvironments = 
+      ( space ^ 0 * 
+        L 
+          ( 
+            P "\\begin{" * BeamerNamesEnvironments * "}"
+            * ( P "<" * ( 1 - P ">") ^ 0 * P ">" ) ^ -1
+          )
+        * P "\r" 
+      ) ^ 0 
+  BeamerEndEnvironments = 
+      ( space ^ 0 * 
+        L ( P "\\end{" * BeamerNamesEnvironments * P "}" ) 
+        * P "\r" 
+      ) ^ 0 
 end
+%    \end{macrocode}
+%
+% \bigskip
+% \paragraph{EOL}
+%
+%    \begin{macrocode}
+local EOL
+if piton_beamer 
+then
+EOL = 
+  P "\r" 
+  *
+  (
+    ( space^0 * -1 )
+    + 
+    Lc ( '\\@@_end_line:' ) 
+    * BeamerEndEnvironments 
+    * BeamerBeginEnvironments 
+    * Lc ( '\\@@_newline: \\@@_begin_line:' )
+  ) 
+  *
+  SpaceIndentation ^ 0
+else
+EOL = 
+  P "\r" 
+  *
+  (
+    ( space ^ 0 * -1 )
+    + 
+    Lc ( '\\@@_end_line:' )  
+    * Lc ( '\\@@_newline: \\@@_begin_line:' )
+  ) 
+  *
+  SpaceIndentation ^ 0
+end 
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+function EOL_for_style ( s ) 
+   return Lc "}}" * EOL * Lc ( "{\\PitonStyle{" .. s .. "}{" ) 
+end 
+%    \end{macrocode}
+% 
+% 
+% \paragraph{The strings}
+% 
+%    \begin{macrocode}
+local String =
+  Lc "{\\PitonStyle{String.Long}{" 
+   * K ( P "\"" )
+   * ( 
+       VisualSpace
+       + 
+       K ( ( 1 - S " \"\r" ) ^ 1 ) 
+       +  
+       EOL_for_style 'String.Long' 
+     ) ^ 0 
+   * K ( P "\"" )
+   * Lc "}}" 
+%    \end{macrocode}
+%
+% 
+% \bigskip
+% Now, the ``quoted strings'' of OCaml (for example \verb+{ext|Essai|ext}+). 
+%
+% For those strings, we will do two consecutive analysis. First an analysis to
+% determine the whole string and, then, an analysis for the potential visual
+% spaces and the EOL in the string.
+% 
+% The first analysis require a match-time capture. For explanations about that
+% programmation, see the paragraphe \emph{Lua's long % strings} in
+% |www.inf.puc-rio.br/~roberto/lpeg|. 
+%    \begin{macrocode}
+local ext = ( R "az" + P "_" ) ^ 0
+local open = "{" * Cg(ext, 'init') * "|" 
+local close = "|" * C(ext) * "}"
+local closeeq = 
+  Cmt ( close * Cb('init'), 
+        function (s, i, a, b) return a==b end ) 
+%    \end{macrocode}
+%
+% \medskip
+% The \textsc{lpeg} |QuotedStringBis| will do the second analysis. 
+%    \begin{macrocode}
+local QuotedStringBis = 
+   Lc "{\\PitonStyle{String.Long}{"  
+   *
+     (  
+        VisualSpace
+        +
+        K ( ( 1 - S " \r" ) ^ 1 ) 
+        +  
+        EOL_for_style 'String.Long' 
+     ) ^ 0 
+   * Lc "}}" 
+%    \end{macrocode}
+% 
+% \medskip
+% We use a ``function capture'' (as called in the official documentation of the
+% \textsc{lpeg}) in order to do the second analysis on the result of the first one.
+%    \begin{macrocode}
+local QuotedString = 
+   C ( open * ( 1 - closeeq ) ^ 0  * close ) /
+  ( function (s) return QuotedStringBis : match(s) end ) 
+%    \end{macrocode}
+% 
+%
+% \bigskip
+% \paragraph{The comments in the OCaml listings}
+%
+% In OCaml, the delimiters for the comments are |(*| and |*)|. There
+% unsymmetrical and, therefore, the comments may be nested. That's why we need a
+% grammar.
+% 
+% In these comments, we embed the math comments (between |$| and |$|) and we
+% embed also a treatment for the end of lines (since the comments may be multi-lines).
+% 
+%    \begin{macrocode}
+local Comment =
+  Lc "{\\PitonStyle{Comment}{" 
+  *
+  P {
+      "A" ,
+      A = K "(*"
+          * ( V "A" 
+              + K ( ( 1 - P "(*" - P "*)" - S "\r$" ) ^ 1 ) -- $
+              + P "$" * K ( ( 1 - S "$\r" ) ^ 1 , 'Comment.Math' ) * P "$" -- $
+              + EOL_for_style 'Comment'
+            ) ^ 0 
+          * K "*)" 
+    }
+  *
+  Lc "}}" 
+%    \end{macrocode}
+% 
+% \bigskip
+% \paragraph{The DefFunction}
+%
+%    \begin{macrocode}
+local DefFunction = 
+  ( K ( P "let rec" + P "let" + P "and" , 'Keyword' ) ) 
+  * Space
+  * K ( identifier , 'Name.Function' ) 
+  * Space 
+  * # ( 1 - P "=" ) 
+%    \end{macrocode}
+% 
+% \bigskip
+% \paragraph{The parameters of the types}
+% 
+%    \begin{macrocode}
+local TypeParameter = K ( P "'" * alpha * # ( 1 - P "'") , 'TypeParameter' ) 
+%    \end{macrocode}
+% 
+% \bigskip
+% \paragraph{The main LPEG}
+%
+% First, the main loop :
+%    \begin{macrocode}
+MainLoop = 
+  (  ( space^1 * -1 ) 
+     + EOL
+     + Space 
+     + Tab
+     + Escape 
+     + Beamer 
+     + TypeParameter
+     + String + QuotedString + Char
+     + Comment
+     + Delim
+     + Operator
+     + Punct
+     + FromImport
+     + ImportAs
+     + Exception 
+     + DefFunction
+     + Keyword * ( Space + Punct + Delim + EOL + -1 ) 
+     + OperatorWord * ( Space + Punct + Delim + EOL + -1 ) 
+     + Builtin * ( Space + Punct + Delim + EOL + -1 ) 
+     + Identifier 
+     + Number
+     + Word
+  ) ^ 0 
+%    \end{macrocode}
+%
+% \bigskip
+% We recall that each line in the Python code to parse will be sent back to
+% LaTeX between a pair |\@@_begin_line:| -- |\@@_end_line:|\footnote{Remember
+% that the \texttt{\textbackslash @@\_end\_line:} must be explicit because it
+% will be used as marker in order to delimit the argument of the command
+% \texttt{\textbackslash @@\_begin\_line:}}.
+%    \begin{macrocode}
+local ocaml = P ( true ) 
 
-piton.defSyntaxPython()
+ocaml =
+  Ct (
+       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 
+       * BeamerBeginEnvironments 
+       * Lc ( '\\@@_begin_line:' ) 
+       * SpaceIndentation ^ 0 
+       * MainLoop
+       * -1 
+       * Lc ( '\\@@_end_line:' )
+     )
 %    \end{macrocode}
 %
+%    \begin{macrocode}
+languages['ocaml'] = ocaml
+%    \end{macrocode}
 % 
 % \bigskip
 % \subsubsection{The function Parse}
 %
+%    \begin{macrocode}
+local MinimalSyntax = Ct ( ( (1 - P "\r" ) ^ 1 + EOL ) ^ 0 )
+%    \end{macrocode}
+%
 % The function |Parse| is the main function of the package \pkg{piton}.
 % It parses its argument and sends back to LaTeX the code with interlaced
 % formatting LaTeX instructions. In fact, everything is done by the
-% \textsc{lpeg} |SyntaxPython| which returns as capture a Lua table containing
+% \textsc{lpeg} |python| which returns as capture a Lua table containing
 % data to send to LaTeX.
 % 
 % \bigskip
 %    \begin{macrocode}
-function piton.Parse(code)
-  local t = SyntaxPython : match ( code ) 
+function piton.Parse(language,code)
+  local t = languages[language] : match ( code ) 
+  if t == nil then t = MinimalSyntax : match ( code ) end
   for _ , s in ipairs(t) do tex.tprint(s) end 
 end
 %    \end{macrocode}
 %
+%    
+%
 % \bigskip
 % The function |ParseFile| will be used by the LaTeX command |\PitonInputFile|.
 % That function merely reads the whole file (that is to say all its lines) and
 % then apply the function~|Parse| to the resulting Lua string.
 %    \begin{macrocode}
-function piton.ParseFile(name,first_line,last_line)
+function piton.ParseFile(language,name,first_line,last_line)
   s = ''
   local i = 0 
   for line in io.lines(name) 
@@ -3958,19 +4625,19 @@
      end
      if i >= last_line then break end 
   end
-  piton.Parse(s) 
+  piton.Parse(language,s) 
 end
 %    \end{macrocode}
 % 
 % \bigskip
-% \subsubsection{Two vairants of  the function Parse with integrated preprocessors}
+% \subsubsection{Two variants of  the function Parse with integrated preprocessors}
 %
 % The following command will be used by the user command |\piton|.
 % For that command, we have to undo the duplication of the symbols |#|.
 %    \begin{macrocode}
-function piton.ParseBis(code)
+function piton.ParseBis(language,code)
   local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( code )
-  return piton.Parse(s) 
+  return piton.Parse(language,s) 
 end
 %    \end{macrocode}
 %
@@ -3981,16 +4648,16 @@
 % element. In that case, you have to remove the potential |\@@_breakable_space:|
 % that have been inserted when the key |break-lines| is in force.
 %    \begin{macrocode}
-function piton.ParseTer(code)
+function piton.ParseTer(language,code)
   local s = ( Cs ( ( P '\\@@_breakable_space:' / ' ' + 1 ) ^ 0 ) ) 
             : match ( code )
-  return piton.Parse(s)
+  return piton.Parse(language,s)
 end
 %    \end{macrocode}
 % 
 %
 % \bigskip
-% \subsubsection{The preprocessors of the function Parse}
+% \subsubsection{Preprocessors of the function Parse for gobble}
 %
 % We deal now with preprocessors of the function |Parse| which are needed when
 % the ``gobble mechanism'' is used.
@@ -4095,7 +4762,7 @@
 % 
 % \bigskip
 %    \begin{macrocode}
-function piton.GobbleParse(n,code)
+function piton.GobbleParse(language,n,code)
   if n==-1 
   then n = AutoGobbleLPEG : match(code)
   else if n==-2 
@@ -4105,7 +4772,7 @@
             end
        end
   end
-  piton.Parse(gobble(n,code))
+  piton.Parse(language,gobble(n,code))
 end 
 %    \end{macrocode}
 %
@@ -4168,7 +4835,6 @@
 end 
 %    \end{macrocode}
 % 
-% \bigskip
 %    \begin{macrocode}
 \end{luacode*}
 %    \end{macrocode}
@@ -4177,6 +4843,14 @@
 % \vspace{1cm}
 % \section{History}
 %
+% \subsection*{Changes between versions 1.3 and 1.4}
+%
+% New key |identifiers| in |\PitonOptions|.
+%
+% New command |\PitonStyle|.
+%
+% |background-color| now accepts as value a \emph{list} of colors.
+%
 % \subsection*{Changes between versions 1.2 and 1.3}
 %
 % When the class Beamer is used, the environment |{Piton}| and the command 
@@ -4194,7 +4868,7 @@
 % \subsection*{Changes between versions 1.1 and 1.2}
 %
 % New keys |break-lines-in-piton| and |break-lines-in-Piton|.
-%
+% 
 % New key |show-spaces-in-string| and modification of the key |show-spaces|.
 %
 % When the class \cls{beamer} is used, the environements |{uncoverenv}|,
@@ -4249,8 +4923,8 @@
 % 
 %
 %
+% \tableofcontents
 %
-%
 % \end{document}
 % 
 %

Modified: trunk/Master/texmf-dist/source/lualatex/piton/piton.ins
===================================================================
--- trunk/Master/texmf-dist/source/lualatex/piton/piton.ins	2023-02-14 20:41:19 UTC (rev 65834)
+++ trunk/Master/texmf-dist/source/lualatex/piton/piton.ins	2023-02-14 20:41:38 UTC (rev 65835)
@@ -1,5 +1,5 @@
 %%
-%% Copyright (C) 2023 by F. Pantigny
+%% Copyright (C) 2022-2023 by F. Pantigny
 %%
 %%
 %% This file may be distributed and/or modified under the
@@ -17,7 +17,7 @@
 \usedir{tex/latex/cascade}
 \preamble
 
-Copyright (C) 2023 by F. Pantigny
+Copyright (C) 2022-2023 by F. Pantigny
 
 This file may be distributed and/or modified under the
 conditions of the LaTeX Project Public License, either

Modified: trunk/Master/texmf-dist/tex/lualatex/piton/piton.sty
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/piton/piton.sty	2023-02-14 20:41:19 UTC (rev 65834)
+++ trunk/Master/texmf-dist/tex/lualatex/piton/piton.sty	2023-02-14 20:41:38 UTC (rev 65835)
@@ -6,7 +6,7 @@
 %%
 %% piton.dtx  (with options: `package')
 %% 
-%% Copyright (C) 2023 by F. Pantigny
+%% Copyright (C) 2022-2023 by F. Pantigny
 %% 
 %% This file may be distributed and/or modified under the
 %% conditions of the LaTeX Project Public License, either
@@ -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{1.3}
-\def\myfiledate{2023/01/29}
+\def\myfileversion{1.4}
+\def\myfiledate{2023/02/14}
 
 \bigskip
 
@@ -129,6 +129,8 @@
         \bool_set_true:N \c__piton_footnote_bool
       }
   }
+\str_new:N \l__piton_language_str
+\str_set:Nn \l__piton_language_str { python }
 \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
@@ -135,8 +137,8 @@
 \tl_new:N \g__piton_aux_tl
 \int_new:N \l__piton_splittable_int
 \int_set:Nn \l__piton_splittable_int { 100 }
-\str_new:N \l__piton_bg_color_tl
-\str_new:N \l__piton_prompt_bg_color_tl
+\clist_new:N \l__piton_bg_color_clist
+\tl_new:N \l__piton_prompt_bg_color_tl
 \dim_new:N \g__piton_width_dim
 \dim_new:N \l__piton_width_on_aux_dim
 \int_new:N \g__piton_env_int
@@ -193,7 +195,7 @@
 \cs_new_protected:Npn \__piton_prompt:
   {
     \tl_gset:Nn \g__piton_begin_line_hook_tl
-      { \tl_set:NV \l__piton_bg_color_tl \l__piton_prompt_bg_color_tl }
+      { \clist_set:NV \l__piton_bg_color_clist \l__piton_prompt_bg_color_tl }
   }
 \cs_new_protected:Npn \__piton_replace_spaces:n #1
   {
@@ -220,7 +222,7 @@
     \bool_if:NTF \l__piton_slim_bool
       { \hcoffin_set:Nn \l_tmpa_coffin }
       {
-        \str_if_empty:NTF \l__piton_bg_color_tl
+        \clist_if_empty:NTF \l__piton_bg_color_clist
           {
             \vcoffin_set:Nnn \l_tmpa_coffin
               { \dim_eval:n { \linewidth - \l__piton_left_margin_dim } }
@@ -246,7 +248,7 @@
               { \tl_if_empty:nF { #1 } }
               \__piton_print_number:
           }
-        \tl_if_empty:NF \l__piton_bg_color_tl
+        \clist_if_empty:NF \l__piton_bg_color_clist
           { \skip_horizontal:n { 0.5 em } }
         \coffin_typeset:Nnnnn \l_tmpa_coffin T l \c_zero_dim \c_zero_dim
       }
@@ -254,7 +256,7 @@
       { \dim_gset:Nn \g__piton_width_dim { \box_wd:N \l_tmpa_box } }
     \box_set_dp:Nn \l_tmpa_box { \box_dp:N \l_tmpa_box + 1.25 pt }
     \box_set_ht:Nn \l_tmpa_box { \box_ht:N \l_tmpa_box + 1.25 pt }
-    \str_if_empty:NTF \l__piton_bg_color_tl
+    \clist_if_empty:NTF \l__piton_bg_color_clist
       { \box_use_drop:N \l_tmpa_box }
       {
         \vbox_top:n
@@ -261,7 +263,7 @@
           {
             \hbox:n
               {
-                \__piton_color:V \l__piton_bg_color_tl
+                \__piton_color:N \l__piton_bg_color_clist
                 \vrule height \box_ht:N \l_tmpa_box
                        depth \box_dp:N \l_tmpa_box
                        width \l__piton_width_on_aux_dim
@@ -275,8 +277,17 @@
     \group_end:
     \tl_gclear:N \g__piton_begin_line_hook_tl
   }
-\cs_set_protected:Npn \__piton_color:n #1
+\cs_set_protected:Npn \__piton_color:N #1
   {
+    \int_set:Nn \l_tmpa_int { \clist_count:N #1 }
+    \int_set:Nn \l_tmpb_int { \int_mod:nn \g__piton_line_int \l_tmpa_int + 1 }
+    \tl_set:Nx \l_tmpa_tl { \clist_item:Nn #1 \l_tmpb_int }
+    \tl_if_eq:NnTF \l_tmpa_tl { none }
+      { \dim_zero:N \l__piton_width_on_aux_dim }
+      { \exp_args:NV \__piton_color_i:n \l_tmpa_tl }
+  }
+\cs_set_protected:Npn \__piton_color_i:n #1
+  {
     \tl_if_head_eq_meaning:nNTF { #1 } [
       {
         \tl_set:Nn \l_tmpa_tl { #1 }
@@ -314,7 +325,7 @@
               \l__piton_continuation_symbol_tl
             }
             \skip_horizontal:n { 0.3 em }
-            \tl_if_empty:NF \l__piton_bg_color_tl
+            \clist_if_empty:NF \l__piton_bg_color_clist
               { \skip_horizontal:n { 0.5 em } }
           }
         \bool_if:NT \l__piton_indent_broken_lines_bool
@@ -333,6 +344,8 @@
 \bool_new:N \l__piton_resume_bool
 \keys_define:nn { PitonOptions }
   {
+    language         .str_set:N         = \l__piton_language_str ,
+    language         .value_required:n  = true ,
     gobble           .int_set:N         = \l__piton_gobble_int ,
     gobble           .value_required:n  = true ,
     auto-gobble      .code:n            = \int_set:Nn \l__piton_gobble_int { -1 } ,
@@ -351,10 +364,10 @@
     resume           .value_forbidden:n = true ,
     splittable       .int_set:N         = \l__piton_splittable_int ,
     splittable       .default:n         = 1 ,
-    background-color .str_set:N         = \l__piton_bg_color_tl ,
+    background-color .clist_set:N       = \l__piton_bg_color_clist ,
     background-color .value_required:n  = true ,
-    prompt-background-color .str_set:N         = \l__piton_prompt_bg_color_tl ,
-    prompt-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 ,
     slim             .bool_set:N        = \l__piton_slim_bool ,
     slim             .default:n         = true ,
     left-margin      .code:n =
@@ -417,7 +430,7 @@
   {
     \bool_if:NT \l__piton_slim_bool
       {
-        \tl_if_empty:NF \l__piton_bg_color_tl
+        \clist_if_empty:NF \l__piton_bg_color_clist
           {
             \tl_gput_right:Nx \g__piton_aux_tl
               {
@@ -443,7 +456,11 @@
     \cs_set_protected:Npn \__piton_begin_line: { }
     \cs_set_protected:Npn \__piton_end_line: { }
     \tl_set:Nx \l_tmpa_tl
-      { \lua_now:n { piton.ParseBis(token.scan_string()) } { #1 } }
+      {
+        \lua_now:e
+          { piton.ParseBis('\l__piton_language_str',token.scan_string()) }
+          { #1 }
+      }
     \bool_if:NTF \l__piton_show_spaces_bool
       { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
       {
@@ -461,7 +478,11 @@
     \cs_set_protected:Npn \__piton_begin_line: { }
     \cs_set_protected:Npn \__piton_end_line: { }
     \tl_set:Nx \l_tmpa_tl
-      { \lua_now:n { piton.Parse(token.scan_string()) } { #1 } }
+      {
+        \lua_now:e
+          { piton.Parse('\l__piton_language_str',token.scan_string()) }
+          { #1 }
+      }
     \bool_if:NT \l__piton_show_spaces_bool
       { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
     \l_tmpa_tl
@@ -478,11 +499,19 @@
       \l__piton_break_lines_in_Piton_bool
       {
         \tl_set:Nx \l_tmpa_tl
-          { \lua_now:n { piton.ParseTer(token.scan_string()) } { #1 } }
+          {
+            \lua_now:e
+              { piton.ParseTer('\l__piton_language_str',token.scan_string()) }
+              { #1 }
+          }
       }
       {
         \tl_set:Nx \l_tmpa_tl
-          { \lua_now:n { piton.Parse(token.scan_string()) } { #1 } }
+          {
+            \lua_now:e
+              { piton.Parse('\l__piton_language_str',token.scan_string()) }
+              { #1 }
+          }
       }
     \bool_if:NT \l__piton_show_spaces_bool
       { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
@@ -501,11 +530,19 @@
       \l__piton_break_lines_in_Piton_bool
       {
         \tl_set:Nx \l_tmpa_tl
-          { \lua_now:n { piton.ParseTer(token.scan_string()) } { #1 } }
+          {
+            \lua_now:e
+              { piton.ParseTer('\l__piton_language_str',token.scan_string()) }
+              { #1 }
+          }
       }
       {
         \tl_set:Nx \l_tmpa_tl
-          { \lua_now:n { piton.Parse(token.scan_string()) } { #1 } }
+          {
+            \lua_now:e
+              { piton.Parse('\l__piton_language_str',token.scan_string()) }
+              { #1 }
+          }
       }
     \bool_if:NT \l__piton_show_spaces_bool
       { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423
@@ -576,7 +613,7 @@
       \vtop \bgroup
       \lua_now:e
         {
-          piton.ParseFile(token.scan_argument() ,
+          piton.ParseFile('\l__piton_language_str',token.scan_argument() ,
            \int_use:N \l__piton_first_line_int ,
            \int_use:N \l__piton_last_line_int )
         }
@@ -633,7 +670,11 @@
             \lua_now:e
               {
                 piton.GobbleParse
-                  ( \int_use:N \l__piton_gobble_int , token.scan_argument() )
+                  (
+                    '\l__piton_language_str' ,
+                    \int_use:N \l__piton_gobble_int ,
+                    token.scan_argument()
+                  )
               }
               { ##1 }
             \vspace { 2.5 pt }
@@ -711,6 +752,8 @@
     Name.Class       .value_required:n = true ,
     Name.Builtin     .tl_set:c = pitonStyle Name.Builtin ,
     Name.Builtin     .value_required:n = true ,
+    TypeParameter    .tl_set:c = pitonStyle TypeParameter ,
+    TypeParameter    .value_required:n = true ,
     Name.Type        .tl_set:c = pitonStyle Name.Type ,
     Name.Type        .value_required:n = true ,
     Operator         .tl_set:c = pitonStyle Operator ,
@@ -717,14 +760,18 @@
     Operator         .value_required:n = true ,
     Operator.Word    .tl_set:c = pitonStyle Operator.Word ,
     Operator.Word    .value_required:n = true ,
-    Post.Function    .tl_set:c = pitonStyle Post.Function ,
-    Post.Function    .value_required:n = true ,
     Exception        .tl_set:c = pitonStyle Exception ,
     Exception        .value_required:n = true ,
     Comment.LaTeX    .tl_set:c = pitonStyle Comment.LaTeX ,
     Comment.LaTeX    .value_required:n = true ,
-    Beamer           .tl_set:c = pitonStyle Beamer ,
-    Beamer           .value_required:n = true ,
+    Identifier       .tl_set:c = pitonStyle Identifier ,
+    Comment.LaTeX    .value_required:n = true ,
+    ParseAgain.noCR  .tl_set:c = pitonStyle ParseAgain.noCR ,
+    ParseAgain.noCR  .value_required:n = true ,
+    ParseAgain       .tl_set:c = pitonStyle ParseAgain ,
+    ParseAgain       .value_required:n = true ,
+    Prompt           .tl_set:c = pitonStyle Prompt ,
+    Prompt           .value_required:n = true ,
     unknown          .code:n =
       \msg_error:nn { piton } { Unknown~key~for~SetPitonStyle }
   }
@@ -737,6 +784,7 @@
     Comment.LaTeX,~
     Dict.Value,~
     Exception,~
+    Identifier,~
     InitialValues,~
     Keyword,~
     Keyword.Constant,~
@@ -748,6 +796,7 @@
     Number,~
     Operator,~
     Operator.Word,~
+    Prompt,~
     String,~
     String.Doc,~
     String.Long,~
@@ -776,11 +825,34 @@
     InitialValues    = \__piton_piton:n ,
     Dict.Value       = \__piton_piton:n ,
     Interpol.Inside  = \color{black}\__piton_piton:n ,
-    Beamer           = \__piton_piton_no_cr:n ,
-    Post.Function    = \__piton_piton:n ,
+    TypeParameter    = \color[HTML]{008800} \itshape ,
+    Identifier       = \__piton_identifier:n ,
+    Prompt           = ,
+    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 \c__piton_math_comments_bool { \SetPitonStyle { Comment.Math } }
+\cs_new_protected:Npn \__piton_identifier:n #1
+  { \cs_if_exist_use:c { PitonIdentifier #1 } { #1 } }
+\keys_define:nn { PitonOptions }
+  { identifiers .code:n = \__piton_set_identifiers:n { #1 } }
+\keys_define:nn { Piton / identifiers }
+  {
+    names .clist_set:N = \l__piton_identifiers_names_tl ,
+    style .tl_set:N    = \l__piton_style_tl ,
+  }
+\cs_new_protected:Npn \__piton_set_identifiers:n #1
+  {
+    \clist_clear_new:N \l__piton_identifiers_names_tl
+    \tl_clear_new:N \l__piton_style_tl
+    \keys_set:nn { Piton / identifiers } { #1 }
+    \clist_map_inline:Nn \l__piton_identifiers_names_tl
+      {
+        \tl_set_eq:cN
+          { PitonIdentifier ##1 }
+          \l__piton_style_tl
+      }
+  }
 \AddToHook { env / piton / begin }
    { \msg_fatal:nn { piton } { No~environment~piton } }
 
@@ -811,7 +883,9 @@
     end-of-broken-line,~
     env-gobble,~
     gobble,~
+    identifiers,~
     indent-broken-lines,~
+    language,~
     left-margin,~
     line-numbers,~
     prompt-background-color,~
@@ -853,7 +927,8 @@
 if piton.comment_latex == nil then piton.comment_latex = ">" end
 piton.comment_latex = "#" .. piton.comment_latex
 local P, S, V, C, Ct, Cc = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc
-local Cf, Cs = lpeg.Cf, lpeg.Cs
+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
@@ -888,7 +963,7 @@
 
 local alphanum = letter + digit
 local identifier = letter * alphanum ^ 0
-local Identifier = K ( identifier )
+local Identifier = K ( identifier , 'Identifier' )
 local Number =
   K (
       ( digit^1 * P "." * digit^0 + digit^0 * P "." * digit^1 + digit^1 )
@@ -911,6 +986,7 @@
 local Tab = P "\t" * Lc ( '\\l__piton_tab_tl' )
 local SpaceIndentation = Lc ( '\\__piton_an_indentation_space:' ) * ( K " " )
 local Delim = K ( S "[()]" )
+local VisualSpace = space * Lc "\\l__piton_space_tl"
 local Operator =
   K ( P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":="
       + P "//" + P "**" + S "-~+/*%=<>&.@|"
@@ -946,7 +1022,7 @@
   'Name.Builtin' )
 
 local Exception =
-  K ( "ArithmeticError" + P "AssertionError" + P "AttributeError"
+  K ( 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"
@@ -990,41 +1066,6 @@
   K ( P "from" , 'Keyword' )
     * Space * K ( identifier , 'Name.Namespace' )
     * Space * K ( P "import" , 'Keyword' )
-local SingleShortInterpol =
-    K ( P "{" , 'String.Interpol')
-  * K ( ( 1 - S "}':" ) ^ 0 , 'Interpol.Inside' )
-  * K ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1
-  * K ( P "}" , 'String.Interpol' )
-
-local DoubleShortInterpol =
-    K ( P "{" , 'String.Interpol' )
-  * K ( ( 1 - S "}\":" ) ^ 0 , 'Interpol.Inside' )
-  * ( K ( P ":" , 'String.Interpol' ) * K ( (1 - S "}:\"") ^ 0 ) ) ^ -1
-  * K ( P "}" , 'String.Interpol' )
-
-local SingleLongInterpol =
-    K ( P "{" , 'String.Interpol' )
-  * K ( ( 1 - S "}:\r" - P "'''" ) ^ 0 , 'Interpol.Inside' )
-  * K ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1
-  * K ( P "}" , 'String.Interpol' )
-
-local DoubleLongInterpol =
-    K ( P "{" , 'String.Interpol' )
-  * K ( ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 , 'Interpol.Inside' )
-  * K ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1
-  * K ( P "}" , 'String.Interpol' )
-local VisualSpace = space * Lc "\\l__piton_space_tl"
-local SingleShortPureString =
-  ( VisualSpace + K ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 ) ) ^ 1
-
-local DoubleShortPureString =
-  ( VisualSpace + K ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 ) ) ^ 1
-
-local SingleLongPureString =
-  K ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 )
-
-local DoubleLongPureString =
-  K ( ( 1 - P "\"\"\"" - S " {}\"\r" ) ^ 1 )
 local PercentInterpol =
   K ( P "%"
       * ( P "(" * alphanum ^ 1 * P ")" ) ^ -1
@@ -1039,7 +1080,16 @@
   Lc ( "{\\PitonStyle{String.Short}{" )
    * (
          K ( P "f'" + P "F'" )
-         * ( SingleShortInterpol + SingleShortPureString ) ^ 0
+         * (
+             K ( P "{" , 'String.Interpol')
+              * K ( ( 1 - S "}':" ) ^ 0 , 'Interpol.Inside' )
+              * K ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1
+              * K ( P "}" , 'String.Interpol' )
+             +
+             VisualSpace
+             +
+             K ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 )
+           ) ^ 0
          * K ( P "'" )
        +
          K ( P "'" + P "r'" + P "R'" )
@@ -1056,7 +1106,16 @@
   Lc ( "{\\PitonStyle{String.Short}{" )
    * (
          K ( P "f\"" + P "F\"" )
-         * ( DoubleShortInterpol + DoubleShortPureString ) ^ 0
+         * (
+             K ( P "{" , 'String.Interpol' )
+               * K ( ( 1 - S "}\":" ) ^ 0 , 'Interpol.Inside' )
+               * ( K ( P ":" , 'String.Interpol' ) * K ( (1 - S "}:\"") ^ 0 ) ) ^ -1
+               * K ( P "}" , 'String.Interpol' )
+             +
+             VisualSpace
+             +
+             K ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 )
+            ) ^ 0
          * K ( P "\"" )
        +
          K ( P "\"" + P "r\"" + P "R\"" )
@@ -1072,11 +1131,13 @@
 local ShortString = SingleShortString + DoubleShortString
 local BalancedBraces =
   P { "E" ,
-       E = ( ShortString + ( 1 - S "{}" ) ) ^ 0
-           *
+       E =
            (
-              P "{" * V "E" * P "}"
-              * ( ShortString + ( 1 - S "{}" ) ) ^ 0
+             P "{" * V "E" * P "}"
+             +
+             ShortString
+             +
+             ( 1 - S "{}" )
            ) ^ 0
     }
 local Beamer = P ( false )
@@ -1084,6 +1145,7 @@
 local BeamerEndEnvironments = P ( true )
 local BeamerNamesEnvironments =
   P "uncoverenv" + P "onlyenv" + P "visibleenv" + P "invisibleenv"
+  + P "alertenv" + P "actionenv"
 
 if piton_beamer
 then
@@ -1099,7 +1161,7 @@
       )
       *
       L ( ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 * P "{" )
-      * K ( BalancedBraces , 'Beamer' )
+      * K ( BalancedBraces , 'ParseAgain.noCR' )
       * L ( P "}" )
     +
       L (
@@ -1107,9 +1169,9 @@
           * P "<" * (1 - P ">") ^ 0 * P ">"
           * P "{"
         )
-      * K ( BalancedBraces , 'Beamer' )
+      * K ( BalancedBraces , 'ParseAgain.noCR' )
       * L ( P "}{" )
-      * K ( BalancedBraces , 'Beamer' )
+      * K ( BalancedBraces , 'ParseAgain.noCR' )
       * L ( P "}" )
     +
       L (
@@ -1117,11 +1179,11 @@
           * P "<" * (1 - P ">") ^ 0 * P ">"
           * P "{"
         )
-      * K ( BalancedBraces , 'Beamer' )
+      * K ( BalancedBraces , 'ParseAgain.noCR' )
       * L ( P "}{" )
-      * K ( BalancedBraces , 'Beamer' )
+      * K ( BalancedBraces , 'ParseAgain.noCR' )
       * L ( P "}{" )
-      * K ( BalancedBraces , 'Beamer' )
+      * K ( BalancedBraces , 'ParseAgain.noCR' )
       * L ( P "}" )
   BeamerBeginEnvironments =
       ( space ^ 0 *
@@ -1138,7 +1200,8 @@
         * P "\r"
       ) ^ 0
 end
-local Prompt = ( # ( P ">>>" + P "..." )  * Lc ( '\\__piton_prompt:' ) ) ^ -1
+local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\__piton_prompt:' ) ) ^ -1
+local Prompt = K ( ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1 , 'Prompt' )
 local EOL
 if piton_beamer
 then
@@ -1151,8 +1214,9 @@
     Lc ( '\\__piton_end_line:' )
     * BeamerEndEnvironments
     * BeamerBeginEnvironments
+    * PromptHastyDetection
+    * Lc ( '\\__piton_newline: \\__piton_begin_line:' )
     * Prompt
-    * Lc ( '\\__piton_newline: \\__piton_begin_line:' )
   )
   *
   SpaceIndentation ^ 0
@@ -1164,40 +1228,41 @@
     ( space ^ 0 * -1 )
     +
     Lc ( '\\__piton_end_line:' )
+    * PromptHastyDetection
+    * Lc ( '\\__piton_newline: \\__piton_begin_line:' )
     * Prompt
-    * Lc ( '\\__piton_newline: \\__piton_begin_line:' )
   )
   *
   SpaceIndentation ^ 0
 end
+function EOL_for_style ( s )
+   return Lc "}}" * EOL * Lc ( "{\\PitonStyle{" .. s .. "}{" )
+end
 local SingleLongString =
   Lc "{\\PitonStyle{String.Long}{"
    * (
          K ( S "fF" * P "'''" )
-         * ( SingleLongInterpol + SingleLongPureString ) ^ 0
-         * Lc "}}"
          * (
-             EOL
+             K ( P "{" , 'String.Interpol' )
+               * K ( ( 1 - S "}:\r" - P "'''" ) ^ 0 , 'Interpol.Inside' )
+               * K ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1
+               * K ( P "}" , 'String.Interpol' )
              +
-             Lc "{\\PitonStyle{String.Long}{"
-             * ( SingleLongInterpol + SingleLongPureString ) ^ 0
-             * Lc "}}"
-             * EOL
+             K ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 )
+             +
+             EOL_for_style 'String.Long'
            ) ^ 0
-         * Lc "{\\PitonStyle{String.Long}{"
-         * ( SingleLongInterpol + SingleLongPureString ) ^ 0
        +
-         K ( ( S "rR" ) ^ -1  * P "'''"
-             * ( 1 - P "'''" - P "\r" ) ^ 0 )
-         * Lc "}}"
+         K ( ( S "rR" ) ^ -1  * P "'''" )
          * (
-             Lc "{\\PitonStyle{String.Long}{"
-             * K ( ( 1 - P "'''" - P "\r" ) ^ 0 )
-             * Lc "}}"
-             * EOL
+             K ( ( 1 - P "'''" - S "\r%" ) ^ 1 )
+             +
+             PercentInterpol
+             +
+             P "%"
+             +
+             EOL_for_style 'String.Long'
            ) ^ 0
-         * Lc "{\\PitonStyle{String.Long}{"
-         * K ( ( 1 - P "'''" - P "\r" ) ^ 0 )
       )
    * K ( P "'''" )
    * Lc "}}"
@@ -1206,30 +1271,27 @@
   Lc "{\\PitonStyle{String.Long}{"
    * (
          K ( S "fF" * P "\"\"\"" )
-         * ( DoubleLongInterpol + DoubleLongPureString ) ^ 0
-         * Lc "}}"
          * (
-             EOL
+             K ( P "{" , 'String.Interpol' )
+               * K ( ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 , 'Interpol.Inside' )
+               * K ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1
+               * K ( P "}" , 'String.Interpol' )
              +
-             Lc "{\\PitonStyle{String.Long}{"
-             * ( DoubleLongInterpol + DoubleLongPureString ) ^ 0
-             * Lc "}}"
-             * EOL
+             K ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 )
+             +
+             EOL_for_style 'String.Long'
            ) ^ 0
-         * Lc "{\\PitonStyle{String.Long}{"
-         * ( DoubleLongInterpol + DoubleLongPureString ) ^ 0
        +
-         K ( ( S "rR" ) ^ -1  * P "\"\"\""
-              * ( 1 - P "\"\"\"" - P "\r" ) ^ 0 )
-         * Lc "}}"
+         K ( ( S "rR" ) ^ -1  * P "\"\"\"" )
          * (
-             Lc "{\\PitonStyle{String.Long}{"
-             * K ( ( 1 - P "\"\"\"" - P "\r" ) ^ 0 )
-             * Lc "}}"
-             * EOL
+             K ( ( 1 - P "\"\"\"" - S "%\r" ) ^ 1 )
+             +
+             PercentInterpol
+             +
+             P "%"
+             +
+             EOL_for_style 'String.Long'
            ) ^ 0
-         * Lc "{\\PitonStyle{String.Long}{"
-         * K ( ( 1 - P "\"\"\"" - P "\r" ) ^ 0 )
       )
    * K ( P "\"\"\"" )
    * Lc "}}"
@@ -1287,7 +1349,7 @@
   * K ( P "(" ) * Params * K ( P ")" )
   * SkipSpace
   * ( K ( P "->" ) * SkipSpace * K ( identifier , 'Name.Type' ) ) ^ -1
-  * K ( ( 1 - S ":\r" )^0 , 'Post.Function' )
+  * K ( ( 1 - S ":\r" )^0 , 'ParseAgain' )
   * K ( P ":" )
   * ( SkipSpace
       * ( EOL + CommentLaTeX + Comment ) -- in all cases, that contains an EOL
@@ -1322,7 +1384,6 @@
      + ShortString
      + Punct
      + FromImport
-     + ImportAs
      + RaiseException
      + DefFunction
      + DefClass
@@ -1334,28 +1395,271 @@
      + Number
      + Word
   ) ^ 0
-local SyntaxPython = P ( true )
+local python = P ( true )
 
-function piton.defSyntaxPython()
-  SyntaxPython =
-    Ct (
-         ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1
-         * BeamerBeginEnvironments
-         * Prompt
-         * Lc ( '\\__piton_begin_line:' )
-         * SpaceIndentation ^ 0
-         * MainLoop
-         * -1
-         * Lc ( '\\__piton_end_line:' )
-       )
+python =
+  Ct (
+       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1
+       * BeamerBeginEnvironments
+       * PromptHastyDetection
+       * Lc ( '\\__piton_begin_line:' )
+       * Prompt
+       * SpaceIndentation ^ 0
+       * MainLoop
+       * -1
+       * Lc ( '\\__piton_end_line:' )
+     )
+local languages = { }
+languages['python'] = python
+local Punct = K ( S ",:;!" )
+local identifier =
+  ( R "az" + R "AZ" + P "_") * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0
+
+local Identifier = K ( identifier )
+
+local Operator =
+  K ( P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":="
+      + P "||" + P "&&" + P "//" + P "**" + P ";;" + P "::" + P "->"
+      + P "+." + P "-." + P "*." + P "/."
+      + S "-~+/*%=<>&@|"
+      ,
+      'Operator'
+    )
+
+local OperatorWord =
+  K ( P "and" + P "asr" + P "land" + P "lor" + P "lsl" + P "lxor"
+      + P "mod" + P "or" ,
+      'Operator.Word')
+
+local Keyword =
+  K ( P "as" + P "assert" + P "begin" + P "class" + P "constraint" + P "done"
+  + P "do" + P "downto" + P "else" + P "end" + P "exception" + P "external"
+  + P "false" + P "for" + P "function" + P "fun" + P "functor" + P "if"
+  + P "in" + P "include" + P "inherit" + P "initializer" + 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 "true" + P "try" + P "type"
+  + P "value" + P "val" + P "virtual" + P "when" + P "while" + P "with" ,
+  'Keyword' )
+  + K ( P "true" + P "false" , 'Keyword.Constant' )
+
+local Builtin =
+  K (   P "not" + P "incr" + P "decr" + P "fst" + P "snd"
+      + P "String.length"
+      + P "List.tl" + P "List.hd" + P "List.mem" + P "List.exists"
+      + P "List.for_all" + P "List.filter" + P "List.length" + P "List.map"
+      + P "List.iter"
+      + P "Array.length" + P "Array.make" + P "Array.make_matrix"
+      + P "Array.init" + P "Array.copy" + P "Array.copy" + P "Array.mem"
+      + P "Array.exists" + P "Array.for_all" + P "Array.map" + P "Array.iter"
+      + P "Queue.create" + P "Queue.is_empty" + P "Queue.push" + P "Queue.pop"
+      + P "Stack.create" + P "Stack.is_empty" + P "Stack.push" + P "Stack.pop"
+      + P "Hashtbl.create" + P "Hashtbl.add" + P "Hashtbl.remove"
+      + P "Hashtbl.mem" + P "Hashtbl.find" + P "Hashtbl.find_opt"
+      + P "Hashtbl.iter"
+      , 'Name.Builtin' )
+local Exception =
+  K ( 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" ,
+  'Exception' )
+local Char =
+  K ( P "'" * ( ( 1 - P "'" ) ^ 0 + P "\\'" ) * P "'" , 'String.Short' )
+local BalancedBraces =
+  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 )
+    +
+      (   P "\\uncover"   * Lc ( '\\__piton_beamer_command:n{uncover}' )
+        + P "\\only"      * Lc ( '\\__piton_beamer_command:n{only}' )
+        + P "\\alert"     * Lc ( '\\__piton_beamer_command:n{alert}' )
+        + P "\\visible"   * Lc ( '\\__piton_beamer_command:n{visible}' )
+        + P "\\invisible" * Lc ( '\\__piton_beamer_command:n{invisible}' )
+        + P "\\action"    * Lc ( '\\__piton_beamer_command:n{action}' )
+      )
+      *
+      L ( ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 * P "{" )
+      * K ( BalancedBraces , 'ParseAgain.noCR' )
+      * L ( P "}" )
+    +
+      L (
+          ( P "\\alt" )
+          * P "<" * (1 - P ">") ^ 0 * P ">"
+          * P "{"
+        )
+      * K ( BalancedBraces , 'ParseAgain.noCR' )
+      * L ( P "}{" )
+      * K ( BalancedBraces , 'ParseAgain.noCR' )
+      * L ( P "}" )
+    +
+      L (
+          ( P "\\temporal" )
+          * P "<" * (1 - P ">") ^ 0 * P ">"
+          * P "{"
+        )
+      * K ( BalancedBraces , 'ParseAgain.noCR' )
+      * L ( P "}{" )
+      * K ( BalancedBraces , 'ParseAgain.noCR' )
+      * L ( P "}{" )
+      * K ( BalancedBraces , 'ParseAgain.noCR' )
+      * L ( P "}" )
+  BeamerBeginEnvironments =
+      ( space ^ 0 *
+        L
+          (
+            P "\\begin{" * BeamerNamesEnvironments * "}"
+            * ( P "<" * ( 1 - P ">") ^ 0 * P ">" ) ^ -1
+          )
+        * P "\r"
+      ) ^ 0
+  BeamerEndEnvironments =
+      ( space ^ 0 *
+        L ( P "\\end{" * BeamerNamesEnvironments * P "}" )
+        * P "\r"
+      ) ^ 0
 end
+local EOL
+if piton_beamer
+then
+EOL =
+  P "\r"
+  *
+  (
+    ( space^0 * -1 )
+    +
+    Lc ( '\\__piton_end_line:' )
+    * BeamerEndEnvironments
+    * BeamerBeginEnvironments
+    * Lc ( '\\__piton_newline: \\__piton_begin_line:' )
+  )
+  *
+  SpaceIndentation ^ 0
+else
+EOL =
+  P "\r"
+  *
+  (
+    ( space ^ 0 * -1 )
+    +
+    Lc ( '\\__piton_end_line:' )
+    * Lc ( '\\__piton_newline: \\__piton_begin_line:' )
+  )
+  *
+  SpaceIndentation ^ 0
+end
+function EOL_for_style ( s )
+   return Lc "}}" * EOL * Lc ( "{\\PitonStyle{" .. s .. "}{" )
+end
+local String =
+  Lc "{\\PitonStyle{String.Long}{"
+   * K ( P "\"" )
+   * (
+       VisualSpace
+       +
+       K ( ( 1 - S " \"\r" ) ^ 1 )
+       +
+       EOL_for_style 'String.Long'
+     ) ^ 0
+   * K ( P "\"" )
+   * Lc "}}"
+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 =
+   Lc "{\\PitonStyle{String.Long}{"
+   *
+     (
+        VisualSpace
+        +
+        K ( ( 1 - S " \r" ) ^ 1 )
+        +
+        EOL_for_style 'String.Long'
+     ) ^ 0
+   * Lc "}}"
+local QuotedString =
+   C ( open * ( 1 - closeeq ) ^ 0  * close ) /
+  ( function (s) return QuotedStringBis : match(s) end )
+local Comment =
+  Lc "{\\PitonStyle{Comment}{"
+  *
+  P {
+      "A" ,
+      A = K "(*"
+          * ( V "A"
+              + K ( ( 1 - P "(*" - P "*)" - S "\r$" ) ^ 1 ) -- $
+              + P "$" * K ( ( 1 - S "$\r" ) ^ 1 , 'Comment.Math' ) * P "$" -- $
+              + EOL_for_style 'Comment'
+            ) ^ 0
+          * K "*)"
+    }
+  *
+  Lc "}}"
+local DefFunction =
+  ( K ( P "let rec" + P "let" + P "and" , 'Keyword' ) )
+  * Space
+  * K ( identifier , 'Name.Function' )
+  * Space
+  * # ( 1 - P "=" )
+local TypeParameter = K ( P "'" * alpha * # ( 1 - P "'") , 'TypeParameter' )
+MainLoop =
+  (  ( space^1 * -1 )
+     + EOL
+     + Space
+     + Tab
+     + Escape
+     + Beamer
+     + TypeParameter
+     + String + QuotedString + Char
+     + Comment
+     + Delim
+     + Operator
+     + Punct
+     + FromImport
+     + ImportAs
+     + Exception
+     + DefFunction
+     + Keyword * ( Space + Punct + Delim + EOL + -1 )
+     + OperatorWord * ( Space + Punct + Delim + EOL + -1 )
+     + Builtin * ( Space + Punct + Delim + EOL + -1 )
+     + Identifier
+     + Number
+     + Word
+  ) ^ 0
+local ocaml = P ( true )
 
-piton.defSyntaxPython()
-function piton.Parse(code)
-  local t = SyntaxPython : match ( code )
+ocaml =
+  Ct (
+       ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1
+       * BeamerBeginEnvironments
+       * Lc ( '\\__piton_begin_line:' )
+       * SpaceIndentation ^ 0
+       * MainLoop
+       * -1
+       * Lc ( '\\__piton_end_line:' )
+     )
+languages['ocaml'] = ocaml
+local MinimalSyntax = Ct ( ( (1 - P "\r" ) ^ 1 + EOL ) ^ 0 )
+function piton.Parse(language,code)
+  local t = languages[language] : match ( code )
+  if t == nil then t = MinimalSyntax : match ( code ) end
   for _ , s in ipairs(t) do tex.tprint(s) end
 end
-function piton.ParseFile(name,first_line,last_line)
+function piton.ParseFile(language,name,first_line,last_line)
   s = ''
   local i = 0
   for line in io.lines(name)
@@ -1365,16 +1669,16 @@
      end
      if i >= last_line then break end
   end
-  piton.Parse(s)
+  piton.Parse(language,s)
 end
-function piton.ParseBis(code)
+function piton.ParseBis(language,code)
   local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( code )
-  return piton.Parse(s)
+  return piton.Parse(language,s)
 end
-function piton.ParseTer(code)
+function piton.ParseTer(language,code)
   local s = ( Cs ( ( P '\\__piton_breakable_space:' / ' ' + 1 ) ^ 0 ) )
             : match ( code )
-  return piton.Parse(s)
+  return piton.Parse(language,s)
 end
 local function gobble(n,code)
   function concat(acc,new_value)
@@ -1428,7 +1732,7 @@
 local EnvGobbleLPEG =
   ( ( 1 - P "\r" ) ^ 0 * P "\r" ) ^ 0
     * Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add ) * -1
-function piton.GobbleParse(n,code)
+function piton.GobbleParse(language,n,code)
   if n==-1
   then n = AutoGobbleLPEG : match(code)
   else if n==-2
@@ -1438,7 +1742,7 @@
             end
        end
   end
-  piton.Parse(gobble(n,code))
+  piton.Parse(language,gobble(n,code))
 end
 function piton.CountLines(code)
   local count = 0



More information about the tex-live-commits mailing list.