summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/saveenv
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/saveenv')
-rw-r--r--macros/latex/contrib/saveenv/saveenv.pdfbin384203 -> 395762 bytes
-rw-r--r--macros/latex/contrib/saveenv/saveenv.sty59
-rw-r--r--macros/latex/contrib/saveenv/saveenv.tex78
3 files changed, 106 insertions, 31 deletions
diff --git a/macros/latex/contrib/saveenv/saveenv.pdf b/macros/latex/contrib/saveenv/saveenv.pdf
index 20bf11c9fd..f93c230efa 100644
--- a/macros/latex/contrib/saveenv/saveenv.pdf
+++ b/macros/latex/contrib/saveenv/saveenv.pdf
Binary files differ
diff --git a/macros/latex/contrib/saveenv/saveenv.sty b/macros/latex/contrib/saveenv/saveenv.sty
index 454275c878..9a694a5f4d 100644
--- a/macros/latex/contrib/saveenv/saveenv.sty
+++ b/macros/latex/contrib/saveenv/saveenv.sty
@@ -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
}
diff --git a/macros/latex/contrib/saveenv/saveenv.tex b/macros/latex/contrib/saveenv/saveenv.tex
index c6d4ba87bb..5a5f741a25 100644
--- a/macros/latex/contrib/saveenv/saveenv.tex
+++ b/macros/latex/contrib/saveenv/saveenv.tex
@@ -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 @@ This package provides tools to create your own verbatim environments, and works
\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 @@ This package provides tools to create your own verbatim environments, and works
\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,17 +91,28 @@ but inside \cs{ExplSyntaxOn} environment it generates a spurious space at the be
Environment that saves its body.
For example, the following code
-
\begin{verbatim}
\begin{saveenv}{\data}
123
456
\end{saveenv}
\end{verbatim}
+will save the string \texttt{123\meta{newline}456\meta{newline}} globally into |\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}
-will save the string \texttt{123\meta{newline}456} globally into \cs{data}.
+\end{saveenv}
+\end{verbatim}
+will make |\data| consist of a single \meta{newline}.
-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.
+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.
@@ -116,7 +127,7 @@ The assignment is global, and done before the macro \cs{endsaveenv} is executed.
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,7 +138,43 @@ Note that this environment is implemented by reading the whole file from the beg
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}
@@ -148,6 +195,8 @@ For example, the following definition
\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 @@ will define an environment \env{custom} that prints out the content inside the e
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 @@ will define an environment \env{custom} that prints out the content inside the e
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}