I'm trying to rewrite some of the codes I have by following the correct expl3 rules. With the following code I define the scontents environment that encapsulates the filecontentsdefmacro environment of the filecontentsdef package using xparse/expl3. Everything works OK, I get to record the content of scontents in a sequence and then I can access it, the theme is the way I get it. The original package has the \filecontentsexec macro to run the content recorded by the filecontentsdefmacro environment, but, I haven't been able to make this work for me and have had to copy almost directly the definition directly from the package and write it in terms of expl3. Like this:
% Expand \l_scontents_macro_tmp_tl and pass to seq
\cs_new_protected:Nn \_scontents_macro_to_seq:
{
\tl_put_right:Nx \l_tmpa_tl
{
\tex_newlinechar:D = 13
\tex_everyeof:D = { \exp_not:N }
\exp_not:N \scantokens \exp_after:wN { \tl_use:c { l_scontents_macro_tmp_tl } }
\tex_newlinechar:D = 10 \scan_stop:
}
\tl_put_right:Nx \l_tmpb_tl
{
\exp_not:N \_scontents_append_contents:nn
{
\exp_not:V \l_scontents_name_seq_tl
}
{ \exp_not:V \l_tmpa_tl }
}
\l_tmpb_tl % add to seq
}
The problem is that I use (and abuse) the :D argument that as far as I've read, it shouldn't be occupied, my idea was to be able to use something shorter, similar to this:
% Expand \l_scontents_macro_tmp_tl and pass to seq
\cs_new_protected:Nn \_scontents_macro_to_seq:
{
\_scontents_append_contents:nn { \l_scontents_name_seq_tl }
{
\filecontentsexec \exp_after:wN { \tl_use:c { l_scontents_macro_tmp_tl } }
}
}
This is the complete example file:
\documentclass{article}
\usepackage{filecontentsdef}[2019/04/20]
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:c { l_scontents_macro_tmp_tl }
\keys_define:nn { scontents }
{
save-env .tl_set:N = \l_scontents_name_seq_tl,
save-env .initial:n = contents,
show-env .bool_set:N = \l_scontents_show_env_tl,
show-env .initial:n = false
}
% Adapted from https://tex.stackexchange.com/a/215571/7832
\cs_new_protected:Npn \_scontents_append_contents:nn #1 #2
{
\seq_if_exist:cF { g_scontents_seq_name_#1_seq }
{
\seq_new:c { g_scontents_seq_name_#1_seq }
}
\seq_gput_right:cn { g_scontents_seq_name_#1_seq } { #2 }
}
\cs_new_protected:Npn \_scontents_getfrom_seq:nn #1 #2
{
\seq_item:cn { g_scontents_seq_name_#2_seq } { #1 }
}
\ProvideExpandableDocumentCommand{\getstored}{ O{1} m }
{
\_scontents_getfrom_seq:nn { #1 } { #2 }
}
% Define environment ( wrap \filecontentsdefmacro )
% Adapted from https://tex.stackexchange.com/a/487746/7832
\ProvideDocumentEnvironment{ scontents }{}
{
\char_set_catcode_active:N \^^M
\scontents_start_environment:w
}
{
\scontents_stop_environment:
\scontents_atend_environment:
}
% Delaying [key=val] for environment
\cs_new_protected:Npn \scontents_environment_keys:w [#1]
{
\keys_set:nn { scontents } { #1 }
}
% Star environment
\group_begin:
\char_set_catcode_active:N \^^M
\cs_new_protected:Npn \scontents_start_environment:w #1 ^^M
{
\tl_if_blank:nF { #1 } { \scontents_environment_keys:w #1 }
\group_begin: % open a group for environment
\use:c { filecontentsdefmacro } { \l_scontents_macro_tmp_tl } ^^M
}
\group_end:
% Stop environment
\cs_new_protected:Nn \scontents_stop_environment:
{
\endfilecontentsdefmacro
\group_end: % close a group for environment
}
% Expand \l_scontents_macro_tmp_tl and pass to seq
\cs_new_protected:Nn \_scontents_macro_to_seq:
{
\tl_put_right:Nx \l_tmpa_tl
{
\tex_newlinechar:D = 13
\tex_everyeof:D = { \exp_not:N }
\exp_not:N \scantokens \exp_after:wN { \tl_use:c { l_scontents_macro_tmp_tl } }
\tex_newlinechar:D = 10 \scan_stop:
}
\tl_put_right:Nx \l_tmpb_tl
{
\exp_not:N \_scontents_append_contents:nn
{
\exp_not:V \l_scontents_name_seq_tl
}
{ \exp_not:V \l_tmpa_tl }
}
\l_tmpb_tl % add to seq
}
% Execution of the code after finishing the scontent environment
\cs_new_protected:Nn \scontents_atend_environment:
{
\_scontents_macro_to_seq:
\bool_if:NT \l_scontents_show_env_tl
{
\_scontents_getfrom_seq:nn { -1 }{ \l_scontents_name_seq_tl }
}
\cs_undefine:N \l_scontents_macro_tmp_tl
}
\ExplSyntaxOff
\setlength{\parindent}{0pt} % just for the example
\begin{document}
\section*{Test environment}
Test \verb+\begin{scontents}+ no \verb+[key=val]+\par
\begin{scontents}
Using \verb+scontents+ env no \verb+[key=val]+, save in
\verb+contents+ with index 1. \footnote{AND footnotes !!}
\begin{verbatim}
(A) verbatim environment
\end{verbatim}
\end{scontents}
Test \verb+\begin{scontents}[save-env=other]+\par
\begin{scontents}[save-env=other]
Using \verb+scontents+ env with \verb+[save-env=other]+, save in
\verb+other+ with index 1.
\begin{verbatim*}
(B) verbatim environment
\end{verbatim*}
\end{scontents}
\section*{Show stored contents}
\getstored[1]{other}
\getstored[1]{contents}
\end{document}
I have tried to write the code following the "rules" (and what I have learned in the forum), if something is badly written (related to expansion or cs), please correct me accordingly.
Greetings.
:Dand\scantokens, that is to say, to place something more in the line ofexpl3? – Pablo González L Jun 18 '19 at 13:17\tl_set_rescan:Nnn. Looking at the code, this function seems to implement basically the same pattern as your\scantokenscode. I'm not sure how well that would work in conjunction withfilecontentsdef, though. – siracusa Jun 18 '19 at 22:44\tl_set_rescan:Nnn, if you have some time, could you extend your answer using\tl_set_rescan:Nnn? Ifexpl3has a function equal to\scantokensI think it would be correct to use it. Saludos – Pablo González L Jun 19 '19 at 00:35\tl_set_rescanbut I couldn't make it work. Not sure if this function isn't supposed to work with verbatim commands or I'm just using it wrong. Also for multiline text all spaces seem to be stripped even at the beginning of lines. – siracusa Jun 19 '19 at 04:00\newlinecharin the{setup}of\tl_set_rescan(I think). – Pablo González L Jun 19 '19 at 11:18