diff options
author | Karl Berry <karl@freefriends.org> | 2023-04-04 20:12:45 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2023-04-04 20:12:45 +0000 |
commit | 261243b388f0561e9089b1eafed6b2e32a7c3987 (patch) | |
tree | ebafc1e6c768dc757f54e3ad6c4780e0e8ee49ae /Master/texmf-dist/source/lualatex | |
parent | 9892241bb3eac84c80f41c5fa7d6996af248a38d (diff) |
piton (4apr23)
git-svn-id: svn://tug.org/texlive/trunk@66763 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/lualatex')
-rw-r--r-- | Master/texmf-dist/source/lualatex/piton/piton.dtx | 1161 |
1 files changed, 690 insertions, 471 deletions
diff --git a/Master/texmf-dist/source/lualatex/piton/piton.dtx b/Master/texmf-dist/source/lualatex/piton/piton.dtx index 126c19dc10b..8d8caee54fd 100644 --- a/Master/texmf-dist/source/lualatex/piton/piton.dtx +++ b/Master/texmf-dist/source/lualatex/piton/piton.dtx @@ -15,8 +15,8 @@ % % \fi % \iffalse -\def\myfileversion{1.4} -\def\myfiledate{2023/02/14} +\def\myfileversion{1.5} +\def\myfiledate{2023/04/04} % % %<*batchfile> @@ -125,7 +125,6 @@ version 2005/12/01 or later. % % % \bigskip -% % The package \pkg{piton} is entirely contained in the file % |piton.sty|. This file may be put in the current directory or in a % |texmf| tree. However, the best is to install \pkg{piton} with a TeX @@ -193,29 +192,33 @@ version 2005/12/01 or later. % When its argument is given between curly braces, the command |\piton| does not % take its argument in verbatim mode. In particular: % \begin{itemize} -% \item several consecutive spaces will be replaced by only one space; -% \item it's not possible to use |%| inside the argument; -% \item the braces must be appear by pairs correctly nested; -% \item the LaTeX commands (those beginning with a backslash |\| but also the -% active characters) are fully expanded (but not executed). -% \end{itemize} +% \item several consecutive spaces will be replaced by only one space, +% +% {\color{cyan} but the command |\|␣ is provided to force the insertion of a space}; % -% An escaping mechanism is provided: the commands |\\|, |\%|, |\{| and |\}| -% insert the corresponding characters |\|, |%|, |{| and |}|. The last two -% commands are necessary only if one need to insert braces which are not -% balanced. +% \item it's not possible to use |%| inside the argument, +% +% {\color{cyan} but the command |\%| is provided to insert a |%|}; +% +% \item the braces must be appear by pairs correctly nested +% +% {\color{cyan} but the commands |\{| and |\}| are also provided for individual braces}; +% +% \item the LaTeX commands\footnote{That concerns the commands beginning with a +% backslash but also the active characters.} are fully expanded and not +% executed, +% +% {\color{cyan} so it's possible to use |\\| to insert a backslash}. +% \end{itemize} % -% \smallskip -% The command |\|␣ inserts a space. It may be used in order to insert several -% consecutive spaces. % -% \smallskip % The other characters (including |#|, |^|, |_|, |&|, |$| and |@|) % must be inserted without backslash. % -% Examples: -% -%\begin{tabular}{>{\color{gray}}l@{\hspace*{1cm}}l} +% \bigskip +%\begin{tabular}{>{\color{gray}}w{l}{75mm}@{\hspace*{1cm}}l} +% \omit Examples : \hfil \\ +% \noalign{\vskip1mm} % \verb|\piton{MyString = '\\n'}| & % \piton{MyString = '\\n'} \\ % \verb|\piton{def even(n): return n\%2==0}| & @@ -228,7 +231,7 @@ version 2005/12/01 or later. % \piton{MyDict = {'a': 3, 'b': 4 }} % \end{tabular} % -% +% \bigskip % It's possible to use the command |\piton| in the arguments of a % LaTeX command.\footnote{For example, it's possible to use the command % \texttt{\textbackslash piton} in a footnote. Example : @@ -243,9 +246,10 @@ version 2005/12/01 or later. % command. % % \medskip -% Examples: % -% \begin{tabular}{>{\color{gray}}l@{\hspace*{1cm}}l} +% \begin{tabular}{>{\color{gray}}w{l}{75mm}@{\hspace*{1cm}}l} +% \omit Examples : \hfil \\ +% \noalign{\vskip1mm} % \verb!\piton|MyString = '\n'|! & % \piton|MyString = '\n'| \\ % \verb|\piton!def even(n): return n%2==0!| & @@ -299,7 +303,13 @@ version 2005/12/01 or later. % \item With the key \Definition{all-line-numbers}, \emph{all} the lines are numbered, % including the empty ones. % -% \item With the key \Definition{resume} the counter of lines is not set to zero +% \item \colorbox{yellow!50}{\bfseries{New 1.5}}\par\nobreak +% +% The key \Definition{numbers-sep} is the horizontal distance between the +% numbers of lines (inserted by |line-numbers| of |all-line-numbers|) and the +% beginning of the lines of code. The initial value is 0.7~em. +% +% \item With the key \Definition{resume}, the counter of lines is not set to zero % at the beginning of each environment |{Piton}| or use of |\PitonInputFile| as % it is otherwise. That allows a numbering of the lines across several % environments. @@ -340,13 +350,14 @@ version 2005/12/01 or later. % 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 +% \texttt{\textbackslash setmonofont} of the package \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). +% |break-lines|\footnote{cf. \ref{line-breaks} p.~\pageref{line-breaks}} is in +% force). % \end{itemize} % % \bigskip @@ -551,7 +562,7 @@ version 2005/12/01 or later. % {\end{tcolorbox}} % \end{verbatim} % -\bigskip +% \bigskip % With this new environment |{Python}|, it's possible to write: % % \begin{Verbatim} @@ -597,7 +608,7 @@ version 2005/12/01 or later. % \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 +% keywords and the built-in functions won't be affected, even if their name is % in the list |\textsl{\ttfamily names}|. % % \begin{Verbatim} @@ -882,6 +893,16 @@ version 2005/12/01 or later. % % \label{beamer} % +% \emph{First remark}\par\nobreak +% Since the environment |{Piton}| catches its body with a verbatim mode, +% it's necessary to use the environments |{Piton}| within environments |{frame}| +% of Beamer protected by the key |fragile|.\footnote{Remind that for an +% environment \texttt{\{frame\}} of Beamer using the key |fragile|, the +% instruction \texttt{\textbackslash end\{frame\}} must be alone on a single +% line (except for any leading whitespace).} +% +% +% \bigskip % When the package \pkg{piton} is used within the class % \cls{beamer}\footnote{The extension \pkg{piton} detects the class \cls{beamer} % but, if needed, it's also possible to activate that mechanism with the key @@ -927,26 +948,11 @@ version 2005/12/01 or later. % \end{itemize} % \medskip -% However, there is two restrictions for the content of the mandatory arguments -% of these commands. -% \begin{itemize} -% \item In the mandatory arguments of these commands, the braces must be -% balanced. However, the braces includes in short strings\footnote{The -% short strings of Python are the strings delimited by characters \texttt{'} or -% 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). For multi-lines elements, -% one should consider the corresponding environments (see below). -% \end{itemize} -% -% \medskip -% Remark that, since the environment |{Piton}| catches its body with a verbatim -% mode, it's necessary to use the environments |{Piton}| within environments -% |{frame}| of Beamer protected by the key |fragile|.\footnote{Remind that for -% an environment \texttt{\{frame\}} of Beamer using the key |fragile|, the -% instruction \texttt{\textbackslash end\{frame\}} must be alone on a single -% line (except for any leading whitespace).} +% In the mandatory arguments of these commands, the braces must be balanced. +% However, the braces included in short strings\footnote{The short strings of +% Python are the strings delimited by characters \texttt{'} or the characters +% \texttt{"} and not \texttt{'''} nor \texttt{"""}. In Python, the short strings +% can't extend on several lines.} of Python are not considered. % % \medskip % Here is a complete example of file: @@ -984,7 +990,7 @@ version 2005/12/01 or later. % % However, there is a restriction: these environments must contain only \emph{whole % lines of Python code} in their body. -%% +% %\medskip % Here is an example: % @@ -1076,6 +1082,8 @@ version 2005/12/01 or later. % % \subsubsection{Line breaks} % +% \label{line-breaks} +% % By default, the elements produced by \pkg{piton} can't be broken by an end on % line. However, there are keys to allow such breaks (the possible breaking % points are the spaces, even the spaces in the Python strings). @@ -1089,7 +1097,6 @@ version 2005/12/01 or later. % \item The key |break-lines| is a conjonction of the two previous keys. % \end{itemize} % - % \bigskip % The package \pkg{piton} provides also several keys to control the appearance % on the line breaks allowed by |break-lines-in-Piton|. @@ -1385,7 +1392,7 @@ version 2005/12/01 or later. % If an environment |{Piton}| is used in an environment |{minipage}| of LaTeX, % the notes are composed, of course, at the foot of the environment % |{minipage}|. Recall that such |{minipage}| can't be broken by a page break. - +% % % \begingroup % \fvset{commandchars=\~\&\@,formatcom=\small\color{gray}} @@ -1747,7 +1754,7 @@ version 2005/12/01 or later. % \subsection{The L3 part of the implementation} % % \subsubsection{Declaration of the package} -% \begin{macrocode} +% \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \RequirePackage{l3keys2e} \ProvidesExplPackage @@ -1760,7 +1767,13 @@ version 2005/12/01 or later. % \bigskip % \begin{macrocode} \msg_new:nnn { piton } { LuaLaTeX~mandatory } - { The~package~'piton'~must~be~used~with~LuaLaTeX.\\ It~won't~be~loaded. } + { + LuaLaTeX~is~mandatory.\\ + The~package~'piton'~requires~the~engine~LuaLaTeX.\\ + \str_if_eq:VnT \c_sys_jobname_str { output } + { If~you~use~Overleaf,~you~can~switch~to~LuaLaTeX~in~the~"Menu". \\} + If~you~go~on,~the~package~'piton'~won't~be~loaded. + } \sys_if_engine_luatex:F { \msg_critical:nn { piton } { LuaLaTeX~mandatory } } % \end{macrocode} % @@ -2075,18 +2088,25 @@ version 2005/12/01 or later. % \end{macrocode} % % \medskip -% The following dimension corresponds to the key |left-margin| of -% |\PitonOptions|. +% The following dimension corresponds to the key |left-margin| of |\PitonOptions|. % \begin{macrocode} \dim_new:N \l_@@_left_margin_dim % \end{macrocode} % % \medskip -% The following boolean correspond will be set when the key |left-margin=auto| +% The following boolean will be set when the key |left-margin=auto| % is used. % \begin{macrocode} \bool_new:N \l_@@_left_margin_auto_bool % \end{macrocode} +% +% \medskip +% The following dimension corresponds to the key |numbers-sep| of +% |\PitonOptions|. +% \begin{macrocode} +\dim_new:N \l_@@_numbers_sep_dim +\dim_set:Nn \l_@@_numbers_sep_dim { 0.7 em } +% \end{macrocode} % % \medskip % The tabulators will be replaced by the content of the following token list. @@ -2170,7 +2190,17 @@ version 2005/12/01 or later. } % \end{macrocode} % -% +% +% \bigskip +% The following commands are a easy way to insert safely braces (|{| and |}|) in +% the TeX flow. +% \begin{macrocode} +\cs_new_protected:Npn \@@_open_brace: + { \directlua { piton.open_brace() } } +\cs_new_protected:Npn \@@_close_brace: + { \directlua { piton.close_brace() } } +% \end{macrocode} +% % \bigskip % The following token list will be evaluated at the beginning of % |\@@_begin_line:|... |\@@_end_line:| and cleared at the end. It will be used @@ -2191,8 +2221,82 @@ version 2005/12/01 or later. { \clist_set:NV \l_@@_bg_color_clist \l_@@_prompt_bg_color_tl } } % \end{macrocode} +% % +% \bigskip +% You will keep track of the current style for the treatment of EOL (for the +% multi-line syntactic elements). +% \begin{macrocode} +\clist_new:N \g_@@_current_style_clist +\clist_set:Nn \g_@@_current_style_clist { __end } +% \end{macrocode} +% The element |__end| is an arbitrary syntactic marker. +% +% \medskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_close_current_styles: + { + \int_set:Nn \l_tmpa_int { \clist_count:N \g_@@_current_style_clist - 1 } + \exp_args:NV \@@_close_n_styles:n \l_tmpa_int + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_close_n_styles:n #1 + { + \int_compare:nNnT { #1 } > 0 + { + \@@_close_brace: + \@@_close_brace: + \@@_close_n_styles:n { #1 - 1 } + } + } +% \end{macrocode} % +% \begin{macrocode} +\cs_new_protected:Npn \@@_open_current_styles: + { \exp_last_unbraced:NV \@@_open_styles:w \g_@@_current_style_clist , } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_open_styles:w #1 , + { + \tl_if_eq:nnF { #1 } { __end } + { \@@_open_brace: #1 \@@_open_brace: \@@_open_styles:w } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_pop_style: + { + \clist_greverse:N \g_@@_current_style_clist + \clist_gpop:NN \g_@@_current_style_clist \l_tmpa_tl + \clist_gpop:NN \g_@@_current_style_clist \l_tmpa_tl + \clist_gpush:Nn \g_@@_current_style_clist { __end } + \clist_greverse:N \g_@@_current_style_clist + } +% \end{macrocode} +% +% \medskip +% \begin{macrocode} +\cs_new_protected:Npn \@@_push_style:n #1 + { + \clist_greverse:N \g_@@_current_style_clist + \clist_gpop:NN \g_@@_current_style_clist \l_tmpa_tl + \clist_gpush:Nn \g_@@_current_style_clist { #1 } + \clist_gpush:Nn \g_@@_current_style_clist { __end } + \clist_greverse:N \g_@@_current_style_clist + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_push_and_exec:n #1 + { + \@@_push_style:n { #1 } + \@@_open_brace: #1 \@@_open_brace: + } +% \end{macrocode} +% % \bigskip % \subsubsection{Treatment of a line of code} % @@ -2226,8 +2330,8 @@ version 2005/12/01 or later. % \bigskip % In the contents provided by Lua, each line of the Python code will be % surrounded by |\@@_begin_line:| and |\@@_end_line:|. |\@@_begin_line:| is a -% LaTeX that we will define now but |\@@_end_line:| is only a syntactic marker -% that has no definition. +% LaTeX command that we will define now but |\@@_end_line:| is only a syntactic +% marker that has no definition. % % \begin{macrocode} \cs_set_protected:Npn \@@_begin_line: #1 \@@_end_line: @@ -2270,7 +2374,13 @@ version 2005/12/01 or later. \@@_print_number: } \clist_if_empty:NF \l_@@_bg_color_clist - { \skip_horizontal:n { 0.5 em } } + { + \dim_compare:nNnT \l_@@_left_margin_dim = \c_zero_dim + { + \bool_if:NF \l_@@_left_margin_auto_bool + { \skip_horizontal:n { 0.5 em } } + } + } \coffin_typeset:Nnnnn \l_tmpa_coffin T l \c_zero_dim \c_zero_dim } % \end{macrocode} @@ -2448,6 +2558,8 @@ version 2005/12/01 or later. } { \dim_set:Nn \l_@@_left_margin_dim { #1 } } , left-margin .value_required:n = true , + numbers-sep .dim_set:N = \l_@@_numbers_sep_dim , + numbers-sep .value_required:n = true , tab-size .code:n = \@@_set_tab_tl:n { #1 } , tab-size .value_required:n = true , show-spaces .bool_set:N = \l_@@_show_spaces_bool , @@ -2502,7 +2614,7 @@ version 2005/12/01 or later. \hbox_overlap_left:n { { \color { gray } \footnotesize \int_to_arabic:n \g_@@_visual_line_int } - \skip_horizontal:n { 0.4 em } + \skip_horizontal:N \l_@@_numbers_sep_dim } } % \end{macrocode} @@ -2774,7 +2886,8 @@ version 2005/12/01 or later. { \g_@@_visual_line_int + \l_@@_nb_non_empty_lines_int } } } - \dim_set:Nn \l_@@_left_margin_dim { \box_wd:N \l_tmpa_box + 0.5em } + \dim_set:Nn \l_@@_left_margin_dim + { \box_wd:N \l_tmpa_box + \l_@@_numbers_sep_dim + 0.1 em } } % \end{macrocode} % Now, the main job. @@ -2855,7 +2968,7 @@ version 2005/12/01 or later. } } \dim_set:Nn \l_@@_left_margin_dim - { \box_wd:N \l_tmpa_box + 0.5 em } + { \box_wd:N \l_tmpa_box + \l_@@_numbers_sep_dim + 0.1 em } } % \end{macrocode} % Now, the main job. @@ -2963,65 +3076,67 @@ version 2005/12/01 or later. % \begin{macrocode} \keys_define:nn { piton / Styles } { - String.Interpol .tl_set:c = pitonStyle String.Interpol , - String.Interpol .value_required:n = true , - FormattingType .tl_set:c = pitonStyle FormattingType , - FormattingType .value_required:n = true , - Dict.Value .tl_set:c = pitonStyle Dict.Value , - Dict.Value .value_required:n = true , - Name.Decorator .tl_set:c = pitonStyle Name.Decorator , - Name.Decorator .value_required:n = true , - Name.Function .tl_set:c = pitonStyle Name.Function , - Name.Function .value_required:n = true , - Keyword .tl_set:c = pitonStyle Keyword , - Keyword .value_required:n = true , - Keyword.Constant .tl_set:c = pitonStyle Keyword.Constant , - Keyword.constant .value_required:n = true , - String.Doc .tl_set:c = pitonStyle String.Doc , - String.Doc .value_required:n = true , - Interpol.Inside .tl_set:c = pitonStyle Interpol.Inside , - Interpol.Inside .value_required:n = true , - String.Long .tl_set:c = pitonStyle String.Long , - String.Long .value_required:n = true , - String.Short .tl_set:c = pitonStyle String.Short , - String.Short .value_required:n = true , - String .meta:n = { String.Long = #1 , String.Short = #1 } , - Comment.Math .tl_set:c = pitonStyle Comment.Math , - Comment.Math .default:n = \@@_math_scantokens:n , - Comment.Math .initial:n = , - Comment .tl_set:c = pitonStyle Comment , - Comment .value_required:n = true , - InitialValues .tl_set:c = pitonStyle InitialValues , - InitialValues .value_required:n = true , - Number .tl_set:c = pitonStyle Number , - Number .value_required:n = true , - Name.Namespace .tl_set:c = pitonStyle Name.Namespace , - Name.Namespace .value_required:n = true , - Name.Class .tl_set:c = pitonStyle Name.Class , - 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 , - Operator .value_required:n = true , - Operator.Word .tl_set:c = pitonStyle Operator.Word , - Operator.Word .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 , - 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 = + String.Interpol .tl_set:c = pitonStyle String.Interpol , + String.Interpol .value_required:n = true , + FormattingType .tl_set:c = pitonStyle FormattingType , + FormattingType .value_required:n = true , + Dict.Value .tl_set:c = pitonStyle Dict.Value , + Dict.Value .value_required:n = true , + Name.Decorator .tl_set:c = pitonStyle Name.Decorator , + Name.Decorator .value_required:n = true , + Name.Function .tl_set:c = pitonStyle Name.Function , + Name.Function .value_required:n = true , + Name.UserFunction .tl_set:c = pitonStyle Name.UserFunction , + Name.UserFunction .value_required:n = true , + Keyword .tl_set:c = pitonStyle Keyword , + Keyword .value_required:n = true , + Keyword.Constant .tl_set:c = pitonStyle Keyword.Constant , + Keyword.constant .value_required:n = true , + String.Doc .tl_set:c = pitonStyle String.Doc , + String.Doc .value_required:n = true , + Interpol.Inside .tl_set:c = pitonStyle Interpol.Inside , + Interpol.Inside .value_required:n = true , + String.Long .tl_set:c = pitonStyle String.Long , + String.Long .value_required:n = true , + String.Short .tl_set:c = pitonStyle String.Short , + String.Short .value_required:n = true , + String .meta:n = { String.Long = #1 , String.Short = #1 } , + Comment.Math .tl_set:c = pitonStyle Comment.Math , + Comment.Math .default:n = \@@_math_scantokens:n , + Comment.Math .initial:n = , + Comment .tl_set:c = pitonStyle Comment , + Comment .value_required:n = true , + InitialValues .tl_set:c = pitonStyle InitialValues , + InitialValues .value_required:n = true , + Number .tl_set:c = pitonStyle Number , + Number .value_required:n = true , + Name.Namespace .tl_set:c = pitonStyle Name.Namespace , + Name.Namespace .value_required:n = true , + Name.Class .tl_set:c = pitonStyle Name.Class , + 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 , + Operator .value_required:n = true , + Operator.Word .tl_set:c = pitonStyle Operator.Word , + Operator.Word .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 , + 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 } } % \end{macrocode} @@ -3068,31 +3183,32 @@ version 2005/12/01 or later. % \begin{macrocode} \SetPitonStyle { - Comment = \color[HTML]{0099FF} \itshape , - Exception = \color[HTML]{CC0000} , - Keyword = \color[HTML]{006699} \bfseries , - Keyword.Constant = \color[HTML]{006699} \bfseries , - Name.Builtin = \color[HTML]{336666} , - Name.Decorator = \color[HTML]{9999FF}, - Name.Class = \color[HTML]{00AA88} \bfseries , - Name.Function = \color[HTML]{CC00FF} , - Name.Namespace = \color[HTML]{00CCFF} , - Number = \color[HTML]{FF6600} , - Operator = \color[HTML]{555555} , - Operator.Word = \bfseries , - String = \color[HTML]{CC3300} , - String.Doc = \color[HTML]{CC3300} \itshape , - String.Interpol = \color[HTML]{AA0000} , - Comment.LaTeX = \normalfont \color[rgb]{.468,.532,.6} , - Name.Type = \color[HTML]{336666} , - InitialValues = \@@_piton:n , - Dict.Value = \@@_piton:n , - Interpol.Inside = \color{black}\@@_piton:n , - TypeParameter = \color[HTML]{008800} \itshape , - Identifier = \@@_identifier:n , - Prompt = , - ParseAgain.noCR = \@@_piton_no_cr:n , - ParseAgain = \@@_piton:n , + Comment = \color[HTML]{0099FF} \itshape , + Exception = \color[HTML]{CC0000} , + Keyword = \color[HTML]{006699} \bfseries , + Keyword.Constant = \color[HTML]{006699} \bfseries , + Name.Builtin = \color[HTML]{336666} , + Name.Decorator = \color[HTML]{9999FF}, + Name.Class = \color[HTML]{00AA88} \bfseries , + Name.Function = \color[HTML]{CC00FF} , + Name.Namespace = \color[HTML]{00CCFF} , + Number = \color[HTML]{FF6600} , + Operator = \color[HTML]{555555} , + Operator.Word = \bfseries , + String = \color[HTML]{CC3300} , + String.Doc = \color[HTML]{CC3300} \itshape , + String.Interpol = \color[HTML]{AA0000} , + Comment.LaTeX = \normalfont \color[rgb]{.468,.532,.6} , + Name.Type = \color[HTML]{336666} , + InitialValues = \@@_piton:n , + Dict.Value = \@@_piton:n , + Interpol.Inside = \color{black}\@@_piton:n , + TypeParameter = \color[HTML]{008800} \itshape , + Identifier = \@@_identifier:n , + Name.UserFunction = , + Prompt = , + ParseAgain.noCR = \@@_piton_no_cr:n , + ParseAgain = \@@_piton:n , } % \end{macrocode} % The last styles |ParseAgain.noCR| and |ParseAgain| should be considered as @@ -3109,11 +3225,13 @@ version 2005/12/01 or later. % \end{macrocode} % % \bigskip +% +% \bigskip % \subsubsection{Highlighting some identifiers} % % \begin{macrocode} \cs_new_protected:Npn \@@_identifier:n #1 - { \cs_if_exist_use:c { PitonIdentifier #1 } { #1 } } + { \cs_if_exist_use:c { PitonIdentifier _ \l_@@_language_str _ #1 } { #1 } } % \end{macrocode} % % \bigskip @@ -3141,11 +3259,58 @@ version 2005/12/01 or later. \clist_map_inline:Nn \l_@@_identifiers_names_tl { \tl_set_eq:cN - { PitonIdentifier ##1 } + { PitonIdentifier _ \l_@@_language_str _ ##1 } \l_@@_style_tl } } % \end{macrocode} +% +% +% \bigskip +% In particular, we have an hightlighting of the indentifiers which are the +% names of Python functions previously defined by the user. Indeed, when a +% Python function is defined, the style |Name.Function.Internal| is applied to +% that name. We define now that style (you define it directly and you short-cut +% the function |\SetPitonStyle|). +% \begin{macrocode} +\cs_new_protected:cpn { pitonStyle Name.Function.Internal } #1 + { +% \end{macrocode} +% First, the element is composed in the TeX flow with the style |Name.Function| +% which is provided to the final user. +% \begin{macrocode} + { \PitonStyle { Name.Function } { #1 } } +% \end{macrocode} +% Now, we specify that the name of the new Python function is a known identifier +% that will be formated with the Piton style |Name.UserFunction|. Of course, +% here the affectation is global because we have to exit many groups and even +% the environments |{Piton}|). +% \begin{macrocode} + \cs_gset_protected:cpn { PitonIdentifier _ \l_@@_language_str _ #1 } + { \PitonStyle{ Name.UserFunction } } +% \end{macrocode} +% Now, we put the name of that new user function in the dedicated sequence +% (specific of the current language). That sequence will be used only by +% |\PitonClearUserFunctions|. +% \begin{macrocode} + \seq_if_exist:cF { g_@@_functions _ \l_@@_language_str _ seq } + { \seq_new:c { g_@@_functions _ \l_@@_language_str _ seq } } + \seq_gput_right:cn { g_@@_functions _ \l_@@_language_str _ seq } { #1 } + } +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\NewDocumentCommand \PitonClearUserFunctions { ! O { \l_@@_language_str } } + { + \seq_if_exist:cT { g_@@_functions _ #1 _ seq } + { + \seq_map_inline:cn { g_@@_functions _ #1 _ seq } + { \cs_undefine:c { PitonIdentifier _ #1 _ ##1} } + \seq_gclear:c { g_@@_functions _ #1 _ seq } + } + } +% \end{macrocode} % % \bigskip % \subsubsection{Security} @@ -3164,7 +3329,7 @@ version 2005/12/01 or later. % \end{macrocode} % % \bigskip -% \subsubsection{The errors messages of the package} +% \subsubsection{The error messages of the package} % % \begin{macrocode} \msg_new:nnnn { piton } { Unknown~key~for~PitonOptions } @@ -3237,6 +3402,12 @@ version 2005/12/01 or later. If~you~go~on,~that~argument~will~be~ignored. } % \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\msg_new:nnn { Piton } { Python~error } + { A~Python~error~has~been~detected. } +% \end{macrocode} % % \bigskip % \subsection{The Lua part of the implementation} @@ -3265,6 +3436,19 @@ if piton.comment_latex == nil then piton.comment_latex = ">" end piton.comment_latex = "#" .. piton.comment_latex % \end{macrocode} % +% +% \bigskip +% The following functions are an easy way to safely insert braces (|{| and |}|) +% in the TeX flow. +% \begin{macrocode} +function piton.open_brace () + tex.sprint("{") +end +function piton.close_brace () + tex.sprint("}") +end +% \end{macrocode} +% % \bigskip % \subsubsection{Special functions dealing with LPEG} % @@ -3276,6 +3460,7 @@ local P, S, V, C, Ct, Cc = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc local Cf, Cs , Cg , Cmt , Cb = lpeg.Cf, lpeg.Cs, lpeg.Cg , lpeg.Cmt , lpeg.Cb local R = lpeg.R % \end{macrocode} +% % % % \bigskip @@ -3318,24 +3503,18 @@ end % \end{macrocode} % % \bigskip -% The function |K| creates a \textsc{lpeg} which will return as capture -% the whole LaTeX code corresponding to a Python chunk (that is to say with the +% The function |K| creates a \textsc{lpeg} which will return as capture the +% whole LaTeX code corresponding to a Python chunk (that is to say with the % LaTeX formatting instructions corresponding to the syntactic nature of that -% Python chunk). The first argument is a pattern (that is to say a \textsc{lpeg} -% without capture) and the second element is a Lua string corresponding to the -% name of a \pkg{piton} style. If the second argument is not present, the -% function |K| behaves as the function |Q| does. -% \begin{macrocode} -local function K(pattern, style) - if style - then - return +% Python chunk). The first argument is a Lua string corresponding to the name of +% a \pkg{piton} style and the second element is a pattern (that is to say a +% \textsc{lpeg} without capture) +% \begin{macrocode} +local function K(style, pattern) + return Lc ( "{\\PitonStyle{" .. style .. "}{" ) * Q ( pattern ) * Lc ( "}}" ) - else - return Q ( pattern ) - end end % \end{macrocode} % The formatting commands in a given \pkg{piton} style (eg. the style |Keyword|) @@ -3344,6 +3523,17 @@ end % deal with both syntaxes, we have used two pairs of braces: % |{\PitonStyle{Keyword}{|\texttt{\slshape text to format}|}}|. % +% +% \bigskip +% \begin{macrocode} +local function WithStyle(style,pattern) + return + Ct ( Cc "Open" * Cc ( "{\\PitonStyle{" .. style .. "}{" ) * Cc "}}" ) + * pattern + * Ct ( Cc "Close" ) +end +% \end{macrocode} +% % \bigskip % The following \textsc{lpeg} catches the Python chunks which are in LaTeX % escapes (and that chunks will be considered as normal LaTeX constructions). We @@ -3399,7 +3589,7 @@ local identifier = letter * alphanum ^ 0 % On the other hand, the \textsc{lpeg} |Identifier| (with a capital) also returns % a \emph{capture}. % \begin{macrocode} -local Identifier = K ( identifier , 'Identifier' ) +local Identifier = K ( 'Identifier' , identifier) % \end{macrocode} % % \bigskip @@ -3417,11 +3607,10 @@ local Identifier = K ( identifier , 'Identifier' ) % \pkg{piton} styles (but this is only a convention). % \begin{macrocode} local Number = - K ( + K ( 'Number' , ( digit^1 * P "." * digit^0 + digit^0 * P "." * digit^1 + digit^1 ) * ( S "eE" * S "+-" ^ -1 * digit^1 ) ^ -1 - + digit^1 , - 'Number' + + digit^1 ) % \end{macrocode} % @@ -3433,32 +3622,32 @@ local Number = % \begin{macrocode} local Word if piton_begin_escape ~= '' -then Word = K ( ( ( 1 - space - P(piton_begin_escape) - P(piton_end_escape) ) +then Word = Q ( ( ( 1 - space - P(piton_begin_escape) - P(piton_end_escape) ) - S "'\"\r[()]" - digit ) ^ 1 ) -else Word = K ( ( ( 1 - space ) - S "'\"\r[()]" - digit ) ^ 1 ) +else Word = Q ( ( ( 1 - space ) - S "'\"\r[()]" - digit ) ^ 1 ) end % \end{macrocode} % % \bigskip % \begin{macrocode} -local Space = ( K " " ) ^ 1 +local Space = ( Q " " ) ^ 1 -local SkipSpace = ( K " " ) ^ 0 +local SkipSpace = ( Q " " ) ^ 0 -local Punct = K ( S ".,:;!" ) +local Punct = Q ( S ".,:;!" ) local Tab = P "\t" * Lc ( '\\l_@@_tab_tl' ) % \end{macrocode} % % \bigskip % \begin{macrocode} -local SpaceIndentation = Lc ( '\\@@_an_indentation_space:' ) * ( K " " ) +local SpaceIndentation = Lc ( '\\@@_an_indentation_space:' ) * ( Q " " ) % \end{macrocode} % % % \bigskip % \begin{macrocode} -local Delim = K ( S "[()]" ) +local Delim = Q ( S "[()]" ) % \end{macrocode} % % \bigskip @@ -3480,26 +3669,26 @@ local VisualSpace = space * Lc "\\l_@@_space_tl" % ligatures available in some fonts such as \emph{Fira Code} to be active. % \begin{macrocode} local Operator = - K ( P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" + K ( 'Operator' , + P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" + P "//" + P "**" + S "-~+/*%=<>&.@|" - , - 'Operator' ) local OperatorWord = - K ( P "in" + P "is" + P "and" + P "or" + P "not" , 'Operator.Word') + K ( 'Operator.Word' ,P "in" + P "is" + P "and" + P "or" + P "not" ) local Keyword = - K ( P "as" + P "assert" + P "break" + P "case" + P "class" + P "continue" + K ( 'Keyword' , + P "as" + P "assert" + P "break" + P "case" + P "class" + P "continue" + P "def" + P "del" + P "elif" + P "else" + P "except" + P "exec" + P "finally" + P "for" + P "from" + P "global" + P "if" + P "import" + P "lambda" + P "non local" + P "pass" + P "return" + P "try" - + P "while" + P "with" + P "yield" + P "yield from" , - 'Keyword' ) - + K ( P "True" + P "False" + P "None" , 'Keyword.Constant' ) + + P "while" + P "with" + P "yield" + P "yield from" ) + + K ( 'Keyword.Constant' ,P "True" + P "False" + P "None" ) local Builtin = - K ( P "__import__" + P "abs" + P "all" + P "any" + P "bin" + P "bool" + K ( 'Name.Builtin' , + P "__import__" + P "abs" + P "all" + P "any" + P "bin" + P "bool" + P "bytearray" + P "bytes" + P "chr" + P "classmethod" + P "compile" + P "complex" + P "delattr" + P "dict" + P "dir" + P "divmod" + P "enumerate" + P "eval" + P "filter" + P "float" + P "format" @@ -3510,11 +3699,12 @@ local Builtin = + P "ord" + P "pow" + P "print" + P "property" + P "range" + P "repr" + P "reversed" + P "round" + P "set" + P "setattr" + P "slice" + P "sorted" + P "staticmethod" + P "str" + P "sum" + P "super" + P "tuple" + P "type" - + P "vars" + P "zip" , - 'Name.Builtin' ) + + P "vars" + P "zip" ) + local Exception = - K ( P "ArithmeticError" + P "AssertionError" + P "AttributeError" + K ( 'Exception' , + P "ArithmeticError" + P "AssertionError" + P "AttributeError" + P "BaseException" + P "BufferError" + P "BytesWarning" + P "DeprecationWarning" + P "EOFError" + P "EnvironmentError" + P "Exception" + P "FloatingPointError" + P "FutureWarning" + P "GeneratorExit" + P "IOError" + P "ImportError" @@ -3533,10 +3723,10 @@ local Exception = + P "ConnectionResetError" + P "FileExistsError" + P "FileNotFoundError" + P "InterruptedError" + P "IsADirectoryError" + P "NotADirectoryError" + P "PermissionError" + P "ProcessLookupError" + P "TimeoutError" - + P "StopAsyncIteration" + P "ModuleNotFoundError" + P "RecursionError" , - 'Exception' ) + + P "StopAsyncIteration" + P "ModuleNotFoundError" + P "RecursionError" ) + -local RaiseException = K ( P "raise" , 'Keyword' ) * SkipSpace * Exception * K ( P "(" ) +local RaiseException = K ( 'Keyword' , P "raise" ) * SkipSpace * Exception * Q ( P "(" ) % \end{macrocode} % @@ -3544,7 +3734,7 @@ local RaiseException = K ( P "raise" , 'Keyword' ) * SkipSpace * Exception * K ( % In Python, a ``decorator'' is a statement whose begins by |@| which patches % the function defined in the following statement. % \begin{macrocode} -local Decorator = K ( P "@" * letter^1 , 'Name.Decorator' ) +local Decorator = K ( 'Name.Decorator' , P "@" * letter^1 ) % \end{macrocode} % % \bigskip @@ -3556,7 +3746,7 @@ local Decorator = K ( P "@" * letter^1 , 'Name.Decorator' ) % Example:\enskip \piton{class myclass:} % \begin{macrocode} local DefClass = - K ( P "class" , 'Keyword' ) * Space * K ( identifier , 'Name.Class' ) + K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier ) % \end{macrocode} % % If the word |class| is not followed by a identifier, it will be catched as @@ -3580,17 +3770,16 @@ local DefClass = % Example:\enskip \piton{import math, numpy} % \begin{macrocode} local ImportAs = - K ( P "import" , 'Keyword' ) + K ( 'Keyword' , P "import" ) * Space - * K ( identifier * ( P "." * identifier ) ^ 0 , - 'Name.Namespace' - ) + * K ( 'Name.Namespace' , + identifier * ( P "." * identifier ) ^ 0 ) * ( - ( Space * K ( P "as" , 'Keyword' ) * Space - * K ( identifier , 'Name.Namespace' ) ) + ( Space * K ( 'Keyword' , P "as" ) * Space + * K ( 'Name.Namespace' , identifier ) ) + - ( SkipSpace * K ( P "," ) * SkipSpace - * K ( identifier , 'Name.Namespace' ) ) ^ 0 + ( SkipSpace * Q ( P "," ) * SkipSpace + * K ( 'Name.Namespace' , identifier ) ) ^ 0 ) % \end{macrocode} % Be careful: there is no commutativity of |+| in the previous expression. @@ -3608,9 +3797,9 @@ local ImportAs = % \smallskip % \begin{macrocode} local FromImport = - K ( P "from" , 'Keyword' ) - * Space * K ( identifier , 'Name.Namespace' ) - * Space * K ( P "import" , 'Keyword' ) + K ( 'Keyword' , P "from" ) + * Space * K ( 'Name.Namespace' , identifier ) + * Space * K ( 'Keyword' , P "import" ) % \end{macrocode} % % \bigskip @@ -3648,14 +3837,14 @@ local FromImport = % technics now in Python). % \begin{macrocode} local PercentInterpol = - K ( P "%" + K ( 'String.Interpol' , + P "%" * ( P "(" * alphanum ^ 1 * P ")" ) ^ -1 * ( S "-#0 +" ) ^ 0 * ( digit ^ 1 + P "*" ) ^ -1 * ( P "." * ( digit ^ 1 + P "*" ) ) ^ -1 * ( S "HlL" ) ^ -1 - * S "sdfFeExXorgiGauc%" , - 'String.Interpol' + * S "sdfFeExXorgiGauc%" ) % \end{macrocode} % @@ -3668,62 +3857,57 @@ local PercentInterpol = % @@\_piton:n} wich means that the interpolations are parsed once again by \pkg{piton}.} % \begin{macrocode} local SingleShortString = - Lc ( "{\\PitonStyle{String.Short}{" ) - * ( + WithStyle ( 'String.Short' , % \end{macrocode} % First, we deal with the f-strings of Python, which are prefixed by |f| or |F|. % \begin{macrocode} - K ( P "f'" + P "F'" ) + Q ( P "f'" + P "F'" ) * ( - K ( P "{" , 'String.Interpol') - * K ( ( 1 - S "}':" ) ^ 0 , 'Interpol.Inside' ) - * K ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1 - * K ( P "}" , 'String.Interpol' ) + K ( 'String.Interpol' , P "{" ) + * K ( 'Interpol.Inside' , ( 1 - S "}':" ) ^ 0 ) + * Q ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1 + * K ( 'String.Interpol' , P "}" ) + VisualSpace + - K ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 ) + Q ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 ) ) ^ 0 - * K ( P "'" ) + * Q ( P "'" ) + % \end{macrocode} % Now, we deal with the standard strings of Python, but also the ``raw strings''. % \begin{macrocode} - K ( P "'" + P "r'" + P "R'" ) - * ( K ( ( P "\\'" + 1 - S " '\r%" ) ^ 1 ) + Q ( P "'" + P "r'" + P "R'" ) + * ( Q ( ( P "\\'" + 1 - S " '\r%" ) ^ 1 ) + VisualSpace + PercentInterpol - + K ( P "%" ) + + Q ( P "%" ) ) ^ 0 - * K ( P "'" ) - ) - * Lc ( "}}" ) + * Q ( P "'" ) ) + local DoubleShortString = - Lc ( "{\\PitonStyle{String.Short}{" ) - * ( - K ( P "f\"" + P "F\"" ) + WithStyle ( 'String.Short' , + Q ( P "f\"" + P "F\"" ) * ( - K ( P "{" , 'String.Interpol' ) - * K ( ( 1 - S "}\":" ) ^ 0 , 'Interpol.Inside' ) - * ( K ( P ":" , 'String.Interpol' ) * K ( (1 - S "}:\"") ^ 0 ) ) ^ -1 - * K ( P "}" , 'String.Interpol' ) + K ( 'String.Interpol' , P "{" ) + * Q ( ( 1 - S "}\":" ) ^ 0 , 'Interpol.Inside' ) + * ( K ( 'String.Interpol' , P ":" ) * Q ( (1 - S "}:\"") ^ 0 ) ) ^ -1 + * K ( 'String.Interpol' , P "}" ) + VisualSpace + - K ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 ) + Q ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 ) ) ^ 0 - * K ( P "\"" ) + * Q ( P "\"" ) + - K ( P "\"" + P "r\"" + P "R\"" ) - * ( K ( ( P "\\\"" + 1 - S " \"\r%" ) ^ 1 ) + Q ( P "\"" + P "r\"" + P "R\"" ) + * ( Q ( ( P "\\\"" + 1 - S " \"\r%" ) ^ 1 ) + VisualSpace + PercentInterpol - + K ( P "%" ) + + Q ( P "%" ) ) ^ 0 - * K ( P "\"" ) - ) - * Lc ( "}}" ) + * Q ( P "\"" ) ) local ShortString = SingleShortString + DoubleShortString % \end{macrocode} @@ -3749,6 +3933,7 @@ local BalancedBraces = ) ^ 0 } % \end{macrocode} +% % % \bigskip % If Beamer is used (or if the key |beamer| is used at load-time), the following @@ -3757,12 +3942,38 @@ local BalancedBraces = local Beamer = P ( false ) local BeamerBeginEnvironments = P ( true ) local BeamerEndEnvironments = P ( true ) -local BeamerNamesEnvironments = +local BeamerNamesEnvironments = P "uncoverenv" + P "onlyenv" + P "visibleenv" + P "invisibleenv" + P "alertenv" + P "actionenv" % \end{macrocode} +% +% \begin{macrocode} +UserCommands = + Ct ( Cc "Open" * C ( "\\emph{" ) * Cc "}" ) + * ( C ( BalancedBraces ) / (function (s) return MainLoopPython:match(s) end ) ) + * P "}" * Ct ( Cc "Close" ) +% \end{macrocode} +% +% \begin{macrocode} +function OneBeamerEnvironment(name) + return + Ct ( Cc "Open" + * C ( + P ( "\\begin{" .. name .. "}" ) + * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 + ) + * Cc ( "\\end{" .. name .. "}" ) + ) + * ( + C ( ( 1 - P ( "\\end{" .. name .. "}" ) ) ^ 0 ) + / (function (s) return MainLoopPython:match(s) end ) + ) + * P ( "\\end{" .. name .. "}" ) * Ct ( Cc "Close" ) +end +% \end{macrocode} % +% % \bigskip % \begin{macrocode} if piton_beamer @@ -3770,24 +3981,27 @@ then Beamer = L ( P "\\pause" * ( P "[" * (1 - P "]") ^ 0 * P "]" ) ^ -1 ) + -% \end{macrocode} -% We recall that the command |\@@_beamer_command:n| executes the argument -% corresponding to its argument but also stores it in |\l_@@_beamer_command_str|. -% That string is used only in the error message ``|cr~not~allowed|'' raised when -% there is a carriage return in the mandatory argument of that command. -% \begin{macrocode} - ( 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 "}" ) - + + Ct ( Cc "Open" + * C ( + ( + P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible" + + P "\\invisible" + P "\\action" + ) + * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 + * P "{" + ) + * Cc "}" + ) + * ( C ( BalancedBraces ) / (function (s) return MainLoopPython:match(s) end ) ) + * P "}" * Ct ( Cc "Close" ) + + + OneBeamerEnvironment "uncoverenv" + + OneBeamerEnvironment "onlyenv" + + OneBeamerEnvironment "visibleenv" + + OneBeamerEnvironment "invisibleenv" + + OneBeamerEnvironment "alertenv" + + OneBeamerEnvironment "actionenv" + + L ( % \end{macrocode} % For |\\alt|, the specification of the overlays (between angular brackets) is mandatory. @@ -3796,9 +4010,9 @@ then * P "<" * (1 - P ">") ^ 0 * P ">" * P "{" ) - * K ( BalancedBraces , 'ParseAgain.noCR' ) + * K ( 'ParseAgain.noCR' , BalancedBraces ) * L ( P "}{" ) - * K ( BalancedBraces , 'ParseAgain.noCR' ) + * K ( 'ParseAgain.noCR' , BalancedBraces ) * L ( P "}" ) + L ( @@ -3809,11 +4023,11 @@ then * P "<" * (1 - P ">") ^ 0 * P ">" * P "{" ) - * K ( BalancedBraces , 'ParseAgain.noCR' ) + * K ( 'ParseAgain.noCR' , BalancedBraces ) * L ( P "}{" ) - * K ( BalancedBraces , 'ParseAgain.noCR' ) + * K ( 'ParseAgain.noCR' , BalancedBraces ) * L ( P "}{" ) - * K ( BalancedBraces , 'ParseAgain.noCR' ) + * K ( 'ParseAgain.noCR' , BalancedBraces ) * L ( P "}" ) % \end{macrocode} % Now for the environemnts. @@ -3841,24 +4055,29 @@ end % \bigskip % The following LPEG will detect the Python prompts when the user is typesetting % an interactive session of Python (directly or through |{pyconsole}| of -% \pkg{pyluatex}). +% \pkg{pyluatex}). We have to detect that prompt twice. The first detection +% (called \emph{hasty detection}) will be before the |\@@_begin_line:| because +% you want to trigger a special background color for that row (and, after the +% |\@@_begin_line:|, it's too late to change de background). % \begin{macrocode} local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\@@_prompt:' ) ) ^ -1 % \end{macrocode} -% We remind that the marker |#| of LPEG specifies that the pattern will be +% We remind that the marker |#| of \textsc{lpeg} specifies that the pattern will be % detected but won't consume any character. % +% \medskip +% With the following \textsc{lpeg}, a style will actually be applied to the +% prompt (for instance, it's possible to decide to discard these prompts). % \begin{macrocode} -local Prompt = K ( ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1 , 'Prompt' ) +local Prompt = K ( 'Prompt' , ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1 ) % \end{macrocode} % +% +% % \bigskip % The following \textsc{lpeg} |EOL| is for the end of lines. % \begin{macrocode} -local EOL -if piton_beamer -then -EOL = +local EOL = P "\r" * ( @@ -3871,45 +4090,23 @@ EOL = % @@\_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} - Lc ( '\\@@_end_line:' ) - * BeamerEndEnvironments - * BeamerBeginEnvironments - * PromptHastyDetection - * Lc ( '\\@@_newline: \\@@_begin_line:' ) - * Prompt - ) - * - SpaceIndentation ^ 0 -else -EOL = - P "\r" - * - ( - ( space ^ 0 * -1 ) - + -% \end{macrocode} -% We recall that each line in the Python code we have 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} - Lc ( '\\@@_end_line:' ) - * PromptHastyDetection - * Lc ( '\\@@_newline: \\@@_begin_line:' ) - * Prompt + Ct ( + Cc "EOL" + * + Ct ( + Lc "\\@@_end_line:" + * BeamerEndEnvironments + * BeamerBeginEnvironments + * PromptHastyDetection + * Lc "\\@@_newline: \\@@_begin_line:" + * Prompt + ) + ) ) * SpaceIndentation ^ 0 -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} @@ -3917,63 +4114,61 @@ end % % \begin{macrocode} local SingleLongString = - Lc "{\\PitonStyle{String.Long}{" - * ( - K ( S "fF" * P "'''" ) + WithStyle ( 'String.Long' , + ( Q ( S "fF" * P "'''" ) * ( - K ( P "{" , 'String.Interpol' ) - * K ( ( 1 - S "}:\r" - P "'''" ) ^ 0 , 'Interpol.Inside' ) - * K ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1 - * K ( P "}" , 'String.Interpol' ) + K ( 'String.Interpol' , P "{" ) + * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "'''" ) ^ 0 ) + * Q ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1 + * K ( 'String.Interpol' , P "}" ) + - K ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 ) + Q ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 ) + - EOL_for_style 'String.Long' + EOL ) ^ 0 + - K ( ( S "rR" ) ^ -1 * P "'''" ) + Q ( ( S "rR" ) ^ -1 * P "'''" ) * ( - K ( ( 1 - P "'''" - S "\r%" ) ^ 1 ) + Q ( ( 1 - P "'''" - S "\r%" ) ^ 1 ) + PercentInterpol + P "%" + - EOL_for_style 'String.Long' + EOL ) ^ 0 ) - * K ( P "'''" ) - * Lc "}}" + * Q ( P "'''" ) ) local DoubleLongString = - Lc "{\\PitonStyle{String.Long}{" - * ( - K ( S "fF" * P "\"\"\"" ) - * ( - K ( P "{" , 'String.Interpol' ) - * K ( ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 , 'Interpol.Inside' ) - * K ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1 - * K ( P "}" , 'String.Interpol' ) - + - K ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 ) - + - EOL_for_style 'String.Long' - ) ^ 0 - + - K ( ( S "rR" ) ^ -1 * P "\"\"\"" ) - * ( - K ( ( 1 - P "\"\"\"" - S "%\r" ) ^ 1 ) - + - PercentInterpol - + - P "%" - + - EOL_for_style 'String.Long' - ) ^ 0 - ) - * K ( P "\"\"\"" ) - * Lc "}}" + WithStyle ( 'String.Long' , + ( + Q ( S "fF" * P "\"\"\"" ) + * ( + K ( 'String.Interpol', P "{" ) + * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) + * Q ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1 + * K ( 'String.Interpol' , P "}" ) + + + Q ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 ) + + + EOL + ) ^ 0 + + + Q ( ( S "rR" ) ^ -1 * P "\"\"\"" ) + * ( + Q ( ( 1 - P "\"\"\"" - S "%\r" ) ^ 1 ) + + + PercentInterpol + + + P "%" + + + EOL + ) ^ 0 + ) + * Q ( P "\"\"\"" ) + ) % \end{macrocode} % % \begin{macrocode} @@ -3986,11 +4181,11 @@ local LongString = SingleLongString + DoubleLongString % of a function definition (which begins with |def|). % \begin{macrocode} local StringDoc = - K ( P "\"\"\"" , 'String.Doc' ) - * ( K ( (1 - P "\"\"\"" - P "\r" ) ^ 0 , 'String.Doc' ) * EOL + K ( 'String.Doc' , P "\"\"\"" ) + * ( K ( 'String.Doc' , (1 - P "\"\"\"" - P "\r" ) ^ 0 ) * EOL * Tab ^ 0 ) ^ 0 - * K ( ( 1 - P "\"\"\"" - P "\r" ) ^ 0 * P "\"\"\"" , 'String.Doc' ) + * K ( 'String.Doc' , ( 1 - P "\"\"\"" - P "\r" ) ^ 0 * P "\"\"\"" ) % \end{macrocode} % % \bigskip @@ -4000,13 +4195,12 @@ local StringDoc = % listings. % \begin{macrocode} local CommentMath = - P "$" * K ( ( 1 - S "$\r" ) ^ 1 , 'Comment.Math' ) * P "$" + P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" local Comment = - Lc ( "{\\PitonStyle{Comment}{" ) - * K ( P "#" ) - * ( CommentMath + K ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 - * Lc ( "}}" ) + WithStyle ( 'Comment' , + Q ( P "#" ) + * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) * ( EOL + -1 ) % \end{macrocode} % @@ -4023,7 +4217,7 @@ local CommentLaTeX = * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" * L ( ( 1 - P "\r" ) ^ 0 ) * Lc "}}" - * ( EOL + -1 ) + * ( EOL + -1 ) -- you could put EOL instead of EOL % \end{macrocode} % % \bigskip @@ -4071,14 +4265,14 @@ local Expression = local Param = SkipSpace * Identifier * SkipSpace * ( - K ( P "=" * Expression , 'InitialValues' ) - + K ( P ":" ) * SkipSpace * K ( letter^1 , 'Name.Type' ) + K ( 'InitialValues' , P "=" * Expression ) + + Q ( P ":" ) * SkipSpace * K ( 'Name.Type' , letter^1 ) ) ^ -1 % \end{macrocode} % % \medskip % \begin{macrocode} -local Params = ( Param * ( K "," * Param ) ^ 0 ) ^ -1 +local Params = ( Param * ( Q "," * Param ) ^ 0 ) ^ -1 % \end{macrocode} % % \bigskip @@ -4089,21 +4283,21 @@ local Params = ( Param * ( K "," * Param ) ^ 0 ) ^ -1 % |Comment|, |CommentLaTeX|, |Params|, |StringDoc|... % \begin{macrocode} local DefFunction = - K ( P "def" , 'Keyword' ) + K ( 'Keyword' , P "def" ) * Space - * K ( identifier , 'Name.Function' ) + * K ( 'Name.Function.Internal' , identifier ) * SkipSpace - * K ( P "(" ) * Params * K ( P ")" ) + * Q ( P "(" ) * Params * Q ( P ")" ) * SkipSpace - * ( K ( P "->" ) * SkipSpace * K ( identifier , 'Name.Type' ) ) ^ -1 + * ( Q ( P "->" ) * SkipSpace * K ( 'Name.Type' , identifier ) ) ^ -1 % \end{macrocode} % 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 , 'ParseAgain' ) - * K ( P ":" ) + * K ( 'ParseAgain' , ( 1 - S ":\r" )^0 ) + * Q ( P ":" ) * ( SkipSpace * ( EOL + CommentLaTeX + Comment ) -- in all cases, that contains an EOL * Tab ^ 0 @@ -4144,20 +4338,20 @@ local DefFunction = % % \begin{macrocode} local ItemDict = - ShortString * SkipSpace * K ( P ":" ) * K ( Expression , 'Dict.Value' ) + ShortString * SkipSpace * Q ( P ":" ) * K ( 'Dict.Value' , Expression ) local ItemOfSet = SkipSpace * ( ItemDict + ShortString ) * SkipSpace local Set = - K ( P "{" ) - * ItemOfSet * ( K ( P "," ) * ItemOfSet ) ^ 0 - * K ( P "}" ) + Q ( P "{" ) + * ItemOfSet * ( Q ( P "," ) * ItemOfSet ) ^ 0 + * Q ( P "}" ) % \end{macrocode} % % \paragraph{Miscellaneous} % % \begin{macrocode} -local ExceptionInConsole = Exception * K ( ( 1 - P "\r" ) ^ 0 ) * EOL +local ExceptionInConsole = Exception * Q ( ( 1 - P "\r" ) ^ 0 ) * EOL % \end{macrocode} % % @@ -4166,14 +4360,15 @@ local ExceptionInConsole = Exception * K ( ( 1 - P "\r" ) ^ 0 ) * EOL % % First, the main loop : % \begin{macrocode} -MainLoop = +MainLoopPython = ( ( space^1 * -1 ) + EOL + Space + Tab + Escape + CommentLaTeX - + Beamer + + Beamer + + UserCommands + LongString + Comment + ExceptionInConsole @@ -4189,10 +4384,10 @@ MainLoop = + RaiseException + DefFunction + DefClass - + Keyword * ( Space + Punct + Delim + EOL + -1 ) + + Keyword * ( Space + Punct + Delim + EOL+ -1 ) + Decorator - + OperatorWord * ( Space + Punct + Delim + EOL + -1 ) - + Builtin * ( Space + Punct + Delim + EOL + -1 ) + + OperatorWord * ( Space + Punct + Delim + EOL+ -1 ) + + Builtin * ( Space + Punct + Delim + EOL+ -1 ) + Identifier + Number + Word @@ -4213,12 +4408,12 @@ python = ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 * BeamerBeginEnvironments * PromptHastyDetection - * Lc ( '\\@@_begin_line:' ) + * Lc '\\@@_begin_line:' * Prompt * SpaceIndentation ^ 0 - * MainLoop + * MainLoopPython * -1 - * Lc ( '\\@@_end_line:' ) + * Lc '\\@@_end_line:' ) % \end{macrocode} % @@ -4231,44 +4426,48 @@ languages['python'] = python % \subsubsection{The LPEG ocaml} % % \begin{macrocode} -local Punct = K ( S ",:;!" ) +local Delim = Q ( P "[|" + P "|]" + S "[()]" ) +% \end{macrocode} +% +% \begin{macrocode} +local Punct = Q ( S ",:;!" ) % \end{macrocode} % % \begin{macrocode} local identifier = ( R "az" + R "AZ" + P "_") * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 -local Identifier = K ( identifier ) +local Identifier = K ( 'Identifier' , identifier ) local Operator = - K ( P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" + K ( 'Operator' , + 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') + K ( 'Operator.Word' , + P "and" + P "asr" + P "land" + P "lor" + P "lsl" + P "lxor" + + P "mod" + P "or" ) local Keyword = - K ( P "as" + P "assert" + P "begin" + P "class" + P "constraint" + P "done" + K ( 'Keyword' , + 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' ) + + P "value" + P "val" + P "virtual" + P "when" + P "while" + P "with" ) + + K ( 'Keyword.Constant' , P "true" + P "false" ) local Builtin = - K ( P "not" + P "incr" + P "decr" + P "fst" + P "snd" + K ( 'Name.Builtin' , + 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" @@ -4280,27 +4479,26 @@ local Builtin = + 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' ) + + P "Hashtbl.iter" ) % \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" + K ( 'Exception' , + P "Division_by_zero" + P "End_of_File" + P "Failure" + P "Invalid_argument" + P "Match_failure" + P "Not_found" + P "Out_of_memory" + P "Stack_overflow" + P "Sys_blocked_io" - + P "Sys_error" + P "Undefined_recursive_module" , - 'Exception' ) + + P "Sys_error" + P "Undefined_recursive_module" ) % \end{macrocode} % -% +% \bigskip % \paragraph{The characters in OCaml} % % \begin{macrocode} local Char = - K ( P "'" * ( ( 1 - P "'" ) ^ 0 + P "\\'" ) * P "'" , 'String.Short' ) + K ( 'String.Short' , P "'" * ( ( 1 - P "'" ) ^ 0 + P "\\'" ) * P "'" ) % \end{macrocode} % % @@ -4337,7 +4535,7 @@ then ) * L ( ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 * P "{" ) - * K ( BalancedBraces , 'ParseAgain.noCR' ) + * K ( 'ParseAgain.noCR' , BalancedBraces ) * L ( P "}" ) + L ( @@ -4345,9 +4543,9 @@ then * P "<" * (1 - P ">") ^ 0 * P ">" * P "{" ) - * K ( BalancedBraces , 'ParseAgain.noCR' ) + * K ( 'ParseAgain.noCR' , BalancedBraces ) * L ( P "}{" ) - * K ( BalancedBraces , 'ParseAgain.noCR' ) + * K ( 'ParseAgain.noCR' , BalancedBraces ) * L ( P "}" ) + L ( @@ -4355,11 +4553,11 @@ then * P "<" * (1 - P ">") ^ 0 * P ">" * P "{" ) - * K ( BalancedBraces , 'ParseAgain.noCR' ) + * K ( 'ParseAgain.noCR' , BalancedBraces ) * L ( P "}{" ) - * K ( BalancedBraces , 'ParseAgain.noCR' ) + * K ( 'ParseAgain.noCR' , BalancedBraces ) * L ( P "}{" ) - * K ( BalancedBraces , 'ParseAgain.noCR' ) + * K ( 'ParseAgain.noCR' , BalancedBraces ) * L ( P "}" ) BeamerBeginEnvironments = ( space ^ 0 * @@ -4380,61 +4578,52 @@ end % % \bigskip % \paragraph{EOL} -% % \begin{macrocode} -local EOL -if piton_beamer -then -EOL = +local 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:' ) + Ct ( + Cc "EOL" + * + Ct ( + Lc "\\@@_end_line:" + * BeamerEndEnvironments + * BeamerBeginEnvironments + * PromptHastyDetection + * Lc "\\@@_newline: \\@@_begin_line:" + * Prompt + ) + ) ) * SpaceIndentation ^ 0 -end % \end{macrocode} % +% % \begin{macrocode} -function EOL_for_style ( s ) - return Lc "}}" * EOL * Lc ( "{\\PitonStyle{" .. s .. "}{" ) -end -% \end{macrocode} -% % % \paragraph{The strings} % +% We need a pattern |string| without captures because it will be used within the +% comments of OCaml. % \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 "}}" +local string = + Q ( P "\"" ) + * ( + VisualSpace + + + Q ( ( 1 - S " \"\r" ) ^ 1 ) + + + EOL + ) ^ 0 + * Q ( P "\"" ) +% \end{macrocode} +% +% \begin{macrocode} +local String = WithStyle ( 'String.Long' , string ) % \end{macrocode} % % @@ -4461,16 +4650,15 @@ local closeeq = % The \textsc{lpeg} |QuotedStringBis| will do the second analysis. % \begin{macrocode} local QuotedStringBis = - Lc "{\\PitonStyle{String.Long}{" - * - ( + WithStyle ( 'String.Long' , + ( VisualSpace + - K ( ( 1 - S " \r" ) ^ 1 ) + Q ( ( 1 - S " \r" ) ^ 1 ) + - EOL_for_style 'String.Long' - ) ^ 0 - * Lc "}}" + EOL + ) ^ 0 ) + % \end{macrocode} % % \medskip @@ -4486,7 +4674,7 @@ local QuotedString = % \bigskip % \paragraph{The comments in the OCaml listings} % -% In OCaml, the delimiters for the comments are |(*| and |*)|. There +% In OCaml, the delimiters for the comments are |(*| and |*)|. There are % unsymmetrical and, therefore, the comments may be nested. That's why we need a % grammar. % @@ -4495,20 +4683,18 @@ local QuotedString = % % \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 "}}" + WithStyle ( 'Comment' , + P { + "A" , + A = Q "(*" + * ( V "A" + + Q ( ( 1 - P "(*" - P "*)" - S "\r$\"" ) ^ 1 ) -- $ + + string + + P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" -- $ + + EOL + ) ^ 0 + * Q "*)" + } ) % \end{macrocode} % % \bigskip @@ -4516,18 +4702,18 @@ local Comment = % % \begin{macrocode} local DefFunction = - ( K ( P "let rec" + P "let" + P "and" , 'Keyword' ) ) + K ( 'Keyword' , P "let rec" + P "let" + P "and" ) * Space - * K ( identifier , 'Name.Function' ) + * K ( 'Name.Function.Internal' , identifier ) * Space - * # ( 1 - P "=" ) + * # ( P "=" * space * P "function" + ( 1 - P "=" ) ) % \end{macrocode} % % \bigskip % \paragraph{The parameters of the types} % % \begin{macrocode} -local TypeParameter = K ( P "'" * alpha * # ( 1 - P "'") , 'TypeParameter' ) +local TypeParameter = K ( 'TypeParameter' , P "'" * alpha * # ( 1 - P "'" ) ) % \end{macrocode} % % \bigskip @@ -4535,7 +4721,7 @@ local TypeParameter = K ( P "'" * alpha * # ( 1 - P "'") , 'TypeParameter' ) % % First, the main loop : % \begin{macrocode} -MainLoop = +MainLoopOCaml = ( ( space^1 * -1 ) + EOL + Space @@ -4576,7 +4762,7 @@ ocaml = * BeamerBeginEnvironments * Lc ( '\\@@_begin_line:' ) * SpaceIndentation ^ 0 - * MainLoop + * MainLoopOCaml * -1 * Lc ( '\\@@_end_line:' ) ) @@ -4589,9 +4775,6 @@ languages['ocaml'] = ocaml % \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 @@ -4603,8 +4786,39 @@ local MinimalSyntax = Ct ( ( (1 - P "\r" ) ^ 1 + EOL ) ^ 0 ) % \begin{macrocode} 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 + local left_stack = {} + local right_stack = {} + for _ , one_item in ipairs(t) + do + if one_item[1] == "EOL" + then + for _ , s in ipairs(right_stack) + do tex.sprint( s ) + end + for _ , s in ipairs(one_item[2]) + do tex.tprint(s) + end + for _ , s in ipairs(left_stack) + do tex.sprint( s ) + end + else + if one_item[1] == "Open" + then + tex.sprint( one_item[2] ) + table.insert(left_stack,one_item[2]) + table.insert(right_stack,one_item[3]) + else + if one_item[1] == "Close" + then + tex.sprint( right_stack[#right_stack] ) + left_stack[#left_stack] = nil + right_stack[#right_stack] = nil + else + tex.tprint(one_item) + end + end + end + end end % \end{macrocode} % @@ -4843,6 +5057,11 @@ end % \vspace{1cm} % \section{History} % +% % \subsection*{Changes between versions 1.4 and 1.5} +% +% New key |numbers-sep|. +% +% % \subsection*{Changes between versions 1.3 and 1.4} % % New key |identifiers| in |\PitonOptions|. |