texlive[65340] Master/texmf-dist: saveenv (23dec22)

commits+karl at tug.org commits+karl at tug.org
Fri Dec 23 22:04:23 CET 2022


Revision: 65340
          http://tug.org/svn/texlive?view=revision&revision=65340
Author:   karl
Date:     2022-12-23 22:04:23 +0100 (Fri, 23 Dec 2022)
Log Message:
-----------
saveenv (23dec22)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/saveenv/saveenv.pdf
    trunk/Master/texmf-dist/doc/latex/saveenv/saveenv.tex
    trunk/Master/texmf-dist/tex/latex/saveenv/saveenv.sty

Modified: trunk/Master/texmf-dist/doc/latex/saveenv/saveenv.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/saveenv/saveenv.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/saveenv/saveenv.tex	2022-12-23 21:03:50 UTC (rev 65339)
+++ trunk/Master/texmf-dist/doc/latex/saveenv/saveenv.tex	2022-12-23 21:04:23 UTC (rev 65340)
@@ -1,5 +1,5 @@
 %%! TEX program = lualatex
-\ProvidesFile{saveenv.tex} [2022/07/08 v0.0.0 ]
+\ProvidesFile{saveenv.tex} [2022/12/23 v0.0.1 ]
 \documentclass{l3doc}
 \EnableCrossrefs
 \CodelineIndex
@@ -41,8 +41,8 @@
 
 \begin{itemize}
 	\item \pkg{scontents} package is similar; however it does not allow programmer to programmatically retrieve the macro content, only do a limited number of actions with them (execute, typeset as verbatim code, etc.).
-	\item \pkg{fancyvrb} and \pkg{verbatimcopy} provides some internal macro for defining similar environments, however they're internal.
-	\item \pkg{filecontentsdef} and \pkg{newverbs} provides very similar facilities (\env{filecontentsdefmacro} environment and \tn{Collectverbenv} command respectively); however it requires \verb+\endlinechar=13+ and does not support \cs{ExplSyntaxOn} environment.
+	\item \pkg{fancyvrb}, \pkg{xsimverb} and \pkg{verbatimcopy} provides some internal macro for defining similar environments, however they're internal and/or too specialized (writes to file etc.).
+	\item \pkg{filecontentsdef} and \pkg{newverbs} provides very similar facilities (\env{filecontentsdefmacro} environment and |\Collectverbenv| command respectively); however it requires |\endlinechar=13| and does not support |\ExplSyntaxOn| environment.
 	\item \pkg{verbatim} provides facilities to define custom verbatim environment that processes the content line-by-line, however the interface is more complicated.
 
 		For comparison, the following code
@@ -80,7 +80,7 @@
 \end{verbatim}
 
 defines an environment that saves the data similar to \env{saveenv} environment described below (with the overhead of |\tl_build_*| functions),
-but inside \cs{ExplSyntaxOn} environment it generates a spurious space at the beginning of the string.
+but inside |\ExplSyntaxOn| environment it generates a spurious space at the beginning of the string.
 \end{itemize}
 
 
@@ -91,7 +91,6 @@
   Environment that saves its body.
   
   For example, the following code
-
 \begin{verbatim}
 \begin{saveenv}{\data}
 123
@@ -98,11 +97,23 @@
 456
 \end{saveenv}
 \end{verbatim}
+will save the string \texttt{123\meta{newline}456\meta{newline}} globally into |\data|.
 
-will save the string \texttt{123\meta{newline}456} globally into \cs{data}.
+Remark: it is consistent to keep the trailing newline, as
+\begin{verbatim}
+\begin{saveenv}{\data}
+\end{saveenv}
+\end{verbatim}
+will make |\data| empty, and
+\begin{verbatim}
+\begin{saveenv}{\data}
 
-The braces around \verb+{\data}+ is optional; however, in the unlikely case if \cs{endlinechar} has the \enquote{letter} catcode, it might be absorbed and gives unexpected result.
+\end{saveenv}
+\end{verbatim}
+will make |\data| consist of a single \meta{newline}.
 
+The braces around |{\data}| is optional; however, in the unlikely case if \cs{endlinechar} has the \enquote{letter} catcode, it might be absorbed and gives unexpected result.
+
 A newline is represented as a token with charcode 10 (|^^J|) and catcode other.
 
 \textbf{Note} that this is unusual, for comparison \pkg{filecontentsdef} stores it as an active |^^M|.
@@ -116,7 +127,7 @@
 
 The data is represented as an \pkg{expl3}-string, that is, a sequence of tokens with catcode 12 (for non-space characters) or 10 (for space character).
 
-In other words, the token list is equal to its own \cs{detokenize}.
+In other words, the token list is equal to its own |\detokenize|.
 
 \DescribeEnv{saveenvghost}
 Similar to above; however the content inside is still typesetted/executed, and the Sync\TeX\ information is preserved.
@@ -127,8 +138,44 @@
 Similar to above; however the final newline and the space characters before \texttt{\cs{end}\{\meta{environment name}\}} are preserved.
 
 For example, the example above with \texttt{saveenv} replaced with \texttt{saveenvkeeplast}
-will save the string \texttt{123\meta{newline}456\meta{newline}} into \cs{data} instead.
+will save the string \texttt{123\meta{newline}456\meta{newline}} into |\data| instead.
 
+\section{Reinsert environments}
+
+Sometimes it's desirable to execute something (e.g. do some local assignments) after the group ends.
+
+There are a few options:
+\begin{itemize}
+	\item use |\aftergroup|,
+	\item close the group, execute the code and open a new one (remember to preserve the value of |\@currenvir|),
+	\item use one of the environments below.
+\end{itemize}
+
+\DescribeEnv{saveenvreinsert}
+Environment that takes two arguments, the \meta{str var} to be set and the code to be put after the group end.
+
+Usage example: If the following code is executed
+\begin{verbatim}
+\begin{saveenvreinsert}{\data}{\myfunction {args etc.}}
+123
+456
+\end{saveenvreinsert}
+some other content
+\end{verbatim}
+the effect would be identical to as if |\data| is set to \texttt{123\meta{newline}456\meta{newline}},
+then the following code is executed
+\begin{verbatim}
+\myfunction {args etc.}some other content
+\end{verbatim}
+If the second argument is empty, this environment is identical to the \env{saveenv} environment.
+
+Note that in the example above |\myfunction| is executed after the group ends,
+while any code in the second block of the |\NewDocumentEnvironment| definition
+would be executed before the group ends (such as in the example below), thus any local assignment will not persist.
+
+\DescribeEnv{saveenvkeeplastreinsert}
+Same as above, but the trailing whitespaces (after the last newline) are preserved.
+
 \section{Extending the environments}
 
 All of the environments are extensible.
@@ -148,6 +195,8 @@
 \end{verbatim}
 will define an environment \env{custom} that prints out the content inside the environment using |\tl_show:N|.
 
+Note that in this case |\tl_show:N \data| is executed before the group ends.
+
 \section{Limitation}
 
 \begin{itemize}
@@ -157,13 +206,15 @@
 
 				Nevertheless, in modern computers, the overhead is negligible.
 			\item In case it's desired to typeset the content afterwards, it's difficult to preserve the Sync\TeX\ data.
+
+				(although with Lua\LaTeX\ it's possible, see \pkg{rescansync} package)
 		\end{itemize}
 		
 	\item Currently nested environments with the same name are not supported (unlike \pkg{scontents} package).
 
-	\item Note that there must be nothing after the \texttt{\cs{begin}\{\meta{environment name}\}} or the \texttt{\cs{end}\{\meta{environment name}\}} line.
+	\item Note that there must be nothing after the |\begin|\texttt{\{\meta{environment name}\}} or the |\end|\texttt{\{\meta{environment name}\}} line.
 
-	\item Note that \texttt{\cs{end}\{\meta{environment name}\}} must not be in the middle of any line.
+	\item Note that |\end|\texttt{\{\meta{environment name}\}} must not be in the middle of any line.
 
 	\item The \cs{endlinechar} must not be tokenized in advance (or if it is, its catcode must be 12/other).
 		This might happen when for example your environment looks ahead for optional argument.
@@ -172,10 +223,9 @@
 		Alternatively, you can 
 		\begin{itemize}
 			\item manually remove the end line token,
-			\item set \verb+\endlinechar=-1\relax+ before calling \cs{saveenv}
-			\item (optional) reset the value of \cs{endlinechar} afterwards.
-				
+			\item set |\endlinechar=-1\relax| inside the environment before calling \cs{saveenv}.
 		\end{itemize}
+		The value of |\endlinechar| will automatically be reset after the group of the environment is closed.
 \end{itemize}
 
 

Modified: trunk/Master/texmf-dist/tex/latex/saveenv/saveenv.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/saveenv/saveenv.sty	2022-12-23 21:03:50 UTC (rev 65339)
+++ trunk/Master/texmf-dist/tex/latex/saveenv/saveenv.sty	2022-12-23 21:04:23 UTC (rev 65340)
@@ -12,7 +12,7 @@
 % 
 % The Current Maintainer of this work is user202729.
 
-\ProvidesExplPackage{saveenv}{2022/07/08}{0.0.0}{Save environment content verbatim}
+\ProvidesExplPackage{saveenv}{2022/12/23}{0.0.1}{Save environment content verbatim}
 \RequirePackage{precattl}
 \msg_new:nnn {saveenv} {trailing-content-or-pretokenized}
 	{Trailing~content~found~on~line,~or~content~pretokenized!}
@@ -51,14 +51,11 @@
 
 	\tl_build_gbegin:N #1
 
-	\prg_replicate:nn {\the\inputlineno-\_senv_firstline-2} {
+	\prg_replicate:nn {\the\inputlineno-\_senv_firstline-1} {
 		\ior_str_get:NN \_senv_file \_senv_line
-		\exp_args:NNo \tl_build_gput_right:Nn #1 {\_senv_line \cO\^^J}
+		\exp_args:NNo \tl_build_gput_right:Nn #1 {\_senv_line ^^J}
 	}
 
-	\ior_str_get:NN \_senv_file \_senv_line
-	\exp_args:NNo \tl_build_gput_right:Nn #1 {\_senv_line}
-
 	\ior_close:N \_senv_file
 
 	\tl_build_gend:N #1
@@ -67,16 +64,19 @@
 
 
 % #1: target macro
-\NewDocumentEnvironment {saveenvkeeplast} {m} {
+% #2: content to be inserted after the \end
+\NewDocumentEnvironment {saveenvkeeplastreinsert} {mm} {
 	\begingroup
 	\edef \_senv_old_endlinechar {\the\endlinechar}
+	%\bench before cctab.
 	\cctab_select:N \c_other_cctab  % note that this changes the value of \endlinechar as well
+	%\bench after cctab.
 	\int_compare:nNnTF {\_senv_old_endlinechar} < {0} {
-		\_senv_start_get_body:N #1
+		\_senv_start_get_body:Nn #1 {#2}
 	} {
 		\exp_last_unbraced:Nf \peek_meaning_remove:NTF { \char_generate:nn{\_senv_old_endlinechar}{12} }    %12 is other
 		{
-			\_senv_start_get_body:N #1
+			\_senv_start_get_body:Nn #1 {#2}
 		}
 		{
 			\msg_error:nn {saveenv} {trailing-content-or-pretokenized}
@@ -85,24 +85,33 @@
 } {
 }
 
+
 % #1: target macro
-\cs_new_protected:Npn \_senv_start_get_body:N #1 {
+% #2: content to be inserted after the \end
+\cs_new_protected:Npn \_senv_start_get_body:Nn #1 #2 {
 	\endlinechar=10~
 	\str_set:NV \_senv_env \@currenvir
 	\tl_replace_all:Nnn \_senv_env {~} {\cO\  }
-	\exp_args:NNVV \_senv_helper #1 \_senv_env \@currenvir
+	\_senv_helper:NVVn #1 \_senv_env \@currenvir {#2}
 }
 
 % #1: target macro
 % #2: value of \@currenvir but with all tokens catcode 12 (other)
 % #3: value of \@currenvir
-\def \_senv_helper #1 #2 #3 {
+% #4 content to be inserted after the \end
+\cs_new_protected:Npn \_senv_helper:Nnnn #1 #2 #3 #4 {
 	\cs_set_protected:cpn {[saveenv]~verbatim~body~scanner~for~#2} ##1 \cO{ \\end\{ } #2 \cO\} {
+		%\bench X3.
 		% ##1: the body
-		\peek_meaning_remove:NTF \cO\^^J {
+		\peek_meaning_remove:NTF ^^J {
+			%\bench inside peek.
 			\endgroup
+			%\bench after endgroup.
 			\str_gset:Nn #1 {##1}
+			%\bench X5.
 			\end{#3}
+			%\bench X6.
+			#4
 		} {
 			\msg_error:nn {saveenv} {trailing-content-end-line}
 		}
@@ -110,14 +119,23 @@
 
 	\use:c {[saveenv]~verbatim~body~scanner~for~#2}
 }
+\cs_generate_variant:Nn \_senv_helper:Nnnn {NVVn}
 
+\NewDocumentEnvironment {saveenvkeeplast} {m} {
+	\saveenvkeeplastreinsert #1 {}
+} {
+	\endsaveenvkeeplastreinsert
+}
+
 % set variable #1 to have content of #2, but with last line dropped.
 % lines are separated by \^^J.
 
+\cs_new:Npn \_senv_append_newline:n #1 { #1 ^^J }
+
 \cs_new_protected:Npn \saveenv_set_drop_last:Nn #1 #2 {
 	\tl_set:Nn \_senv_body {#2}
 	\tl_replace_all:Nnn \_senv_body {~} {\cO\  }  % keep spaces in seq_set_split (support older expl3 versions)
-	\seq_set_split:NnV \_senv_lines {\cO\^^J} \_senv_body
+	\seq_set_split:NnV \_senv_lines {^^J} \_senv_body
 	\seq_pop_right:NN \_senv_lines \_senv_lastline
 	\tl_map_inline:Nn \_senv_lastline {  % debug check, ensure last line is empty
 		\int_case:nnF {`##1}  {
@@ -128,17 +146,24 @@
 			\msg_error:nnoVV {saveenv} {leading-content-last-line} {\number`##1} \_senv_lastline \@currenvir
 		}
 	}
-	\str_gset:Nx #1 {\seq_use:Nn \_senv_lines {\cO\^^J}}
+	%\str_gset:Nx #1 {\seq_use:Nn \_senv_lines {^^J}}  % this is extremely slow because \seq_use:Nn is ⋆-expandable
+	\str_gset:Nx #1 {\seq_map_function:NN \_senv_lines \_senv_append_newline:n }
 }
 
 \cs_generate_variant:Nn \saveenv_set_drop_last:Nn {NV}
 
+\NewDocumentEnvironment {saveenvreinsert} {mm} {
+	\saveenvkeeplastreinsert #1 {#2}
+} {
+	\endsaveenvkeeplastreinsert
+	\saveenv_set_drop_last:NV #1 #1
+}
 
 \NewDocumentEnvironment {saveenv} {m} {
-	\saveenvkeeplast \_senv_content
+	\saveenvkeeplast #1
 } {
 	\endsaveenvkeeplast
-	\saveenv_set_drop_last:NV #1 \_senv_content
+	\saveenv_set_drop_last:NV #1 #1
 }
 
 



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