diff options
author | Karl Berry <karl@freefriends.org> | 2023-05-04 20:30:12 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2023-05-04 20:30:12 +0000 |
commit | 4dbc6757af1e88d09347cd5d0238aa44e1f81013 (patch) | |
tree | c71d73450dea2765d7e1b0d9ab1ef0a78a517cfb /Master/texmf-dist/source/lualatex | |
parent | 38951983767ecadf441c8c88658dc039d709a8a7 (diff) |
piton (4may23)
git-svn-id: svn://tug.org/texlive/trunk@67019 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/lualatex')
-rw-r--r-- | Master/texmf-dist/source/lualatex/piton/piton.dtx | 1195 |
1 files changed, 760 insertions, 435 deletions
diff --git a/Master/texmf-dist/source/lualatex/piton/piton.dtx b/Master/texmf-dist/source/lualatex/piton/piton.dtx index 794fc718eb2..5202fea7112 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.5a} -\def\myfiledate{2023/04/11} +\def\myfileversion{1.6} +\def\myfiledate{2023/05/03} % % %<*batchfile> @@ -205,8 +205,8 @@ version 2005/12/01 or later. % {\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, +% backslash but also the active characters (with catcode equal to 13).} are +% fully expanded and not executed, % % {\color{cyan} so it's possible to use |\\| to insert a backslash}. % \end{itemize} @@ -325,17 +325,17 @@ version 2005/12/01 or later. % example part \ref{example-numbering} on page~\pageref{example-numbering}. % % \item The key \Definition{background-color} sets the background color of the -% environments |{Piton}| and the listings produced by |\PitonInputFile| (that -% background has a width of |\linewidth|). +% environments |{Piton}| and the listings produced by |\PitonInputFile| (it's +% possible to fix the width of that background with the key |width| described +% below). % % \smallskip -% \colorbox{yellow!50}{\textbf{New 1.4}}\enskip The key |background-color| -% supports also as value a \emph{list} of colors. In this case, the successive -% rows are colored by using the colors of the list in a cyclic way. +% The key |background-color| supports also as value a \emph{list} of colors. In +% this case, the successive rows are colored by using the colors of the list in +% a cyclic way. % % \emph{Example} : |\PitonOptions{background-color = {gray!5,white}}| % -% % The key |background-color| accepts a color defined «on the fly». For example, % it's possible to write |background-color = [cmyk]{0.1,0.05,0,0}|. % @@ -344,6 +344,24 @@ version 2005/12/01 or later. % continuation ``|...|'') characteristic of the Python consoles with % \textsc{repl} (\emph{read-eval-print loop}). % +% \item \colorbox{yellow!50}{\textbf{New 1.6}}\enskip The key |width| will fix +% the width of the listing. That width applies to the colored backgrounds +% specified by |background-color| and |prompt-background-color| but also for the +% automatic breaking of the lines (when required by |break-lines|: +% cf.~\ref{line-breaks}, p.~\pageref{line-breaks}). +% +% That key may take in as value a numeric value but also the special +% value~|min|. With that value, the width will be computed from the maximal +% width of the lines of code. Caution: the special value~|min| requires two +% compilations with LuaLaTeX\footnote{The maximal width is computed during the +% first compilation, written on the |aux| file and re-used during the second +% compilation. Several tools such as |latexmk| (used by Overleaf) do +% automatically a sufficient number of compilations.}. +% +% For an example of use of |width=min|, see the section~\ref{example-comments}, +% p.~\pageref{example-comments}. +% +% % \item When the key \Definition{show-spaces-in-strings} is activated, the % spaces in the short strings (that is to say those delimited by |'| or |"|) are % replaced by the character~␣ (U+2423 : \textsc{open box}). Of course, that @@ -464,9 +482,8 @@ version 2005/12/01 or later. % \url{https://pygments.org/styles/}. Remark that, by default, Pygments provides for its style \pkg{manni} a colored background whose color is the HTML color \texttt{\#F0F3F3}. It's possible to have the same color in \texttt{\{Pion\}} with the instruction \texttt{\textbackslash PitonOptions\{background-color = [HTML]\{F0F3F3\}\}}.} % % \bigskip -% \colorbox{yellow!50}{\textbf{New 1.4}}\enskip The command |\PitonStyle| takes -% in as argument the name of a style and allows to retrieve the value (as a list -% of LaTeX instructions) of that style. +% The command |\PitonStyle| takes in as argument the name of a style and allows +% to retrieve the value (as a list of LaTeX instructions) of that style. % % \smallskip % For example, it's possible to write |{\PitonStyle{Keyword}{function}}| and we @@ -521,7 +538,53 @@ version 2005/12/01 or later. % \end{table} % % +% \vspace{1cm} \colorbox{yellow!50}{\textbf{New 1.6}}\par\nobreak +% +% The extension \pkg{piton} provides a special style called~|UserFunction|. That +% style applies to the names of the functions previously defined by the user via +% an instruction Python \piton{def} in one of the previous listings. The initial +% value of that style is empty, and, therefore, the names of the functions are +% formatted as standard text (in black). However, it's possible to change the +% value of that style, as any other style, with the command |\PitonSetStyle|. +% +% \medskip +% In the following example, we fix as value for that style |UserFunction| the +% initial value of the the style |Name.Function| (which applies to the name of +% the functions, \emph{at the moment of their definition}). +% +% \begingroup +% +% \begin{Verbatim} +% \PitonSetStyle{~emphase#UserFunction@ = \color[HTML]{CC00FF}} +% \end{Verbatim} +% +% \SetPitonStyle{UserFunction = \color[HTML]{CC00FF}} +% +% \begin{Piton} +% def transpose(v,i,j): +% x = v[i] +% v[i] = v[j] +% v[j] = x +% +% def passe(v): +% for in in range(0,len(v)-1): +% if v[i] > v[i+1]: +% transpose(v,i,i+1) +% \end{Piton} +% +% \endgroup +% +% As one see, the name |transpse| 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 +% +% \bigskip +% Of course, the list of the names of Python functions previously défined is +% kept in the memory of LuaLaTeX (in a global way, that is to say independtly of +% the TeX groups). The extension \pkg{piton} provides a command to clear that +% list : it's the command |\PitonClearUserFunctions|. % % \subsection{Creation of new environments} % @@ -588,9 +651,8 @@ version 2005/12/01 or later. % % \subsection{Highlighting some identifiers} % -% \colorbox{yellow!50}{\textbf{New 1.4}} It's possible to require a changement -% of formating for some identifiers with the key |identifiers| of -% |\PitonOptions|. +% It's possible to require a changement of formating for some identifiers with +% the key |identifiers| of |\PitonOptions|. % % \smallskip % That key takes in as argument a value of the following format: @@ -894,12 +956,13 @@ 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).} +% 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|, i.e. with +% |\begin{frame}[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 @@ -1123,16 +1186,14 @@ version 2005/12/01 or later. % % % \bigskip -% The following code has been composed in a standard LaTeX |{minipage}| of width -% 12~cm with the following tuning: +% The following code has been composed with the following tuning: % % \begin{Verbatim} -% \PitonOptions{break-lines,indent-broken-lines,background-color=gray!15} +% \PitonOptions{width=12cm,break-lines,indent-broken-lines,background-color=gray!15} % \end{Verbatim} % % \begin{center} -% \PitonOptions{break-lines,indent-broken-lines,background-color=gray!15} -% \begin{minipage}{12cm} +% \PitonOptions{width=12cm,break-lines,indent-broken-lines,background-color=gray!15} % \begin{Piton} % def dict_of_list(l): % """Converts a list of subrs and descriptions of glyphs in a dictionary""" @@ -1147,7 +1208,6 @@ version 2005/12/01 or later. % our_dict[name] = [treat_Postscript_line(k) for k in list_letter[1:-1]] % return dict % \end{Piton} -% \end{minipage} % \end{center} % % \subsection{Footnotes in the environments of piton} @@ -1225,9 +1285,9 @@ version 2005/12/01 or later. % \begin{Piton} % def arctan(x,n=10): % if x < 0: -% return -arctan(-x) #> (appel récursif) +% return -arctan(-x) #> (recursive call) % elif x > 1: -% return pi/2 - arctan(1/x) #> (autre appel récursif) +% return pi/2 - arctan(1/x) #> (other recursive call) % else: % return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) % \end{Piton} @@ -1241,9 +1301,9 @@ version 2005/12/01 or later. % \begin{Piton} % def arctan(x,n=10): % if x < 0: -% return -arctan(-x) #> (appel récursif) +% return -arctan(-x) #> (recursive call) % elif x > 1: -% return pi/2 - arctan(1/x) #> (autre appel récursif) +% return pi/2 - arctan(1/x) #> (other recursive call) % else: % return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) % \end{Piton} @@ -1269,9 +1329,9 @@ version 2005/12/01 or later. % \begin{Piton} % def arctan(x,n=10): % if x < 0: -% return -arctan(-x) #> appel récursif +% return -arctan(-x) #> recursive call % elif x > 1: -% return pi/2 - arctan(1/x) #> autre appel récursif +% return pi/2 - arctan(1/x) #> other recursive call % else: % return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) % \end{Piton} @@ -1284,9 +1344,9 @@ version 2005/12/01 or later. % \begin{Piton} % def arctan(x,n=10): % if x < 0: -% return -arctan(-x) #> appel récursif +% return -arctan(-x) #> recursive call % elif x > 1: -% return pi/2 - arctan(1/x) #> autre appel récursif +% return pi/2 - arctan(1/x) #> another recursive call % else: % return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) % \end{Piton} @@ -1295,52 +1355,49 @@ version 2005/12/01 or later. % % \vspace{1cm} % It's also possible to display these LaTeX comments in a kind of second column -% by limiting the width of the Python code by an environment |{minipage}| of LaTeX. +% by limiting the width of the Python code with the key |width|. In the +% following example, we use the key |width| with the special value~|min|. % % % \begingroup % \fvset{commandchars=\~\&\@,formatcom=\small\color{gray}} % \begin{Verbatim} -% \PitonOptions{background-color=gray!10} +% \PitonOptions{background-color=gray!10, width=min} % ~emphase&\NewDocumentCommand{\MyLaTeXCommand}{m}{\hfill \normalfont\itshape\rlap{\quad #1}}@ % ~emphase&\SetPitonStyle{Comment.LaTeX = \MyLaTeXCommand}@ -% ~emphase&\begin{minipage}{12cm}@ % \begin{Piton} % def arctan(x,n=10): % if x < 0: -% return -arctan(-x) #> appel récursif +% return -arctan(-x) #> recursive call % elif x > 1: -% return pi/2 - arctan(1/x) #> autre appel récursif +% return pi/2 - arctan(1/x) #> anoother recursive call % else: % s = 0 % for k in range(n): % s += (-1)**k/(2*k+1)*x**(2*k+1) % return s % \end{Piton} -% ~emphase&\end{minipage}@ % \end{Verbatim} % \endgroup % % % % \begingroup -% \PitonOptions{background-color=gray!10} +% \PitonOptions{background-color=gray!10, width=min} % \NewDocumentCommand{\MyLaTeXCommand}{m}{\hfill \normalfont\itshape\rlap{\quad #1}} % \SetPitonStyle{Comment.LaTeX = \MyLaTeXCommand} -% \begin{minipage}{12cm} % \begin{Piton} % def arctan(x,n=10): % if x < 0: -% return -arctan(-x) #> appel récursif +% return -arctan(-x) #> recursive call % elif x > 1: -% return pi/2 - arctan(1/x) #> autre appel récursif +% return pi/2 - arctan(1/x) #> another recursive call % else: % s = 0 % for k in range(n): % s += (-1)**k/(2*k+1)*x**(2*k+1) % return s % \end{Piton} -% \end{minipage} % \endgroup % % @@ -1432,49 +1489,6 @@ version 2005/12/01 or later. % \endgroup % % -% \vspace{1cm} -% If we embed an environment |{Piton}| in an environment |{minipage}| -% (typically in order to limit the width of a colored background), it's -% necessary to embed the whole environment |{minipage}| in an environment -% |{savenotes}| (of \pkg{footnote} or \pkg{footnotehyper}) in order to have the -% footnotes composed at the bottom of the page. -% -% \begingroup -% \fvset{commandchars=\~\&\@,formatcom=\small\color{gray}} -% \begin{Verbatim} -% \PitonOptions{background-color=gray!10} -% ~emphase&\begin{savenotes}@ -% \begin{minipage}{13cm} -% \begin{Piton} -% def arctan(x,n=10): -% if x < 0: -% return -arctan(-x)~emphase&#>\footnote{First recursive call.}@ -% elif x > 1: -% return pi/2 - arctan(1/x)~emphase&#>\footnote{Second recursive call.}@ -% else: -% return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) -% \end{Piton} -% \end{minipage} -% ~emphase&\end{savenotes}@ -% \end{Verbatim} -% \endgroup -% -% -% -% \begin{savenotes} -% \PitonOptions{background-color=gray!10} -% \begin{minipage}{13cm} -% \begin{Piton} -% def arctan(x,n=10): -% if x < 0: -% return -arctan(-x)#>\footnote{First recursive call.} -% elif x > 1: -% return pi/2 - arctan(1/x)#>\footnote{Second recursive call.} -% else: -% return sum( (-1)**k/(2*k+1)*x**(2*k+1) for k in range(n) ) -% \end{Piton} -% \end{minipage} -% \end{savenotes} % % \bigskip % @@ -1551,7 +1565,7 @@ version 2005/12/01 or later. % n is the number of terms in the sum % """ % if x < 0: -% return -arctan(-x) # appel récursif +% return -arctan(-x) # recursive call % elif x > 1: % return pi/2 - arctan(1/x) % #> (we have used that $\arctan(x)+\arctan(1/x)=\pi/2$ for $x>0$) @@ -1631,6 +1645,12 @@ version 2005/12/01 or later. % % \section{Implementation} % +% % \medskip +% The development of the extension \pkg{piton} is done on the following GitHub +% depot: +% +% \verb|https://github.com/fpantigny/piton| +% % \subsection{Introduction} % % The main job of the package \pkg{piton} is to take in as input a Python @@ -2021,20 +2041,6 @@ version 2005/12/01 or later. \tl_new:N \l_@@_prompt_bg_color_tl % \end{macrocode} % -% \medskip -% We will compute the maximal width of the lines of an environment |{Piton}| in -% |\g_@@_width_dim|. We need a global variable because, when the key |footnote| -% is in force, each line when be composed in an environment |{savenotes}| and -% (when |slim| is in force) we need to exit |\g_@@_width_dim| from that -% environment. -% \begin{macrocode} -\dim_new:N \g_@@_width_dim -% \end{macrocode} -% The value of that dimension as written on the |aux| file will be stored in -% |\l_@@_width_on_aux_dim|. -% \begin{macrocode} -\dim_new:N \l_@@_width_on_aux_dim -% \end{macrocode} % % \medskip % We will count the environments |{Piton}| (and, in fact, also the commands @@ -2085,10 +2091,52 @@ version 2005/12/01 or later. \bool_new:N \l_@@_break_lines_in_piton_bool % \end{macrocode} % +% \bigskip +% The following dimension will be the width of the listing constructed by +% |{Piton}| or |\PitonInputFile|. +% \begin{itemize} +% \item If the user uses the key |width| of |\PitonOptions| with a numerical +% value, that value will be stored in |\l_@@_width_dim|. +% \item If the user uses the key |width| with the special value~|min|, the +% dimension |\l_@@_width_dim| will, \emph{in the second run}, be computed from +% the value of |\l_@@_line_width_dim| stored in the |aux| file +% (computed during the first run the maximal width of the lines of the listing). +% During the first run, |\l_@@_width_line_dim| will be set equal to |\linewidth|. +% \item Elsewhere, |\l_@@_width_dim| will be set at the beginning of the listing +% (in |\@@_pre_env:|) equal to the current value of |\linewidth|. +% \end{itemize} +% +% \begin{macrocode} +\dim_new:N \l_@@_width_dim +% \end{macrocode} +% % \medskip -% The following boolean corresponds to the key |slim| of |\PitonOptions|. +% We will also use another dimension called |\l_@@_line_width_dim|. That +% will the width of the actual lines of code. That dimension may be lower than +% the whole |\l_@@_width_dim| because we have to take into account the value of +% |\l_@@_left_margin_dim| (for the numbers of lines when |line-numbers| is in +% force) and another small margin when a background color is used (with the key +% |background-color|). % \begin{macrocode} -\bool_new:N \l_@@_slim_bool +\dim_new:N \l_@@_line_width_dim +% \end{macrocode} +% +% \medskip +% The following flag will be raised with the key |width| is used with the +% special value |min|. +% \begin{macrocode} +\bool_new:N \l_@@_width_min_bool +% \end{macrocode} +% +% \medskip +% If the key |width| is used with the special value~|min|, we will compute the +% maximal width of the lines of an environment |{Piton}| in |\g_@@_tmp_width_dim| +% because we need it for the case of the key |width| is used with the spacial +% value |min|. We need a global variable because, when the key |footnote| is in +% force, each line when be composed in an environment |{savenotes}| and we need +% to exit our |\g_@@_tmp_width_dim| from that environment. +% \begin{macrocode} +\dim_new:N \g_@@_tmp_width_dim % \end{macrocode} % % \medskip @@ -2222,84 +2270,13 @@ version 2005/12/01 or later. \cs_new_protected:Npn \@@_prompt: { \tl_gset:Nn \g_@@_begin_line_hook_tl - { \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 + \tl_if_empty:NF \l_@@_prompt_bg_color_tl % added 2023-04-24 + { \clist_set:NV \l_@@_bg_color_clist \l_@@_prompt_bg_color_tl } + } } % \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} @@ -2345,22 +2322,15 @@ version 2005/12/01 or later. \int_gzero:N \g_@@_indentation_int % \end{macrocode} % -% -% Be careful: there is curryfication in the following lines. +% \medskip +% First, we will put in the coffin |\l_tmpa_coffin| the actual content of a line +% of the code (without the potential number of line). +% +% Be careful: There is curryfication in the following code. % \begin{macrocode} - \bool_if:NTF \l_@@_slim_bool - { \hcoffin_set:Nn \l_tmpa_coffin } - { - \clist_if_empty:NTF \l_@@_bg_color_clist - { - \vcoffin_set:Nnn \l_tmpa_coffin - { \dim_eval:n { \linewidth - \l_@@_left_margin_dim } } - } - { - \vcoffin_set:Nnn \l_tmpa_coffin - { \dim_eval:n { \linewidth - \l_@@_left_margin_dim - 0.5 em } } - } - } + \bool_if:NTF \l_@@_width_min_bool + \@@_put_in_coffin_ii:n + \@@_put_in_coffin_i:n { \language = -1 \raggedright @@ -2368,47 +2338,51 @@ version 2005/12/01 or later. \@@_replace_spaces:n { #1 } \strut \hfil } +% \end{macrocode} +% Now, we add the potential number of line, the potential left margin and the +% potential background. +% \begin{macrocode} \hbox_set:Nn \l_tmpa_box { \skip_horizontal:N \l_@@_left_margin_dim \bool_if:NT \l_@@_line_numbers_bool { \bool_if:NF \l_@@_all_line_numbers_bool - { \tl_if_eq:nnF { #1 } { \PitonStyle {Prompt}{} } } % corrected 2023/04/10 + { \tl_if_eq:nnF { #1 } { \PitonStyle {Prompt}{} } } +% \end{macrocode} +% Remember that |\@@_print_number:| always uses |\hbox_overlap_left:n|. +% \begin{macrocode} \@@_print_number: } +% \end{macrocode} +% If there is a background, we must remind that there is a left margin of 0.5~em +% for the background... +% \begin{macrocode} \clist_if_empty:NF \l_@@_bg_color_clist { +% \end{macrocode} +% ... but if only if the key |left-margin| is not used ! +% \begin{macrocode} \dim_compare:nNnT \l_@@_left_margin_dim = \c_zero_dim - { - \bool_if:NF \l_@@_left_margin_auto_bool - { \skip_horizontal:n { 0.5 em } } - } + { \skip_horizontal:n { 0.5 em } } } \coffin_typeset:Nnnnn \l_tmpa_coffin T l \c_zero_dim \c_zero_dim } -% \end{macrocode} -% We compute in |\g_@@_width_dim| the maximal width of the lines of the -% environment. -% \begin{macrocode} - \dim_compare:nNnT { \box_wd:N \l_tmpa_box } > \g_@@_width_dim - { \dim_gset:Nn \g_@@_width_dim { \box_wd:N \l_tmpa_box } } \box_set_dp:Nn \l_tmpa_box { \box_dp:N \l_tmpa_box + 1.25 pt } \box_set_ht:Nn \l_tmpa_box { \box_ht:N \l_tmpa_box + 1.25 pt } \clist_if_empty:NTF \l_@@_bg_color_clist { \box_use_drop:N \l_tmpa_box } { - \vbox_top:n + \vtop { \hbox:n { \@@_color:N \l_@@_bg_color_clist \vrule height \box_ht:N \l_tmpa_box depth \box_dp:N \l_tmpa_box - width \l_@@_width_on_aux_dim + width \l_@@_width_dim } \skip_vertical:n { - \box_ht_plus_dp:N \l_tmpa_box } - \box_set_wd:Nn \l_tmpa_box \l_@@_width_on_aux_dim \box_use_drop:N \l_tmpa_box } } @@ -2419,6 +2393,54 @@ version 2005/12/01 or later. % \end{macrocode} % % \bigskip +% In the general case (which is also the simpler), the key |width| is not used, +% or (if used) it is not used with the special value~|min|. +% In that case, the content of a line of code is composed in a vertical coffin +% with a width equal to |\l_@@_line_width_dim|. That coffin may, +% eventually, contains several lines when the key |broken-lines-in-Piton| (or +% |broken-lines|) is used. +% +% That commands takes in its argument by curryfication. +% \begin{macrocode} +\cs_set_protected:Npn \@@_put_in_coffin_i:n + { \vcoffin_set:Nnn \l_tmpa_coffin \l_@@_line_width_dim } +% \end{macrocode} +% +% \bigskip +% The second case is the case when the key |width| is used with the special +% value~|min|. +% \begin{macrocode} +\cs_set_protected:Npn \@@_put_in_coffin_ii:n #1 + { +% \end{macrocode} +% First, we compute the natural width of the line of code because we have to +% compute the natural width of the whole listing (and it will be written on the +% |aux| file in the variable |\l_@@_width_dim|). +% \begin{macrocode} + \hbox_set:Nn \l_tmpa_box { #1 } +% \end{macrocode} +% Now, you can actualize the value of |\g_@@_tmp_width_dim| (it will be used to +% write on the |aux| file the natural width of the environment). +% \begin{macrocode} + \dim_compare:nNnT { \box_wd:N \l_tmpa_box } > \g_@@_tmp_width_dim + { \dim_gset:Nn \g_@@_tmp_width_dim { \box_wd:N \l_tmpa_box } } +% \end{macrocode} +% +% \begin{macrocode} + \hcoffin_set:Nn \l_tmpa_coffin + { + \hbox_to_wd:nn \l_@@_line_width_dim +% \end{macrocode} +% We unpack the bock in order to free the potential |\hfill| springs present in +% the LaTeX comments (cf. section~\ref{example-comments}, p.~\pageref{example-comments}). +% \begin{macrocode} + { \hbox_unpack:N \l_tmpa_box \hfil } + } + } +% \end{macrocode} +% +% +% \bigskip % The command |\@@_color:N| will take in as argument a reference to a % comma-separated list of colors. A color will be picked by using the value of % |\g_@@_line_int| (modulo the number of colors in the list). @@ -2430,10 +2452,10 @@ version 2005/12/01 or later. \tl_set:Nx \l_tmpa_tl { \clist_item:Nn #1 \l_tmpb_int } \tl_if_eq:NnTF \l_tmpa_tl { none } % \end{macrocode} -% By setting |\l_@@_width_on_aux_dim| to zero, the colored rectangle will be +% By setting |\l_@@_width_dim| to zero, the colored rectangle will be % drawn with zero width and, thus, it will be a mere strut (and we need that strut). % \begin{macrocode} - { \dim_zero:N \l_@@_width_on_aux_dim } + { \dim_zero:N \l_@@_width_dim } { \exp_args:NV \@@_color_i:n \l_tmpa_tl } } % \end{macrocode} @@ -2466,7 +2488,7 @@ version 2005/12/01 or later. { \egroup \bool_if:NT \c_@@_footnote_bool { \end { savenotes } } - \newline + \par \mode_leave_vertical: % \newline \bool_if:NT \c_@@_footnote_bool { \begin { savenotes } } \vtop \bgroup } @@ -2552,15 +2574,27 @@ version 2005/12/01 or later. background-color .value_required:n = true , prompt-background-color .tl_set:N = \l_@@_prompt_bg_color_tl , prompt-background-color .value_required:n = true , - slim .bool_set:N = \l_@@_slim_bool , - slim .default:n = true , + width .code:n = + \str_if_eq:nnTF { #1 } { min } + { + \bool_set_true:N \l_@@_width_min_bool + \dim_zero:N \l_@@_width_dim + } + { + \bool_set_false:N \l_@@_width_min_bool + \dim_set:Nn \l_@@_width_dim { #1 } + } , + width .value_required:n = true , left-margin .code:n = \str_if_eq:nnTF { #1 } { auto } { \dim_zero:N \l_@@_left_margin_dim \bool_set_true:N \l_@@_left_margin_auto_bool } - { \dim_set:Nn \l_@@_left_margin_dim { #1 } } , + { + \dim_set:Nn \l_@@_left_margin_dim { #1 } + \bool_set_false:N \l_@@_left_margin_auto_bool + } , left-margin .value_required:n = true , numbers-sep .dim_set:N = \l_@@_numbers_sep_dim , numbers-sep .value_required:n = true , @@ -2645,20 +2679,17 @@ version 2005/12/01 or later. } % \end{macrocode} % +% \bigskip +% The following macro with be used only when the key |width| is used with the +% special value~|min|. % \begin{macrocode} \cs_new_protected:Npn \@@_width_to_aux: { - \bool_if:NT \l_@@_slim_bool - { - \clist_if_empty:NF \l_@@_bg_color_clist - { - \tl_gput_right:Nx \g_@@_aux_tl - { - \dim_set:Nn \l_@@_width_on_aux_dim - { \dim_eval:n { \g_@@_width_dim + 0.5 em } } - } - } - } + \tl_gput_right:Nx \g_@@_aux_tl + { + \dim_set:Nn \l_@@_line_width_dim + { \dim_eval:n { \g_@@_tmp_width_dim } } + } } % \end{macrocode} % @@ -2819,11 +2850,18 @@ version 2005/12/01 or later. \automatichyphenmode = 1 \int_gincr:N \g_@@_env_int \tl_gclear:N \g_@@_aux_tl + \dim_compare:nNnT \l_@@_width_dim = \c_zero_dim + { \dim_set_eq:NN \l_@@_width_dim \linewidth } +% \end{macrocode} +% We read the information written on the |aux| file by previous run (when the +% key |width| is used with the special value~|min|). At this time, the only +% potential information written on the |aux| file is the value of +% |\l_@@_line_width_dim| when the key |width| has been used with the special +% value~|min|). +% \begin{macrocode} \cs_if_exist_use:c { c_@@ _ \int_use:N \g_@@_env_int _ tl } - \dim_compare:nNnT \l_@@_width_on_aux_dim = \c_zero_dim - { \dim_set_eq:NN \l_@@_width_on_aux_dim \linewidth } \bool_if:NF \l_@@_resume_bool { \int_gzero:N \g_@@_visual_line_int } - \dim_gzero:N \g_@@_width_dim + \dim_gzero:N \g_@@_tmp_width_dim \int_gzero:N \g_@@_line_int \dim_zero:N \parindent \dim_zero:N \lineskip @@ -2842,79 +2880,99 @@ version 2005/12/01 or later. last-line .value_required:n = true , } % \end{macrocode} +% +% +% \bigskip +% If the final user has used both |left-margin=auto| and |line-numbers|, we have +% to compute the width of the maximal number of lines at the end of the +% environment to fix the correct value to |left-margin|. The first argument of +% the following function is the name of the Lua function that will be applied to +% the second argument in order to count the number of lines. +% \begin{macrocode} +\cs_new_protected:Npn \@@_compute_left_margin:nn #1 #2 + { + \bool_lazy_and:nnT \l_@@_left_margin_auto_bool \l_@@_line_numbers_bool + { + \hbox_set:Nn \l_tmpa_box + { + \footnotesize + \bool_if:NTF \l_@@_all_line_numbers_bool + { + \int_to_arabic:n + { \g_@@_visual_line_int + \l_@@_nb_lines_int } + } + { + \lua_now:n + { piton.#1(token.scan_argument()) } + { #2 } + \int_to_arabic:n + { \g_@@_visual_line_int + \l_@@_nb_non_empty_lines_int } + } + } + \dim_set:Nn \l_@@_left_margin_dim + { \box_wd:N \l_tmpa_box + \l_@@_numbers_sep_dim + 0.1 em } + } + } +% \end{macrocode} % +% +% % \bigskip +% Whereas |\l_@@_with_dim| is the width of the environment, +% |\l_@@_line_width_dim| is the width of the lines of code without the +% potential margins for the numbers of lines and the background. Depending on +% the case, you have to compute |\l_@@_line_width_dim| from |\l_@@_width_dim| or +% we have to do the opposite. % \begin{macrocode} -\NewDocumentCommand { \PitonInputFile } { d < > O { } m } +\cs_new_protected:Npn \@@_compute_width: { - \tl_if_novalue:nF { #1 } + \dim_compare:nNnTF \l_@@_line_width_dim = \c_zero_dim { - \bool_if:NTF \c_@@_beamer_bool - { \begin { uncoverenv } < #1 > } - { \msg_error:nn { piton } { overlay~without~beamer } } - } - \group_begin: - \int_zero_new:N \l_@@_first_line_int - \int_zero_new:N \l_@@_last_line_int - \int_set_eq:NN \l_@@_last_line_int \c_max_int - \keys_set:nn { PitonInputFile } { #2 } - \@@_pre_env: - \mode_if_vertical:TF \mode_leave_vertical: \newline + \dim_set_eq:NN \l_@@_line_width_dim \l_@@_width_dim + \clist_if_empty:NTF \l_@@_bg_color_clist % \end{macrocode} -% We count with Lua the number of lines of the argument. The result will be -% stored by Lua in |\l_@@_nb_lines_int|. That information will be used to allow -% or disallow page breaks. +% If there is no background, we only subtract the left margin. % \begin{macrocode} - \lua_now:n { piton.CountLinesFile(token.scan_argument()) } { #3 } -% \end{macrocode} -% If the final user has used both |left-margin=auto| and |line-numbers| or -% |all-line-numbers|, we have to compute the width of the maximal number of -% lines at the end of the composition of the listing to fix the correct value to -% |left-margin|. -% \begin{macrocode} - \bool_lazy_and:nnT \l_@@_left_margin_auto_bool \l_@@_line_numbers_bool - { - \hbox_set:Nn \l_tmpa_box - { - \footnotesize - \bool_if:NTF \l_@@_all_line_numbers_bool - { - \int_to_arabic:n - { \g_@@_visual_line_int + \l_@@_nb_lines_int } - } - { - \lua_now:n - { piton.CountNonEmptyLinesFile(token.scan_argument()) } - { #3 } - \int_to_arabic:n - { \g_@@_visual_line_int + \l_@@_nb_non_empty_lines_int } - } - } - \dim_set:Nn \l_@@_left_margin_dim - { \box_wd:N \l_tmpa_box + \l_@@_numbers_sep_dim + 0.1 em } - } + { \dim_sub:Nn \l_@@_line_width_dim \l_@@_left_margin_dim } % \end{macrocode} -% Now, the main job. +% If there is a background, we subtract 0.5~em for the margin on the right. % \begin{macrocode} - \ttfamily - \bool_if:NT \c_@@_footnote_bool { \begin { savenotes } } - \vtop \bgroup - \lua_now:e - { - piton.ParseFile('\l_@@_language_str',token.scan_argument() , - \int_use:N \l_@@_first_line_int , - \int_use:N \l_@@_last_line_int ) - } - { #3 } - \egroup - \bool_if:NT \c_@@_footnote_bool { \end { savenotes } } - \@@_width_to_aux: - \group_end: - \tl_if_novalue:nF { #1 } - { \bool_if:NT \c_@@_beamer_bool { \end { uncoverenv } } } - \@@_write_aux: + { + \dim_sub:Nn \l_@@_line_width_dim { 0.5 em } +% \end{macrocode} +% And we subtract also for the left margin. If the key |left-margin| has been +% used (with a numerical value or with the special value~|min|), +% |\l_@@_left_margin_dim| has a non-zero value\footnote{If the key +% \texttt{left-margin} has been used with the special value \texttt{min}, the +% actual value of \texttt{\textbackslash l_\@\@_left_margin_dim} has yet been +% computed when we use the current command.} and we use that value. Elsewhere, +% we use a value of 0.5~em. +% \begin{macrocode} + \dim_compare:nNnTF \l_@@_left_margin_dim = \c_zero_dim + { \dim_sub:Nn \l_@@_line_width_dim { 0.5 em } } + { \dim_sub:Nn \l_@@_line_width_dim \l_@@_left_margin_dim } + } + } +% \end{macrocode} +% If |\l_@@_line_width_dim| has yet a non-empty value, that means that it has +% been read on the |aux| file: it has been written on a previous run because the +% key |width| is used with the special value~|min|). We compute now the width of +% the environment by computations opposite to the preceding ones. +% \begin{macrocode} + { + \dim_set_eq:NN \l_@@_width_dim \l_@@_line_width_dim + \clist_if_empty:NTF \l_@@_bg_color_clist + { \dim_add:Nn \l_@@_width_dim \l_@@_left_margin_dim } + { + \dim_add:Nn \l_@@_width_dim { 0.5 em } + \dim_compare:nNnTF \l_@@_left_margin_dim = \c_zero_dim + { \dim_add:Nn \l_@@_width_dim { 0.5 em } } + { \dim_add:Nn \l_@@_width_dim \l_@@_left_margin_dim } + } + } } % \end{macrocode} +% % % % \bigskip @@ -2935,7 +2993,7 @@ version 2005/12/01 or later. ####1 \c_backslash_str end \c_left_brace_str #1 \c_right_brace_str } - { + { \group_end: \mode_if_vertical:TF \mode_leave_vertical: \newline % \end{macrocode} @@ -2945,39 +3003,16 @@ version 2005/12/01 or later. % \begin{macrocode} \lua_now:n { piton.CountLines(token.scan_argument()) } { ##1 } % \end{macrocode} -% If the final user has used both |left-margin=auto| and |line-numbers|, we have -% to compute the width of the maximal number of lines at the end of the -% environment to fix the correct value to |left-margin|. +% The first argument of the following function is the name of the Lua function +% that will be applied to the second argument in order to count the number of lines. % \begin{macrocode} - \bool_lazy_and:nnT \l_@@_left_margin_auto_bool \l_@@_line_numbers_bool - { - \bool_if:NTF \l_@@_all_line_numbers_bool - { - \hbox_set:Nn \l_tmpa_box - { - \footnotesize - \int_to_arabic:n - { \g_@@_visual_line_int + \l_@@_nb_lines_int } - } - } - { - \lua_now:n - { piton.CountNonEmptyLines(token.scan_argument()) } - { ##1 } - \hbox_set:Nn \l_tmpa_box - { - \footnotesize - \int_to_arabic:n - { \g_@@_visual_line_int + \l_@@_nb_non_empty_lines_int } - } - } - \dim_set:Nn \l_@@_left_margin_dim - { \box_wd:N \l_tmpa_box + \l_@@_numbers_sep_dim + 0.1 em } - } + \@@_compute_left_margin:nn { CountNonEmptyLines } { ##1 } + \@@_compute_width: + \ttfamily % \end{macrocode} -% Now, the main job. +% |\c_@@_footnote_bool| is raised when the package \pkg{piton} has been load +% with the key |footnote| \emph{or} the key |footnotehyper|. % \begin{macrocode} - \ttfamily \bool_if:NT \c_@@_footnote_bool { \begin { savenotes } } \vtop \bgroup \lua_now:e @@ -2993,10 +3028,14 @@ version 2005/12/01 or later. \vspace { 2.5 pt } \egroup \bool_if:NT \c_@@_footnote_bool { \end { savenotes } } - \@@_width_to_aux: % \end{macrocode} -% The following |\end{#1}| is only for the groups and the stack of environments -% of LaTeX. +% If the user has used the key |width| with the special value~|min|, we write on +% the |aux| file the value of |\l_@@_line_width_dim| (largest width of the lines +% of code of the environment). +% \begin{macrocode} + \bool_if:NT \l_@@_width_min_bool \@@_width_to_aux: +% \end{macrocode} +% The following |\end{#1}| is only for the stack of environments of LaTeX. % \begin{macrocode} \end { #1 } \@@_write_aux: @@ -3054,6 +3093,78 @@ version 2005/12/01 or later. % \end{macrocode} % % +% \bigskip +% The code of the command |\PitonInputFile| is somewhat similar to the code of +% the environment |{Piton}|. In fact, it's simpler because there isn't the +% problem of catching the content of the environment in a verbatim mode. +% \begin{macrocode} +\NewDocumentCommand { \PitonInputFile } { d < > O { } m } + { + \file_if_exist:nTF { #3 } + { \@@_input_file:nnn { #1 } { #2 } { #3 } } + { \msg_error:nnn { piton } { unknown~file } { #3 } } + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new_protected:Npn \@@_input_file:nnn #1 #2 #3 + { +% \end{macrocode} +% We recall that, if we are in Beamer, the command |\PitonInputFile| is +% ``overlay-aware'' and that's why there is an optional argument between angular +% brackets (|<| and |>|). +% \begin{macrocode} + \tl_if_novalue:nF { #1 } + { + \bool_if:NTF \c_@@_beamer_bool + { \begin { uncoverenv } < #1 > } + { \msg_error:nn { piton } { overlay~without~beamer } } + } + \group_begin: + \int_zero_new:N \l_@@_first_line_int + \int_zero_new:N \l_@@_last_line_int + \int_set_eq:NN \l_@@_last_line_int \c_max_int + \keys_set:nn { PitonInputFile } { #2 } + \@@_pre_env: + \mode_if_vertical:TF \mode_leave_vertical: \newline +% \end{macrocode} +% We count with Lua the number of lines of the argument. The result will be +% stored by Lua in |\l_@@_nb_lines_int|. That information will be used to allow +% or disallow page breaks. +% \begin{macrocode} + \lua_now:n { piton.CountLinesFile(token.scan_argument()) } { #3 } +% \end{macrocode} +% The first argument of the following function is the name of the Lua function +% that will be applied to the second argument in order to count the number of lines. +% \begin{macrocode} + \@@_compute_left_margin:nn { CountNonEmptyLinesFile } { #3 } + \@@_compute_width: + \ttfamily + \bool_if:NT \c_@@_footnote_bool { \begin { savenotes } } + \vtop \bgroup + \lua_now:e + { + piton.ParseFile( + '\l_@@_language_str', + token.scan_argument() , + \int_use:N \l_@@_first_line_int , + \int_use:N \l_@@_last_line_int ) + } + { #3 } + \egroup + \bool_if:NT \c_@@_footnote_bool { \end { savenotes } } + \bool_if:NT \l_@@_width_min_bool \@@_width_to_aux: + \group_end: +% \end{macrocode} +% We recall that, if we are in Beamer, the command |\PitonInputFile| is +% ``overlay-aware'' and that's why we close now an environment |{uncoverenv}| +% that we have opened at the beginning of the command. +% \begin{macrocode} + \tl_if_novalue:nF { #1 } + { \bool_if:NT \c_@@_beamer_bool { \end { uncoverenv } } } + \@@_write_aux: + } +% \end{macrocode} % % \bigskip % \subsubsection{The styles} @@ -3088,10 +3199,12 @@ version 2005/12/01 or later. Dict.Value .value_required:n = true , Name.Decorator .tl_set:c = pitonStyle Name.Decorator , Name.Decorator .value_required:n = true , + Name.Field .tl_set:c = pitonStyle Name.Field , + Name.Field .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 , + UserFunction .tl_set:c = pitonStyle UserFunction , + UserFunction .value_required:n = true , Keyword .tl_set:c = pitonStyle Keyword , Keyword .value_required:n = true , Keyword.Constant .tl_set:c = pitonStyle Keyword.Constant , @@ -3110,12 +3223,16 @@ version 2005/12/01 or later. Comment.Math .initial:n = , Comment .tl_set:c = pitonStyle Comment , Comment .value_required:n = true , + Name.Constructor .tl_set:c = pitonStyle Name.Constructor , + Name.Constructor .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.Module .tl_set:c = pitonStyle Name.Module , + Name.Module .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 , @@ -3163,9 +3280,13 @@ version 2005/12/01 or later. Keyword.Constant,~ Name.Builtin,~ Name.Class,~ + Name.Constructor,~ Name.Decorator,~ + Name.Field,~ Name.Function,~ + Name.Module,~ Name.Namespace,~ + UserFunction,~ Number,~ Operator,~ Operator.Word,~ @@ -3179,9 +3300,9 @@ version 2005/12/01 or later. % \end{macrocode} % % \bigskip -% \subsubsection{The initial style} +% \subsubsection{The initial styles} % -% The initial style is inspired by the style ``manni'' of Pygments. +% The initial styles are inspired by the style ``manni'' of Pygments. % % \medskip % \begin{macrocode} @@ -3196,6 +3317,9 @@ version 2005/12/01 or later. Name.Class = \color[HTML]{00AA88} \bfseries , Name.Function = \color[HTML]{CC00FF} , Name.Namespace = \color[HTML]{00CCFF} , + Name.Constructor = \color[HTML]{006000} \bfseries , + Name.Field = \color[HTML]{AA6600} , + Name.Module = \color[HTML]{0060A0} \bfseries , Number = \color[HTML]{FF6600} , Operator = \color[HTML]{555555} , Operator.Word = \bfseries , @@ -3207,9 +3331,9 @@ version 2005/12/01 or later. InitialValues = \@@_piton:n , Dict.Value = \@@_piton:n , Interpol.Inside = \color{black}\@@_piton:n , - TypeParameter = \color[HTML]{008800} \itshape , + TypeParameter = \color[HTML]{336666} \itshape , Identifier = \@@_identifier:n , - Name.UserFunction = , + UserFunction = , Prompt = , ParseAgain.noCR = \@@_piton_no_cr:n , ParseAgain = \@@_piton:n , @@ -3271,14 +3395,14 @@ version 2005/12/01 or later. % % % \bigskip -% In particular, we have an hightlighting of the indentifiers which are the +% In particular, we have an highlighting 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. @@ -3286,16 +3410,16 @@ version 2005/12/01 or later. { \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, +% that will be formated with the Piton style |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 } } + { \PitonStyle { 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|. +% (specific of the current language). {\bfseries 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 } } @@ -3336,6 +3460,15 @@ version 2005/12/01 or later. % \subsubsection{The error messages of the package} % % \begin{macrocode} +\msg_new:nnn { piton } { unknown~file } + { + Unknown~file. \\ + The~file~'#1'~is~unknown.\\ + Your~command~\token_to_str:N \PitonInputFile\ will~be~discarded. + } +% \end{macrocode} +% +% \begin{macrocode} \msg_new:nnnn { piton } { Unknown~key~for~PitonOptions } { Unknown~key. \\ @@ -3365,10 +3498,9 @@ version 2005/12/01 or later. resume,~ show-spaces,~ show-spaces-in-strings,~ - slim,~ splittable,~ - tabs-auto-gobble~ - and~tab-size. + tabs-auto-gobble,~ + tab-size~and~width. } % \end{macrocode} % @@ -3636,7 +3768,7 @@ end % \begin{macrocode} local Space = ( Q " " ) ^ 1 -local SkipSpace = ( Q " " ) ^ 0 +local SkipSpace = ( Q " " ) ^ 0 local Punct = Q ( S ".,:;!" ) @@ -3679,7 +3811,7 @@ local Operator = ) local OperatorWord = - K ( 'Operator.Word' ,P "in" + P "is" + P "and" + P "or" + P "not" ) + K ( 'Operator.Word' , P "in" + P "is" + P "and" + P "or" + P "not" ) local Keyword = K ( 'Keyword' , @@ -3919,13 +4051,13 @@ local ShortString = SingleShortString + DoubleShortString % \bigskip % \paragraph{Beamer} % -% The following \textsc{lpeg} |BalancedBraces| will be used for the (mandatory) +% The following \textsc{lpeg} |balanced_braces| will be used for the (mandatory) % argument of the commands |\only| and \emph{al.} of Beamer. It's necessary to % use a \emph{grammar} because that pattern mainly checks the correct nesting of % the delimiters (and it's known in the theory of formal languages that this % can't be done with regular expressions \emph{stricto sensu} only). % \begin{macrocode} -local BalancedBraces = +local balanced_braces = P { "E" , E = ( @@ -3949,16 +4081,13 @@ local BeamerEndEnvironments = P ( true ) 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} % +% \bigskip +% The following function will return a \textsc{lpeg} which will catch an +% environment of Beamer (supported by \pkg{piton}), that is to say |{uncover}|, +% |{only}|, etc. % \begin{macrocode} function OneBeamerEnvironment(name) return @@ -3971,7 +4100,7 @@ function OneBeamerEnvironment(name) ) * ( C ( ( 1 - P ( "\\end{" .. name .. "}" ) ) ^ 0 ) - / (function (s) return MainLoopPython:match(s) end ) + / ( function (s) return MainLoopPython:match(s) end ) ) * P ( "\\end{" .. name .. "}" ) * Ct ( Cc "Close" ) end @@ -3983,7 +4112,7 @@ end if piton_beamer then Beamer = - L ( P "\\pause" * ( P "[" * (1 - P "]") ^ 0 * P "]" ) ^ -1 ) + L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) + Ct ( Cc "Open" * C ( @@ -3996,10 +4125,9 @@ then ) * Cc "}" ) - * ( C ( BalancedBraces ) / (function (s) return MainLoopPython:match(s) end ) ) + * ( C ( balanced_braces ) / (function (s) return MainLoopPython:match(s) end ) ) * P "}" * Ct ( Cc "Close" ) - + - OneBeamerEnvironment "uncoverenv" + + OneBeamerEnvironment "uncoverenv" + OneBeamerEnvironment "onlyenv" + OneBeamerEnvironment "visibleenv" + OneBeamerEnvironment "invisibleenv" @@ -4014,9 +4142,9 @@ then * P "<" * (1 - P ">") ^ 0 * P ">" * P "{" ) - * K ( 'ParseAgain.noCR' , BalancedBraces ) + * K ( 'ParseAgain.noCR' , balanced_braces ) * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , BalancedBraces ) + * K ( 'ParseAgain.noCR' , balanced_braces ) * L ( P "}" ) + L ( @@ -4027,11 +4155,11 @@ then * P "<" * (1 - P ">") ^ 0 * P ">" * P "{" ) - * K ( 'ParseAgain.noCR' , BalancedBraces ) + * K ( 'ParseAgain.noCR' , balanced_braces ) * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , BalancedBraces ) + * K ( 'ParseAgain.noCR' , balanced_braces ) * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , BalancedBraces ) + * K ( 'ParseAgain.noCR' , balanced_braces ) * L ( P "}" ) % \end{macrocode} % Now for the environemnts. @@ -4221,34 +4349,30 @@ local CommentLaTeX = * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" * L ( ( 1 - P "\r" ) ^ 0 ) * Lc "}}" - * ( EOL + -1 ) -- you could put EOL instead of EOL + * ( EOL + -1 ) % \end{macrocode} % % \bigskip % \paragraph{DefFunction} % -% The following \textsc{lpeg} |Expression| will be used for the parameters in +% The following \textsc{lpeg} |expression| will be used for the parameters in % the \emph{argspec} of a Python function. It's necessary to use a \emph{grammar} % because that pattern mainly checks the correct nesting of the delimiters % (and it's known in the theory of formal languages that this can't be done with % regular expressions \emph{stricto sensu} only). % \begin{macrocode} -local Expression = +local expression = P { "E" , - E = ( 1 - S "{}()[]\r," ) ^ 0 - * ( - ( P "{" * V "F" * P "}" - + P "(" * V "F" * P ")" - + P "[" * V "F" * P "]" ) * ( 1 - S "{}()[]\r," ) ^ 0 - ) ^ 0 , - F = ( 1 - S "{}()[]\r\"'" ) ^ 0 - * ( ( - P "'" * (P "\\'" + 1 - S"'\r" )^0 * P "'" - + P "\"" * (P "\\\"" + 1 - S"\"\r" )^0 * P "\"" - + P "{" * V "F" * P "}" - + P "(" * V "F" * P ")" - + P "[" * V "F" * P "]" - ) * ( 1 - S "{}()[]\r\"'" ) ^ 0 ) ^ 0 , + E = ( P "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * P "'" + + P "\"" * (P "\\\"" + 1 - S "\"\r" ) ^ 0 * P "\"" + + P "{" * V "F" * P "}" + + P "(" * V "F" * P ")" + + P "[" * V "F" * P "]" + + ( 1 - S "{}()[]\r," ) ) ^ 0 , + F = ( P "{" * V "F" * P "}" + + P "(" * V "F" * P ")" + + P "[" * V "F" * P "]" + + ( 1 - S "{}()[]\r\"'" ) ) ^ 0 } % \end{macrocode} % @@ -4269,8 +4393,8 @@ local Expression = local Param = SkipSpace * Identifier * SkipSpace * ( - K ( 'InitialValues' , P "=" * Expression ) - + Q ( P ":" ) * SkipSpace * K ( 'Name.Type' , letter^1 ) + K ( 'InitialValues' , P "=" * expression ) + + Q ( P ":" ) * SkipSpace * K ( 'Name.Type' , letter ^ 1 ) ) ^ -1 % \end{macrocode} % @@ -4342,7 +4466,7 @@ local DefFunction = % % \begin{macrocode} local ItemDict = - ShortString * SkipSpace * Q ( P ":" ) * K ( 'Dict.Value' , Expression ) + ShortString * SkipSpace * Q ( P ":" ) * K ( 'Dict.Value' , expression ) local ItemOfSet = SkipSpace * ( ItemDict + ShortString ) * SkipSpace @@ -4364,37 +4488,39 @@ local ExceptionInConsole = Exception * Q ( ( 1 - P "\r" ) ^ 0 ) * EOL % % First, the main loop : % \begin{macrocode} -MainLoopPython = - ( ( space^1 * -1 ) - + EOL +local MainPython = + EOL + Space + Tab + Escape + CommentLaTeX + Beamer - + UserCommands + LongString + Comment + ExceptionInConsole + Set + Delim -% \end{macrocode} -% |Operator| must be before |Punct|. -% \begin{macrocode} + Operator + + OperatorWord * ( Space + Punct + Delim + EOL + -1 ) + ShortString + Punct + FromImport + 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 ) + + Builtin * ( Space + Punct + Delim + EOL + -1 ) + Identifier + Number + Word +% \end{macrocode} +% +% Ici, il ne faut pas mettre |local| ! +% \begin{macrocode} +MainLoopPython = + ( ( space^1 * -1 ) + + MainPython ) ^ 0 % \end{macrocode} % @@ -4437,12 +4563,89 @@ local Delim = Q ( P "[|" + P "|]" + S "[()]" ) local Punct = Q ( S ",:;!" ) % \end{macrocode} % +% The identifiers catched by |cap_identifier| begin with a cap. In OCaml, it's +% used for the constructors of types and for the modules. +% \begin{macrocode} +local cap_identifier = R "AZ" * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 +% \end{macrocode} +% +% \begin{macrocode} +local Constructor = K ( 'Name.Constructor' , cap_identifier ) +local ModuleType = K ( 'Name.Type' , cap_identifier ) +% \end{macrocode} +% +% The identifiers which begin with a lower case letter of an underscore are used +% elsewhere in OCaml. % \begin{macrocode} local identifier = - ( R "az" + R "AZ" + P "_") * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 - + ( R "az" + P "_") * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 local Identifier = K ( 'Identifier' , identifier ) +% \end{macrocode} +% +% +% Now, we deal with the records because we want to catch the names of the fields +% of those records in all circunstancies. +% \begin{macrocode} +local expression_for_fields = + P { "E" , + E = ( P "{" * V "F" * P "}" + + P "(" * V "F" * P ")" + + P "[" * V "F" * P "]" + + P "\"" * (P "\\\"" + 1 - S "\"\r" )^0 * P "\"" + + P "'" * ( P "\\'" + 1 - S "'\r" )^0 * P "'" + + ( 1 - S "{}()[]\r;" ) ) ^ 0 , + F = ( P "{" * V "F" * P "}" + + P "(" * V "F" * P ")" + + P "[" * V "F" * P "]" + + ( 1 - S "{}()[]\r\"'" ) ) ^ 0 + } +% \end{macrocode} +% +% \begin{macrocode} +local OneFieldDefinition = + ( K ( 'KeyWord' , P "mutable" ) * SkipSpace ) ^ -1 + * K ( 'Name.Field' , identifier ) * SkipSpace + * Q ":" * SkipSpace + * K ( 'Name.Type' , expression_for_fields ) + * SkipSpace + +local OneField = + K ( 'Name.Field' , identifier ) * SkipSpace + * Q "=" * SkipSpace + * ( C ( expression_for_fields ) / ( function (s) return LoopOCaml:match(s) end ) ) + * SkipSpace + +local Record = + Q "{" * SkipSpace + * + ( + OneFieldDefinition * ( Q ";" * SkipSpace * OneFieldDefinition ) ^ 0 + + + OneField * ( Q ";" * SkipSpace * OneField ) ^ 0 + ) + * + Q "}" +% \end{macrocode} +% +% \bigskip +% Now, we deal with the notations with points (eg: |List.length|). In OCaml, +% such notation is used for the fields of the records and for the modules. +% \begin{macrocode} +local DotNotation = + ( + K ( 'Name.Module' , cap_identifier ) + * Q "." + * ( Identifier + Constructor + Q "(" + Q "[" + Q "{" ) + + + Identifier + * Q "." + * K ( 'Name.Field' , identifier ) + ) + * ( Q "." * K ( 'Name.Field' , identifier ) ) ^ 0 +% \end{macrocode} +% +% \begin{macrocode} local Operator = K ( 'Operator' , P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" @@ -4458,10 +4661,10 @@ local OperatorWord = local Keyword = 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 "assert" + P "as" + P "begin" + P "class" + P "constraint" + P "done" + + P "downto" + P "do" + P "else" + P "end" + P "exception" + P "external" + + P "false" + P "for" + P "function" + P "functor" + P "fun" + P "if" + + P "include" + P "inherit" + P "initializer" + P "in" + P "lazy" + P "let" + P "match" + P "method" + P "module" + P "mutable" + P "new" + P "object" + P "of" + P "open" + P "private" + P "raise" + P "rec" + P "sig" + P "struct" + P "then" + P "to" + P "true" + P "try" + P "type" @@ -4470,20 +4673,7 @@ local Keyword = local Builtin = - 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" - + P "List.iter" - + P "Array.length" + P "Array.make" + P "Array.make_matrix" - + P "Array.init" + P "Array.copy" + P "Array.copy" + P "Array.mem" - + P "Array.exists" + P "Array.for_all" + P "Array.map" + P "Array.iter" - + P "Queue.create" + P "Queue.is_empty" + P "Queue.push" + P "Queue.pop" - + P "Stack.create" + P "Stack.is_empty" + P "Stack.push" + P "Stack.pop" - + P "Hashtbl.create" + P "Hashtbl.add" + P "Hashtbl.remove" - + P "Hashtbl.mem" + P "Hashtbl.find" + P "Hashtbl.find_opt" - + P "Hashtbl.iter" ) + K ( 'Name.Builtin' , P "not" + P "incr" + P "decr" + P "fst" + P "snd" ) % \end{macrocode} % % \bigskip @@ -4510,7 +4700,7 @@ local Char = % \paragraph{Beamer} % % \begin{macrocode} -local BalancedBraces = +local balanced_braces = P { "E" , E = ( @@ -4539,7 +4729,7 @@ then ) * L ( ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 * P "{" ) - * K ( 'ParseAgain.noCR' , BalancedBraces ) + * K ( 'ParseAgain.noCR' , balanced_braces ) * L ( P "}" ) + L ( @@ -4547,9 +4737,9 @@ then * P "<" * (1 - P ">") ^ 0 * P ">" * P "{" ) - * K ( 'ParseAgain.noCR' , BalancedBraces ) + * K ( 'ParseAgain.noCR' , balanced_braces ) * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , BalancedBraces ) + * K ( 'ParseAgain.noCR' , balanced_braces ) * L ( P "}" ) + L ( @@ -4557,11 +4747,11 @@ then * P "<" * (1 - P ">") ^ 0 * P ">" * P "{" ) - * K ( 'ParseAgain.noCR' , BalancedBraces ) + * K ( 'ParseAgain.noCR' , balanced_braces ) * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , BalancedBraces ) + * K ( 'ParseAgain.noCR' , balanced_braces ) * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , BalancedBraces ) + * K ( 'ParseAgain.noCR' , balanced_braces ) * L ( P "}" ) BeamerBeginEnvironments = ( space ^ 0 * @@ -4614,7 +4804,7 @@ local EOL = % We need a pattern |string| without captures because it will be used within the % comments of OCaml. % \begin{macrocode} -local string = +local ocaml_string = Q ( P "\"" ) * ( VisualSpace @@ -4627,7 +4817,7 @@ local string = % \end{macrocode} % % \begin{macrocode} -local String = WithStyle ( 'String.Long' , string ) +local String = WithStyle ( 'String.Long' , ocaml_string ) % \end{macrocode} % % @@ -4693,7 +4883,7 @@ local Comment = A = Q "(*" * ( V "A" + Q ( ( 1 - P "(*" - P "*)" - S "\r$\"" ) ^ 1 ) -- $ - + string + + ocaml_string + P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" -- $ + EOL ) ^ 0 @@ -4705,12 +4895,100 @@ local Comment = % \paragraph{The DefFunction} % % \begin{macrocode} +local balanced_parens = + P { "E" , + E = + ( + P "(" * V "E" * P ")" + + + ( 1 - S "()" ) + ) ^ 0 + } +% \end{macrocode} +% +% \begin{macrocode} +local Argument = + K ( 'Identifier' , identifier ) + + Q "(" * SkipSpace + * K ( 'Identifier' , identifier ) * SkipSpace + * Q ":" * SkipSpace + * K ( 'Name.Type' , balanced_parens ) * SkipSpace + * Q ")" +% \end{macrocode} +% +% Despite its name, then \textsc{lpeg} |DefFunction| deals also with |let open| +% which opens locally a module. +% \begin{macrocode} local DefFunction = + K ( 'Keyword' , P "let open" ) + * Space + * K ( 'Name.Module' , cap_identifier ) + + K ( 'Keyword' , P "let rec" + P "let" + P "and" ) - * Space - * K ( 'Name.Function.Internal' , identifier ) - * Space - * # ( P "=" * space * P "function" + ( 1 - P "=" ) ) + * Space + * K ( 'Name.Function.Internal' , identifier ) + * Space + * ( + Q "=" * SkipSpace * K ( 'Keyword' , P "function" ) + + + Argument + * ( SkipSpace * Argument ) ^ 0 + * ( + SkipSpace + * Q ":" + * K ( 'Name.Type' , ( 1 - P "=" ) ^ 0 ) + ) ^ -1 + ) +% \end{macrocode} +% +% +% \bigskip +% \paragraph{The DefModule} +% +% The following LPEG will be used in the definitions of modules but also in the +% definitions of \emph{types} of modules. +% \begin{macrocode} +local DefModule = + K ( 'Keyword' , P "module" ) * Space + * + ( + K ( 'Keyword' , P "type" ) * Space + * K ( 'Name.Type' , cap_identifier ) + + + K ( 'Name.Module' , cap_identifier ) * SkipSpace + * + ( + Q "(" * SkipSpace + * K ( 'Name.Module' , cap_identifier ) * SkipSpace + * Q ":" * SkipSpace + * K ( 'Name.Type' , cap_identifier ) * SkipSpace + * + ( + Q "," * SkipSpace + * K ( 'Name.Module' , cap_identifier ) * SkipSpace + * Q ":" * SkipSpace + * K ( 'Name.Type' , cap_identifier ) * SkipSpace + ) ^ 0 + * Q ")" + ) ^ -1 + * + ( + Q "=" * SkipSpace + * K ( 'Name.Module' , cap_identifier ) * SkipSpace + * Q "(" + * K ( 'Name.Module' , cap_identifier ) * SkipSpace + * + ( + Q "," + * + K ( 'Name.Module' , cap_identifier ) * SkipSpace + ) ^ 0 + * Q ")" + ) ^ -1 + ) + + + K ( 'Keyword' , P "include" + P "open" ) + * Space * K ( 'Name.Module' , cap_identifier ) % \end{macrocode} % % \bigskip @@ -4725,9 +5003,8 @@ local TypeParameter = K ( 'TypeParameter' , P "'" * alpha * # ( 1 - P "'" ) ) % % First, the main loop : % \begin{macrocode} -MainLoopOCaml = - ( ( space^1 * -1 ) - + EOL +MainOCaml = + EOL + Space + Tab + Escape @@ -4739,15 +5016,24 @@ MainLoopOCaml = + Operator + Punct + FromImport - + ImportAs + Exception + DefFunction + + DefModule + + Record + Keyword * ( Space + Punct + Delim + EOL + -1 ) + OperatorWord * ( Space + Punct + Delim + EOL + -1 ) + Builtin * ( Space + Punct + Delim + EOL + -1 ) + + DotNotation + + Constructor + Identifier + Number + Word + +LoopOCaml = MainOCaml ^ 0 + +MainLoopOCaml = + ( ( space^1 * -1 ) + + MainOCaml ) ^ 0 % \end{macrocode} % @@ -4797,15 +5083,28 @@ function piton.Parse(language,code) if one_item[1] == "EOL" then for _ , s in ipairs(right_stack) - do tex.sprint( s ) + 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 ) + do tex.sprint(s) end else +% \end{macrocode} +% +% Here is an example of an item beginning with |"Open"|. +% +% |{ "Open" , "\begin{uncover}<2>" , "\end{cover}" }| +% +% In order to deal with the ends of lines, we have to close the environment +% (|{cover}| in this example) at the end of each line and reopen it at the +% beginning of the new line. That's why we use two Lua stacks, called +% |left_stack| and |right_stack|. |left_stack| will be for the elements like +% |\begin{uncover}<2>| and |right_stack| will be for the elements like +% |\end{cover}|. +% \begin{macrocode} if one_item[1] == "Open" then tex.sprint( one_item[2] ) @@ -4834,7 +5133,7 @@ end % then apply the function~|Parse| to the resulting Lua string. % \begin{macrocode} function piton.ParseFile(language,name,first_line,last_line) - s = '' + local s = '' local i = 0 for line in io.lines(name) do i = i + 1 @@ -4843,7 +5142,19 @@ function piton.ParseFile(language,name,first_line,last_line) end if i >= last_line then break end end - piton.Parse(language,s) +% \end{macrocode} +% We extract the BOM of utf-8, if present. +% \begin{macrocode} + if string.byte(s,1) == 13 + then if string.byte(s,2) == 239 + then if string.byte(s,3) == 187 + then if string.byte(s,4) == 191 + then s = string.sub(s,5,-1) + end + end + end + end + piton.Parse(language,s) end % \end{macrocode} % @@ -5070,7 +5381,21 @@ end % \nolinkurl{https://tug.org/svn/texlive/trunk/Master/texmf-dist/tex/lualatex/piton/piton.sty} % } % -% % \subsection*{Changes between versions 1.4 and 1.5} +% \medskip +% The development of the extension \pkg{piton} is done on the following GitHub +% repository: +% +% \verb|https://github.com/fpantigny/piton| +% +% \subsection*{Changes between versions 1.5 and 1.6} +% +% New key |width| (for the total width of the listing). +% +% New style |UserFunction| to format the names of the Python functions +% previously defined by the user. Command |\PitonClearUserFunctions| to clear +% the list of such functions names. +% +% \subsection*{Changes between versions 1.4 and 1.5} % % New key |numbers-sep|. % |