From 1b771c1e303b8274d871ee6bd4bdd5ba03bdd152 Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Tue, 19 Mar 2024 03:02:55 +0000
Subject: CTAN sync 202403190302

---
 macros/luatex/latex/piton/piton.dtx | 607 +++++++++++++++++++++++++-----------
 1 file changed, 425 insertions(+), 182 deletions(-)

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

diff --git a/macros/luatex/latex/piton/piton.dtx b/macros/luatex/latex/piton/piton.dtx
index fb06977b46..aa149d78e9 100644
--- a/macros/luatex/latex/piton/piton.dtx
+++ b/macros/luatex/latex/piton/piton.dtx
@@ -72,12 +72,12 @@
 % \iffalse
 %<*STY>
 % \fi
-\def\PitonFileVersion{2.6a}
-\def\PitonFileDate{2024/03/06}
+\def\PitonFileVersion{2.6b}
+\def\PitonFileDate{2024/03/18}
 % \iffalse
 %</STY>
 %<*LUA>
--- Version 2.6a of 2024/03/06
+piton_version = "2.6b" -- 2024/03/18
 %</LUA>
 %\fi
 %
@@ -659,17 +659,31 @@
 % any other style, with the command |\SetPitonStyle|.
 %
 % \medskip
-% In the following example, we fix as value for that style |UserFunction| the
-% initial value of the style |Name.Function| (which applies to the name of
-% the functions, \emph{at the moment of their definition}).
+% In the following example, we tune the styles |Name.Function| and |UserFunction|
+% so as to have clickable names of functions linked to the (informatic)
+% definition of the function.
 %
 % \begingroup
 %
+% \NewDocumentCommand{\MyDefFunction}{m}{\hypertarget{piton:#1}{\color[HTML]{CC00FF}{#1}}}
+% \NewDocumentCommand{\MyUserFunction}{m}{\hyperlink{piton:#1}{#1}}
+%
+% \SetPitonStyle
+%   {
+%     Name.Function = \MyDefFunction ,
+%     UserFunction = \MyUserFunction
+%   }
+%
+% \medskip
 % \begin{Verbatim}
-% \SetPitonStyle{~emphase#UserFunction@ = \color[HTML]{CC00FF}}
+% \NewDocumentCommand{\MyDefFunction}{m}
+%    {\hypertarget{piton:~#1}{\color[HTML]{CC00FF}{~#1}}}
+% \NewDocumentCommand{\MyUserFunction}{m}{\hyperlink{piton:~#1}{~#1}}
+%
+% \SetPitonStyle{Name.Function = \MyDefFunction, ~emphase#UserFunction@ = \MyUserFunction}
 % \end{Verbatim}
 %
-% \SetPitonStyle{UserFunction = \color[HTML]{CC00FF}}
+% \bigskip
 %
 % \begin{Piton}
 % def transpose(v,i,j):
@@ -685,10 +699,6 @@
 %
 % \endgroup
 %
-% As one see, the name |transpose| has been highlighted because it's the name of
-% a Python function previously defined by the user (hence the name
-% |UserFunction| for that style).
-%
 % \PitonClearUserFunctions[Python]
 %
 % \bigskip
@@ -3145,7 +3155,6 @@
 % Now, we add the potential number of line, the potential left margin and the
 % potential background.
 %    \begin{macrocode}
-    \tl_log:n { Contenu : #1.}
     \hbox_set:Nn \l_tmpa_box 
       { 
         \skip_horizontal:N \l_@@_left_margin_dim
@@ -3793,6 +3802,8 @@
     \group_begin:
     \cs_set_protected:Npn \@@_begin_line: { }
     \cs_set_protected:Npn \@@_end_line: { }
+    \cs_set:cpn { pitonStyle _ \l_piton_language_str  _ Prompt } { }
+    \cs_set:cpn { pitonStyle _ Prompt } { }
     \bool_lazy_or:nnTF 
       \l_@@_break_lines_in_piton_bool
       \l_@@_break_lines_in_Piton_bool
@@ -3828,6 +3839,8 @@
     \group_begin:
     \cs_set_protected:Npn \@@_begin_line: { }
     \cs_set_protected:Npn \@@_end_line: { }
+    \cs_set:cpn { pitonStyle _ \l_piton_language_str  _ Prompt } { }
+    \cs_set:cpn { pitonStyle _ Prompt } { }
     \cs_set_protected:Npn \@@_newline:
       { \msg_fatal:nn { piton } { cr~not~allowed } }
     \bool_lazy_or:nnTF 
@@ -4318,6 +4331,7 @@
   {
     Comment ,
     Comment.LaTeX ,
+    Discard ,
     Exception ,
     FormattingType ,    
     Identifier ,
@@ -4325,6 +4339,14 @@
     Interpol.Inside ,
     Keyword ,
     Keyword.Constant ,
+    Keyword2 ,
+    Keyword3 ,
+    Keyword4 ,
+    Keyword5 ,
+    Keyword6 ,
+    Keyword7 ,
+    Keyword8 ,
+    Keyword9 ,
     Name.Builtin ,      
     Name.Class ,
     Name.Constructor ,
@@ -4345,7 +4367,12 @@
     String.Long ,
     String.Short ,     
     TypeParameter ,    
-    UserFunction 
+    UserFunction ,
+%    \end{macrocode}
+% Now, specific styles for the languages created with |\NewPitonLanguage| with
+% the syntax of \pkg{listings}.
+%    \begin{macrocode}
+    directive
   }  
 
 \clist_map_inline:Nn \g_@@_styles_clist  
@@ -4433,10 +4460,12 @@
     TypeParameter      = \color[HTML]{336666} \itshape ,
     Preproc            = \color[HTML]{AA6600} \slshape ,
     Identifier         = \@@_identifier:n , 
+    directive          = \color[HTML]{AA6600} ,
     UserFunction       = , 
     Prompt             = , 
     ParseAgain.noCR    = \@@_piton_no_cr:n , 
     ParseAgain         = \@@_piton:n ,
+    Discard            = \use_none:n 
   }
 %    \end{macrocode}
 % The last styles |ParseAgain.noCR| and |ParseAgain| should be considered as 
@@ -4470,14 +4499,14 @@
     \tl_if_novalue:nTF { #1 }
       { 
         \clist_map_inline:Nn \l_tmpa_clist 
-          { \cs_set:cpn { pitonIdentifier _ ##1 } { #3 } }
+          { \cs_set:cpn { PitonIdentifier _ ##1 } { #3 } }
       }
       {
         \str_set:Nx \l_tmpa_str { \str_lowercase:n { #1 } }
         \str_if_eq:onT \l_tmpa_str { current-language }
           { \str_set_eq:NN \l_tmpa_str \l_piton_language_str }
         \clist_map_inline:Nn \l_tmpa_clist 
-          { \cs_set:cpn { pitonIdentifier _ \l_tmpa_str _ ##1 } { #3 } }
+          { \cs_set:cpn { PitonIdentifier _ \l_tmpa_str _ ##1 } { #3 } }
       }
   } 
 %    \end{macrocode}
@@ -4485,8 +4514,8 @@
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_identifier:n #1
   { 
-    \cs_if_exist_use:cF { pitonIdentifier _ \l_piton_language_str _ #1 } 
-      { \cs_if_exist_use:c { pitonIdentifier_ #1 } }
+    \cs_if_exist_use:cF { PitonIdentifier _ \l_piton_language_str _ #1 } 
+      { \cs_if_exist_use:c { PitonIdentifier _ #1 } }
     { #1 } 
   } 
 %    \end{macrocode}
@@ -4644,11 +4673,22 @@
     {piton}.~This~error~is~fatal.
   }
 %    \end{macrocode}
+%
 % 
 % \bigskip
 % \subsubsection{The error messages of the package}
 % 
 %    \begin{macrocode}
+\@@_msg_new:nn { bad~version~of~piton.lua }
+  {
+    Bad~number~version~of~'piton.lua'\\
+    The~file~'piton.lua'~loaded~has~not~the~same~number~of~
+    version~as~the~file~'piton.sty'.~You~can~go~on~but~you~should~
+    address~that~issue.
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
 \@@_msg_new:nn { key~identifiers~deprecated }
   {
     The~key~'identifiers'~in~the~command~\token_to_str:N PitonOptions\ 
@@ -4831,10 +4871,27 @@
 % \bigskip
 % \subsubsection{We load piton.lua}
 %
+%
+% \bigskip
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_test_version:n #1
+  { 
+    \str_if_eq:VnF \PitonFileVersion { #1 } 
+      { \@@_error:n { bad~version~of~piton.lua } }
+  }
+%    \end{macrocode}
+%
 % \bigskip
 %    \begin{macrocode}
 \hook_gput_code:nnn { begindocument } { . }
-  { \lua_now:e { require("piton.lua") } }
+  { 
+    \lua_now:n 
+      { 
+        require ( "piton" ) 
+        tex.sprint ( luatexbase.catcodetables.CatcodeTableExpl ,
+                     "\\@@_test_version:n {" .. piton_version .. "}" ) 
+      } 
+  }
 %    \end{macrocode}
 % 
 % \bigskip
@@ -5086,10 +5143,11 @@ local Number =
 % corresponding to the keys |begin-escape| and |end-escape|. 
 %    \begin{macrocode}
 local Word
-if piton.begin_escape ~= nil 
-then Word = Q ( ( ( 1 - space - P ( piton.begin_escape ) - P ( piton.end_escape ) ) 
+if piton.begin_escape then 
+  Word = Q ( ( 1 - space - piton.begin_escape - piton.end_escape 
                    - S "'\"\r[({})]" - digit ) ^ 1 )
-else Word = Q ( ( ( 1 - space ) - S "'\"\r[({})]" - digit ) ^ 1 )
+else 
+  Word = Q ( ( 1 - space - S "'\"\r[({})]" - digit ) ^ 1 )
 end
 %    \end{macrocode}
 %
@@ -5128,6 +5186,7 @@ local VisualSpace = space * Lc "\\l_@@_space_tl"
 % \paragraph{Several tools for the construction of the main LPEG}
 %
 %    \begin{macrocode}
+local LPEG0 = { }
 local LPEG1 = { }
 local LPEG2 = { }
 local LPEG_cleaner = { }
@@ -5145,7 +5204,7 @@ local function Compute_braces ( lpeg_string ) return
     P { "E" ,
          E = 
              (
-               P "{" * V "E" * P "}" 
+               "{" * V "E" * "}" 
                + 
                lpeg_string
                + 
@@ -5173,10 +5232,10 @@ end
 % \bigskip
 %    \begin{macrocode}
 local function Compute_LPEG_cleaner ( lang , braces ) return 
-  Ct ( ( piton.ListCommands * P "{" 
+  Ct ( ( piton.ListCommands * "{" 
           * (  braces 
               / ( function ( s ) return LPEG_cleaner[lang] : match ( s ) end ) )
-          * P "}" 
+          * "}" 
          + EscapeClean
          +  C ( P ( 1 ) )
         ) ^ 0 ) / table.concat 
@@ -5217,9 +5276,9 @@ BeamerBeginEnvironments =
       L 
         ( 
           P "\\begin{" * BeamerNamesEnvironments * "}"
-          * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1
+          * ( "<" * ( 1 - P ">" ) ^ 0 * ">" ) ^ -1
         )
-      * P "\r" 
+      * "\r" 
     ) ^ 0 
 %    \end{macrocode}
 %
@@ -5227,8 +5286,8 @@ BeamerBeginEnvironments =
 %    \begin{macrocode}
 BeamerEndEnvironments = 
     ( space ^ 0 * 
-      L ( P "\\end{" * BeamerNamesEnvironments * P "}" ) 
-      * P "\r" 
+      L ( P "\\end{" * BeamerNamesEnvironments * "}" ) 
+      * "\r" 
     ) ^ 0 
 %    \end{macrocode}
 %
@@ -5243,18 +5302,18 @@ local function Compute_Beamer ( lang , braces )
 % \bigskip
 % We will compute in |lpeg| the \textsc{lpeg} that we will return.
 %    \begin{macrocode}
-  local lpeg = L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) 
+  local lpeg = L ( P "\\pause" * ( "[" * ( 1 - P "]" ) ^ 0 * "]" ) ^ -1 ) 
   lpeg = lpeg + 
       Ct ( Cc "Open" 
             * C ( ( P "\\uncover" + "\\only" + "\\alert" + "\\visible"
                     + "\\invisible" + "\\action" ) 
-                  * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1 
+                  * ( "<" * ( 1 - P ">" ) ^ 0 * ">" ) ^ -1 
                   * P "{" 
                 ) 
             * Cc "}" 
          ) 
        * ( braces / ( function ( s ) return LPEG1[lang] : match ( s ) end ) )
-       * P "}" 
+       * "}" 
        * Ct ( Cc "Close" ) 
 %    \end{macrocode}
 % 
@@ -5264,7 +5323,7 @@ local function Compute_Beamer ( lang , braces )
 % brackets) is mandatory. 
 %    \begin{macrocode}
   lpeg = lpeg +
-    L ( P "\\alt" * P "<" * ( 1 - P ">" ) ^ 0 * P ">" * P "{" )
+    L ( P "\\alt" * "<" * ( 1 - P ">" ) ^ 0 * ">" * "{" )
      * K ( 'ParseAgain.noCR' , braces ) 
      * L ( P "}{" )
      * K ( 'ParseAgain.noCR' , braces ) 
@@ -5275,7 +5334,7 @@ local function Compute_Beamer ( lang , braces )
 % For |\\temporal|, the specification of the overlays (between angular brackets) is mandatory.
 %    \begin{macrocode}
   lpeg = lpeg +
-      L ( ( P "\\temporal" ) * P "<" * ( 1 - P ">" ) ^ 0 * P ">" * P "{" )
+      L ( ( P "\\temporal" ) * "<" * ( 1 - P ">" ) ^ 0 * ">" * "{" )
       * K ( 'ParseAgain.noCR' , braces ) 
       * L ( P "}{" )
       * K ( 'ParseAgain.noCR' , braces ) 
@@ -5292,7 +5351,7 @@ local function Compute_Beamer ( lang , braces )
         Ct ( Cc "Open" 
              * C ( 
                     P ( "\\begin{" .. x .. "}" )
-                    * ( P "<" * ( 1 - P ">") ^ 0 * P ">" ) ^ -1 
+                    * ( "<" * ( 1 - P ">") ^ 0 * ">" ) ^ -1 
                   ) 
              * Cc ( "\\end{" .. x ..  "}" )
             ) 
@@ -5569,9 +5628,9 @@ local FromImport =
 local PercentInterpol =  
   K ( 'String.Interpol' , 
       P "%" 
-      * ( P "(" * alphanum ^ 1 * P ")" ) ^ -1 
+      * ( "(" * alphanum ^ 1 * ")" ) ^ -1 
       * ( S "-#0 +" ) ^ 0 
-      * ( digit ^ 1 + P "*" ) ^ -1 
+      * ( digit ^ 1 + "*" ) ^ -1 
       * ( "." * ( digit ^ 1 + "*" ) ) ^ -1 
       * ( S "HlL" ) ^ -1
       * S "sdfFeExXorgiGauc%" 
@@ -5789,24 +5848,20 @@ local expression =
 % \piton{def MyFunction(a,b,x=10,n:int): return n}
 % \end{center}
 % the \textsc{lpeg} |Params| will be used to catch the chunk\enskip |a,b,x=10,n:int|.
-% 
-% Or course, a |Params| is simply a comma-separated list of |Param|, and that's
-% why we define first the \textsc{lpeg} |Param|.
 %
 % \medskip
 %    \begin{macrocode}
-local Param = 
-  SkipSpace * ( Identifier + Q "*args" + Q "**kwargs" ) * SkipSpace
-   * ( 
-         K ( 'InitialValues' , "=" * expression )
-       + Q ":" * SkipSpace * K ( 'Name.Type' , letter ^ 1  ) 
-     ) ^ -1
+local Params = 
+  P { "E" , 
+       E = ( V "F" * ( Q "," * V "F" ) ^ 0 ) ^ -1 ,
+       F = SkipSpace * ( Identifier + Q "*args" + Q "**kwargs" ) * SkipSpace
+           * ( 
+                 K ( 'InitialValues' , "=" * expression )
+               + Q ":" * SkipSpace * K ( 'Name.Type' , letter ^ 1 ) 
+             ) ^ -1
+    }
 %    \end{macrocode}
 % 
-% \medskip
-%    \begin{macrocode}
-local Params = ( Param * ( Q "," * Param ) ^ 0 ) ^ -1
-%    \end{macrocode}
 % 
 % \bigskip
 % The following \textsc{lpeg} |DefFunction| catches a keyword |def| and the
@@ -5829,7 +5884,7 @@ local DefFunction =
 % \pkg{piton}). We could avoid that kind of trick by using a non-terminal of a
 % grammar but we have probably here a better legibility.
 %    \begin{macrocode}
-  * K ( 'ParseAgain' , ( 1 - S ":\r" ) ^ 0 ) 
+  * K ( 'ParseAgain.noCR' , ( 1 - S ":\r" ) ^ 0 ) 
   * Q ":" 
   * ( SkipSpace
       * ( EOL + CommentLaTeX + Comment ) -- in all cases, that contains an EOL
@@ -6942,16 +6997,15 @@ end
 % value of~$n$.
 %    \begin{macrocode}
 local function gobble ( n , code )
-  if n==0 
+  if n == 0 
   then return code
-  else 
-       return ( Ct ( 
-                     ( 1 - P "\r" ) ^ (-n) * C ( ( 1 - P "\r" ) ^ 0 ) 
-                       * ( C "\r" 
-                       * ( 1 - P "\r" ) ^ (-n)
-                       * C ( ( 1 - P "\r" ) ^ 0 )
-                      ) ^ 0 
-                   ) / table.concat ) : match ( code ) 
+  else return 
+       ( Ct ( 
+              ( 1 - P "\r" ) ^ (-n) * C ( ( 1 - P "\r" ) ^ 0 ) 
+                * ( C "\r" * ( 1 - P "\r" ) ^ (-n) * C ( ( 1 - P "\r" ) ^ 0 )
+            ) ^ 0 ) 
+         / table.concat 
+       ) : match ( code ) 
   end
 end
 %    \end{macrocode}
@@ -7208,22 +7262,73 @@ function piton.new_language ( lang , definition )
 % now in the Lua table |def_table|. We will use it several times.
 %
 % \medskip
+% The following \textsc{lpeg} will be used to extract arguments in the values of
+% the keys (|morekeywords|, |morecomment|, |morestring|, etc.).
+%    \begin{macrocode}
+  local tex_braced_arg = "{" * C ( ( 1 - P "}" ) ^ 0 ) * "}" 
+  local tex_arg = tex_braced_arg + C ( 1 ) 
+  local tex_option_arg =  "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" + Cc ( nil ) 
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+  local args_for_morekeywords 
+    = "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" 
+       * space ^ 0 
+       * tex_option_arg
+       * space ^ 0
+       * tex_arg
+       * space ^ 0
+       * ( tex_braced_arg + Cc ( nil ) ) 
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+  local args_for_moredelims
+    = ( C ( P "*" ^ -2 ) + Cc ( nil ) ) * space ^ 0 
+      * args_for_morekeywords
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+  local args_for_morecomment
+    = "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" 
+       * space ^ 0 
+       * tex_option_arg 
+       * space ^ 0
+       * C ( P ( 1 ) ^ 0 * -1 )
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+  local args_for_tag 
+    = ( P "*" ^ -2 ) 
+       * space ^ 0
+       * ( "[" * ( 1 - P "]" ) ^ 0 * "]" ) ^ 0 
+       * space ^ 0
+       * tex_arg
+       * space ^ 0
+       * tex_arg
+%    \end{macrocode}
+%
+%
 % \bigskip
 % We scan the definition of the language (i.e. the table |def_table|) in order
 % to detect the potential key |sensitive|. Indeed, we have to catch that key
 % before the treatment of the keywords of the language. We will also look for
-% the potential keys |alsodigit| and |alsoletter|. 
+% the potential keys |alsodigit|, |alsoletter| and |tag|. 
 %    \begin{macrocode}
   local sensitive = true 
-  for _ , x in ipairs ( def_table )
-  do if x[1] == "sensitive"
-     then if x[2] == nil or ( P "true" ) : match ( x[2] ) 
-          then sensitive = true 
-          else if ( P "false" ) : match ( x[2] ) then sensitive = false end
-          end
-     end
-     if x[1] == "alsodigit" then x[2] : gsub ( "." , add_to_digit ) end 
-     if x[1] == "alsoletter" then x[2] : gsub ( "." , add_to_letter ) end 
+  local left_tag , right_tag 
+  for _ , x in ipairs ( def_table ) do
+    if x[1] == "sensitive" then 
+      if x[2] == nil or ( P "true" ) : match ( x[2] ) then 
+        sensitive = true 
+      else 
+        if ( P "false" + P "f" ) : match ( x[2] ) then sensitive = false end
+      end
+    end
+    if x[1] == "alsodigit" then x[2] : gsub ( "." , add_to_digit ) end 
+    if x[1] == "alsoletter" then x[2] : gsub ( "." , add_to_letter ) end 
+    if x[1] == "tag" then
+      left_tag , right_tag = args_for_tag : match ( x[2] ) 
+    end 
   end
 %    \end{macrocode}
 % Now, the \textsc{lpeg} for the numbers. Of course, it uses |digit| previously
@@ -7250,11 +7355,6 @@ function piton.new_language ( lang , definition )
 % Now, we scan the definition of the language (i.e. the table |def_table|) for
 % the keywords.
 %
-% The following LPEG catches the optional argument (between square brackets) in
-% first position.
-%    \begin{macrocode}
-  local option = "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" 
-%    \end{macrocode}
 %
 % The following LPEG does \emph{not} catch the optional argument between square
 % brackets in first position.
@@ -7280,28 +7380,44 @@ function piton.new_language ( lang , definition )
   end 
   local Keyword = P ( false )  
 %    \end{macrocode}
-% Now, we actually treat all the keywords.
+% Now, we actually treat all the keywords and also the key |moredirectives|.
 %    \begin{macrocode}
   for _ , x in ipairs ( def_table )
-  do if x[1] == "morekeywords" or x[1] == "otherkeywords" then
-        local keywords = P ( false ) 
-        for _ , word in ipairs ( split_clist : match ( x[2] ) )
-        do if sensitive 
+  do if x[1] == "morekeywords" 
+        or x[1] == "otherkeywords" 
+        or x[1] == "moredirectives" 
+        or x[1] == "moretexcs"
+     then
+        local keywords = P ( false )
+%    \end{macrocode}
+%    \begin{macrocode}
+        local style = "\\PitonStyle{Keyword}"
+        if x[1] == "moredirectives" then style = "\\PitonStyle{directive}" end
+        style =  tex_option_arg : match ( x[2] ) or style
+        local n = tonumber (style )
+        if n then 
+         if n > 1 then style = "\\PitonStyle{Keyword" .. style .. "}" end
+        end 
+%    \end{macrocode}
+%    \begin{macrocode}
+        for _ , word in ipairs ( split_clist : match ( x[2] ) ) do
+          if x[1] == "moretexcs" then
+            keywords = Q ( "\\" .. word ) + keywords
+          else 
+            if sensitive 
 %    \end{macrocode}
 % The documentation of \pkg{lstlistings} specifies that, for the key
 % |otherkeywords|, if a keyword is a prefix of another keyword, then the prefix
 % must appear first. However, for the \text{lpeg}, it's rather the contrary.
 % That's why, here, we add the new element \emph{on the left}.
 %    \begin{macrocode}
-           then keywords = Q ( word  ) + keywords
-           else keywords = keyword_to_lpeg ( word ) + keywords
-           end 
+            then keywords = Q ( word  ) + keywords
+            else keywords = keyword_to_lpeg ( word ) + keywords
+            end
+          end 
         end
         Keyword = Keyword + 
-           Lc ( "{" 
-                 ..  ( option : match ( x[2] ) or "\\PitonStyle{Keyword}" ) 
-                 .. "{" )
-           * keywords * Lc "}}" 
+           Lc ( "{" .. style .. "{" ) * keywords * Lc "}}" 
      end 
      if x[1] == "keywordsprefix" then
        local prefix = ( ( C ( 1 - P " " ) ^ 1 ) * P " " ^ 0 ) : match ( x[2] ) 
@@ -7310,50 +7426,57 @@ function piton.new_language ( lang , definition )
   end    
 %    \end{macrocode}
 %
+% 
 % \bigskip
 % Now, we scan the definition of the language (i.e. the table |def_table|) for
 % the strings.
 %    \begin{macrocode}
   local long_string  = P ( false )
   local LongString = P (false ) 
-  local args = "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" 
-               * space ^ 0 
-               * ( "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" + Cc ( nil ) ) 
-               * space ^ 0 
-               * ( "{" * C ( ( 1 - P "}" ) ^ 0 ) * "}" + C ( 1 ) ) 
   local central_pattern = P ( false ) 
-  for _ , x in ipairs ( def_table )
-  do if x[1] == "morestring" then
-       arg1 , arg2 , arg3 = args : match ( x[2] ) 
-       arg2 = arg2 or "\\PitonStyle{String.Long}" 
-       if arg1 == "b" then 
-         central_pattern = Q ( ( P ( "\\" .. arg3 )  + 1 - S ( " \r" .. arg3 ) ) ^ 1 ) 
-       end
-       if arg1 == "d" then 
-         central_pattern = Q ( ( P ( arg3 .. arg3 )  + 1 - S ( " \r" .. arg3 ) ) ^ 1 ) 
-       end
-       if arg1 == "bd" then 
-         central_pattern = 
-           Q ( ( P ( arg3 .. arg3 ) + P ( "\\" .. arg3 ) + 1 - S ( " \r" .. arg3 ) ) ^ 1 ) 
-       end
-       if arg1 == "m" then 
-         central_pattern =  Q ( ( P ( arg3 .. arg3 ) + 1 - S ( " \r" .. arg3 ) ) ^ 1 ) 
-       end
-       if arg1 == "m" 
-       then prefix = P ( false ) 
-       else prefix = lpeg.B ( 1 - letter - ")" - "]" ) 
-       end
+  for _ , x in ipairs ( def_table ) do
+    if x[1] == "morestring" then
+      arg1 , arg2 , arg3 , arg4 = args_for_morekeywords : match ( x[2] ) 
+      arg2 = arg2 or "\\PitonStyle{String.Long}"
+      if arg1 == "s" then
+        long_string =
+          Q ( arg3 ) 
+          * ( Q ( ( 1 - P ( arg4 ) - S "$\r" ) ^ 1 ) -- $
+              + EOL 
+            ) ^ 0  
+          * Q ( arg4 ) 
+      else  
+        central_pattern = 1 - S ( " \r" .. arg3 ) 
+        if arg1 : match "b" then 
+          central_pattern = P ( "\\" .. arg3 )  + central_pattern
+        end
+%    \end{macrocode}
+% In fact, the specifier |d| is point-less: when it is not in force, it's still
+% possible to double the delimiter with a correct behaviour of \pkg{piton}
+% since, in that case, \pkg{piton} will compose \emph{two} contiguous strings...
+%    \begin{macrocode}
+        if arg1 : match "d" or arg1 == "m" then 
+          central_pattern = P ( arg3 .. arg3 )  + central_pattern
+        end
+        if arg1 == "m" 
+        then prefix = P ( false ) 
+        else prefix = lpeg.B ( 1 - letter - ")" - "]" ) 
+        end
 %    \end{macrocode}
 % First, we create |long_string| because we need that \textsc{lpeg} in the
 % nested comments.
 %    \begin{macrocode}
-       long_string = long_string +
-         prefix * ( Q ( arg3 ) * ( VisualSpace + central_pattern + EOL ) ^ 0 * Q ( arg3 ) )
-       LongString = LongString +
-          Ct ( Cc "Open" * Cc ( "{" ..  arg2 .. "{" ) * Cc "}}" )
-          * long_string 
-          * Ct ( Cc "Close" ) 
-     end 
+        long_string = long_string +
+           prefix 
+           * Q ( arg3 ) 
+           * ( VisualSpace + Q ( central_pattern ^ 1 ) + EOL ) ^ 0 
+           * Q ( arg3 ) 
+      end
+      LongString = LongString +
+         Ct ( Cc "Open" * Cc ( "{" ..  arg2 .. "{" ) * Cc "}}" )
+         * long_string 
+         * Ct ( Cc "Close" ) 
+    end 
   end
 
   local braces = Compute_braces ( String ) 
@@ -7365,70 +7488,122 @@ function piton.new_language ( lang , definition )
 %    \end{macrocode}
 %
 % \bigskip
-% Now, we deal with the comments.
+% Now, we deal with the comments and the delims.
 %    \begin{macrocode}
-  local Comment = P ( false ) 
+  local CommentDelim = P ( false ) 
 
-  local args = "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" 
-               * space ^ 0 
-               * ( "[" * C ( ( 1 - P "]" ) ^ 0 ) * "]" + Cc ( nil ) ) 
-               * space ^ 0
-               * ( "{" * C ( ( 1 - P "}" ) ^ 0 ) * "}" + C ( 1 ) ) 
-               * space ^ 0
-               * ( "{" * C ( ( 1 - P "}" ) ^ 0 ) * "}" + Cc ( nil ) ) 
-
-  for _ , x in ipairs ( def_table )
-  do if x[1] == "morecomment"
-     then local arg1 , arg2 , arg3 , arg4 = args : match ( x[2] ) 
-          arg2 = arg2 or "\\PitonStyle{Comment}"
-          if arg1 == "l" then 
-            if arg3 == [[\#]] then arg3 = "#" end -- mandatory
-            Comment = Comment + 
-                Ct ( Cc "Open" 
-                     * Cc ( "{" .. arg2 .. "{" ) * Cc "}}" ) 
-                     *  Q ( arg3 ) 
-                     * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 -- $
-                * Ct ( Cc "Close" ) 
-                * ( EOL + -1 )
-           end 
-           if arg1 == "s" then 
-             Comment = Comment +
-                 Ct ( Cc "Open" * Cc ( "{" .. arg2 .. "{" ) * Cc "}}" ) 
-                 * Q ( arg3 ) 
-                 * ( 
-                     CommentMath 
-                     + Q ( ( 1 - P ( arg4 ) - S "$\r" ) ^ 1 ) -- $
-                     + EOL 
-                   ) ^ 0  
-                 * Q ( arg4 ) 
-                 * Ct ( Cc "Close" ) 
-           end
-           if arg1 == "n" then 
-             Comment = Comment +
-               Ct ( Cc "Open" * Cc ( "{" .. arg2 .. "{" ) * Cc "}}" ) 
-                * P { "A" ,
-                     A = Q ( arg3 ) 
-                         * ( V "A" 
-                             + Q ( ( 1 - P ( arg3 ) - P ( arg4 ) 
-                                     - S "\r$\"" ) ^ 1 ) -- $
-                             + long_string
-                             +   "$" -- $
-                                 * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) --$
-                                 * "$" -- $
-                             + EOL
-                           ) ^ 0 
-                         * Q ( arg4 )
-                    }  
-               * Ct ( Cc "Close" ) 
-           end
+  for _ , x in ipairs ( def_table ) do
+    if x[1] == "morecomment" then 
+      local arg1 , arg2 , other_args = args_for_morecomment : match ( x[2] ) 
+      arg2 = arg2 or "\\PitonStyle{Comment}"
+%    \end{macrocode}
+% If the letter |i| is present in the first argument (eg: 
+% |morecomment = [si]{(*}{*)}|, then the corresponding comments are discarded. 
+%    \begin{macrocode}
+      if arg1 : match "i" then arg2 = "\\PitonStyle{Discard}" end
+      if arg1 : match "l" then 
+        local arg3 = ( tex_braced_arg + C ( P ( 1 ) ^ 0 * -1 ) )
+                     : match ( other_args ) 
+        if arg3 == [[\#]] then arg3 = "#" end -- mandatory
+        CommentDelim = CommentDelim + 
+            Ct ( Cc "Open" 
+                 * Cc ( "{" .. arg2 .. "{" ) * Cc "}}" ) 
+                 *  Q ( arg3 ) 
+                 * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 -- $
+            * Ct ( Cc "Close" ) 
+            * ( EOL + -1 )
+      else 
+        local arg3 , arg4 = 
+          ( tex_arg * space ^ 0 * tex_arg ) : match ( other_args )
+        if arg1 : match "s" then 
+          CommentDelim = CommentDelim +
+              Ct ( Cc "Open" * Cc ( "{" .. arg2 .. "{" ) * Cc "}}" ) 
+              * Q ( arg3 ) 
+              * ( 
+                  CommentMath 
+                  + Q ( ( 1 - P ( arg4 ) - S "$\r" ) ^ 1 ) -- $
+                  + EOL 
+                ) ^ 0  
+              * Q ( arg4 ) 
+              * Ct ( Cc "Close" ) 
+        end
+        if arg1 : match "n" then 
+          CommentDelim = CommentDelim +
+            Ct ( Cc "Open" * Cc ( "{" .. arg2 .. "{" ) * Cc "}}" ) 
+             * P { "A" ,
+                  A = Q ( arg3 ) 
+                      * ( V "A" 
+                          + Q ( ( 1 - P ( arg3 ) - P ( arg4 ) 
+                                  - S "\r$\"" ) ^ 1 ) -- $
+                          + long_string
+                          +   "$" -- $
+                              * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) --$
+                              * "$" -- $
+                          + EOL
+                        ) ^ 0 
+                      * Q ( arg4 )
+                 }  
+            * Ct ( Cc "Close" ) 
+        end
+      end
+    end 
+%    \end{macrocode}
+% For the keys |moredelim|, we have to add another argument in first position,
+% equal to |*| or |**|.
+%    \begin{macrocode}
+    if x[1] == "moredelim" then 
+      local arg1 , arg2 , arg3 , arg4 , arg5 
+        = args_for_moredelims : match ( x[2] )  
+      local MyFun = Q 
+      if arg1 == "*" or arg1 == "**" then
+        MyFun = function ( x ) return K ( 'ParseAgain.noCR' , x ) end
+      end
+      local left_delim 
+      if arg2 : match "i" then
+        left_delim = P ( arg4 ) 
+      else 
+        left_delim = Q ( arg4 )
       end 
+      if arg2 : match "l" then 
+        CommentDelim = CommentDelim +
+            Ct ( Cc "Open" * Cc ( "{" .. arg3 .. "{" ) * Cc "}}" ) 
+            * left_delim
+            * ( MyFun ( ( 1 - P "\r" ) ^ 1 ) ) ^ 0  
+            * Ct ( Cc "Close" ) 
+            * ( EOL + -1 ) 
+      end
+      if arg2 : match "s" then 
+        local right_delim 
+        if arg2 : match "i" then
+          right_delim = P ( arg5 )
+        else 
+          right_delim = Q ( arg5 )
+        end 
+        CommentDelim = CommentDelim +
+            Ct ( Cc "Open" * Cc ( "{" .. arg3 .. "{" ) * Cc "}}" ) 
+            * left_delim
+            * ( MyFun ( ( 1 - P ( arg5 ) - "\r" ) ^ 1 ) + EOL ) ^ 0  
+            * right_delim
+            * Ct ( Cc "Close" ) 
+      end
+    end 
   end 
 
   local Delim = Q ( S "{[()]}" )
-  local Punct = Q ( S ",:;!\\'\"" )
-
+  local Punct = Q ( S "=,:;!\\'\"" )
+%    \end{macrocode}
+%
+%
+%    \begin{macrocode}
+%    \end{macrocode}
+%
+%
+%    \begin{macrocode}
   local Main = 
          space ^ 1 * -1
+%    \end{macrocode}
+% The spaces at the end of the lines are discarded.
+%    \begin{macrocode}
        + space ^ 0 * EOL 
        + Space 
        + Tab
@@ -7436,18 +7611,33 @@ function piton.new_language ( lang , definition )
        + CommentLaTeX
        + Beamer
        + DetectedCommands
-       + Comment 
+       + CommentDelim
        + Delim
        + LongString
-        -- should maybe be after the following line!
        + Keyword * ( Space + Punct + Delim + EOL + -1 ) 
        + Punct 
        + K ( 'Identifier' , letter * alphanum ^ 0 )
        + Number
        + Word
-
+%    \end{macrocode}
+%
+% The \textsc{lpeg} |LPEG1[lang]| is used to reformat small elements, for
+% example the arguments of the ``detected commands''.
+%   \begin{macrocode}
   LPEG1[lang] = Main ^ 0 
-
+%    \end{macrocode}
+%
+%
+% \bigskip
+% If the key |tag| has been used, then |left_tag| (and also |right_tag|) is non nil.
+%    \begin{macrocode}
+  if left_tag then
+  end 
+%    \end{macrocode}
+% 
+% 
+% The \textsc{lpeg} |LPEG2[lang]| is used to format general chunks of code.
+%    \begin{macrocode}
   LPEG2[lang] = 
     Ct (
          ( space ^ 0 * P "\r" ) ^ -1 
@@ -7458,11 +7648,64 @@ function piton.new_language ( lang , definition )
          * -1 
          * Lc '\\@@_end_line:' 
        )
-
+%    \end{macrocode}
+%
+% 
+%    \begin{macrocode}
+  if left_tag then
+    local Tag = Q ( left_tag * other ^ 0 ) 
+                * ( ( ( 1 - P ( right_tag ) ) ^ 0 )
+                  / ( function ( x ) return LPEG0[lang] : match ( x ) end ) )
+                * Q ( right_tag ) 
+    MainWithoutTag
+            = space ^ 1 * -1
+            + space ^ 0 * EOL 
+            + Space 
+            + Tab
+            + Escape + EscapeMath 
+            + CommentLaTeX
+            + Beamer
+            + DetectedCommands
+            + CommentDelim
+            + Delim
+            + LongString
+            + Keyword * ( Space + Punct + Delim + EOL + -1 ) 
+            + Punct 
+            + K ( 'Identifier' , letter * alphanum ^ 0 )
+            + Number
+            + Word 
+    LPEG0[lang] = MainWithoutTag ^ 0 
+    MainWithTag 
+            = space ^ 1 * -1
+            + space ^ 0 * EOL 
+            + Space 
+            + Tab
+            + Escape + EscapeMath 
+            + CommentLaTeX
+            + Beamer
+            + DetectedCommands
+            + CommentDelim
+            + Tag 
+            + Delim
+            + Punct 
+            + K ( 'Identifier' , letter * alphanum ^ 0 )
+            + Word 
+    LPEG1[lang] = MainWithTag ^ 0 
+    LPEG2[lang] = 
+      Ct (
+           ( space ^ 0 * P "\r" ) ^ -1 
+           * BeamerBeginEnvironments 
+           * Lc '\\@@_begin_line:'
+           * SpaceIndentation ^ 0 
+           * LPEG1[lang]
+           * -1 
+           * Lc '\\@@_end_line:' 
+         )
+  end
 end
 %</LUA>
 %    \end{macrocode}
-% 
+%
 %
 % 
 % \vspace{1cm}
-- 
cgit v1.2.3

