diff options
author | Karl Berry <karl@freefriends.org> | 2022-12-23 21:04:23 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2022-12-23 21:04:23 +0000 |
commit | 3380912e470b2169b6c54166d32f14d631d63270 (patch) | |
tree | e84177a9effa207f76020b4aff5f0d263dd299d3 /Master | |
parent | 8d383d484835575910b71ef5e1746d57be9afef3 (diff) |
saveenv (23dec22)
git-svn-id: svn://tug.org/texlive/trunk@65340 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rw-r--r-- | Master/texmf-dist/doc/latex/saveenv/saveenv.pdf | bin | 384203 -> 395762 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/saveenv/saveenv.tex | 78 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/saveenv/saveenv.sty | 59 |
3 files changed, 106 insertions, 31 deletions
diff --git a/Master/texmf-dist/doc/latex/saveenv/saveenv.pdf b/Master/texmf-dist/doc/latex/saveenv/saveenv.pdf Binary files differindex 20bf11c9fd9..f93c230efa9 100644 --- a/Master/texmf-dist/doc/latex/saveenv/saveenv.pdf +++ b/Master/texmf-dist/doc/latex/saveenv/saveenv.pdf diff --git a/Master/texmf-dist/doc/latex/saveenv/saveenv.tex b/Master/texmf-dist/doc/latex/saveenv/saveenv.tex index c6d4ba87bb8..5a5f741a250 100644 --- a/Master/texmf-dist/doc/latex/saveenv/saveenv.tex +++ b/Master/texmf-dist/doc/latex/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} diff --git a/Master/texmf-dist/tex/latex/saveenv/saveenv.sty b/Master/texmf-dist/tex/latex/saveenv/saveenv.sty index 454275c878e..9a694a5f4d5 100644 --- a/Master/texmf-dist/tex/latex/saveenv/saveenv.sty +++ b/Master/texmf-dist/tex/latex/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 } |