1

I am trying to encapsulate a couple of environments to pass them to lists using xparse/expl3. I have defined a one command and two environments and I have had a problem with one of them.

I use the environments to save notes type question/answer where the answers are stored in a list to show them at the end of the file or elsewhere in it, the issue is that sometimes need to use verbatim.

The scontent environment uses the +b argument of xparse and only Verb[...]{...} (from fvextra) can be used (you can not use the verbatim environment for example).

The scontent* environment is based on filecontentsdef and can use verb|...| in a line or \begin{verbatim} environment, this generates an external file but has the facility of saving the content in a \macro.

When executing \begin{scontent*} pass the following:

  1. Save the current content in \macro
  2. Copy the current contents of \macro in \l_my_macro_copy_tl
  3. Pass the contents of \l_my_macro_copy_tl to list using \expanddafter\envtolist\expanddafter{ content save in \l_my_macro_copy_tl}
  4. If this is the key [show-env = true] run \usecontent[-1]{\l_scontent_env_save_tl}

The problem is in the execution of

\expanddafter\envtolist\expanddafter{\l_my_macro_copy_tl}

at end of environment scontent*, I tried with the following (ugly and incorrect) lines:

% \begin{scontent*}[...] verbatim env save in \macro
% Copy a current content of \macro in \l_my_macro_copy_tl and pass to list
\tl_new:N \l_my_macro_copy_tl
\NewDocumentEnvironment{scontent*}{ !O{} }
 { 
  \group_begin:
  \filecontentsdef{\jobname.tsc}{\macro} % save in \macro
 }{
  \endfilecontentsdef %
  \group_end:
  \IfNoValueF {#1} { \keys_set:nn { scontent } {#1} }
  \tl_set:Nx \l_my_macro_copy_tl \macro 
  \exp_after:wN \envtolist \exp_after:wN { \exp_not:N \tex_newlinechar:D = 13 \exp_not:N \scantokens \exp_after:wN { \l_my_macro_copy_tl } }%
  \IfBooleanT { \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }
  }

with this I eliminate the errors when compiling, but, the content is not saved in the list...How can i fix this?

My idea is not to occupy directly \showme{...} and only use \usecontent[index]{list name} in document.

I know that the command \showme{...} and \usecontent[index]{list name} works if you execute it out of the environment, but my idea is automate this when run scontent*.

This is my example file (MWE), the comments should be removed to see the error that occurs.

\documentclass{article}
\usepackage{filecontentsdef,etoolbox,xparse,fvextra,xcolor}
\usepackage[margin=0.6in,noheadfoot,papersize={8.5in,13in}]{geometry}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\ExplSyntaxOn
% show content save in \macro
\tl_new:N \l_temp_argument_tl
\NewDocumentCommand\showme{ +m }{%
 \tl_set:Nx \l_temp_argument_tl { #1 }
 \tex_newlinechar:D = 13
 \exp_not:N { \scantokens \exp_after:wN { \l_temp_argument_tl } }
}

% \elementin{listname} and \clearlist{listname}
\cs_new:Npn \elementin #1 { \seq_count:c {l_savecontent_content_#1_seq} }
\cs_new:Npn \clearlist #1 { \seq_clear_new:c {l_savecontent_content_#1_seq} }

% \addcontent{listname}{{#1}} ...need double {{...}}
\NewDocumentCommand{\addcontent}{ m +m } { \savecontent_add_content:nn { #1 } { #2 } }

% \usecontent[index]{listname}
\DeclareExpandableDocumentCommand{\usecontent}{O{1}m} { \savecontent_use_content:nn { #1 } { #2 } }

\cs_new_protected:Npn \savecontent_add_content:nn #1 #2
 {
 \seq_if_exist:cF { l_savecontent_content_#1_seq }
    { \seq_new:c { l_savecontent_content_#1_seq } }
 \__savecontent_add_content:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \__savecontent_add_content:nn #1 #2
 {
    \tl_map_inline:nn { #2 }
  {
    \seq_gput_right:cn { l_savecontent_content_#1_seq } { ##1 }
  }
 }

\cs_new:Npn \savecontent_use_content:nn #1 #2 { \seq_item:cn { l_savecontent_content_#2_seq } { #1 } }

\keys_define:nn { scontent }
 {
    save-cmd .tl_set:N   = \l_scontent_cmd_save_tl, save-cmd .initial:n  = content,%
    save-env .tl_set:N   = \l_scontent_env_save_tl, save-env .initial:n  = content, %
    show-cmd .bool_set:N = \l_scontent_cmd_show_tl, show-cmd .initial:n  = false, show-cmd .value_required:n = true,%
    show-env .bool_set:N = \l_scontent_env_show_tl, show-env .initial:n  = false, show-env .value_required:n = true,%
    show-all .meta:n     = { show-env = true , show-cmd = true },%
 }

\NewDocumentCommand{\Setscontent}{ +m } { \keys_set:nn { scontent } {#1} }

% pass to list
\newrobustcmd{\envtolist}[1]{\addcontent{ \l_scontent_env_save_tl }{{#1}}}

% \Scontent[...]{...} NO verbatim env support, but \Verb[...]{...} yes
\NewDocumentCommand{\Scontent}{ O{} +m }
 {
  \group_begin:
  \IfNoValueF{#1} { \keys_set:nn { scontent } {#1} }
  \addcontent{ \l_scontent_cmd_save_tl }{ { #2 } } % pass direct to list
  \IfBooleanT{ \l_scontent_cmd_show_tl } { \usecontent[-1]{ \l_scontent_cmd_save_tl} }
  \group_end:
 }

% \begin{scontent}[...] NO verbatim env suport, but \Verb[...]{...} yes
\NewDocumentEnvironment{scontent}{ !o +b }
 {
  \group_begin:
  \IfNoValueF {#1} { \keys_set:nn { scontent } {#1} }
 }{
  \expandafter\envtolist\expandafter{#2}
  \IfBooleanT { \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }
  \group_end:
 }

% \begin{scontent*}[...] verbatim env save in \macro
\tl_new:N \l_my_macro_copy_tl % \tl_var to copy \macro at definition time
\NewDocumentEnvironment{scontent*}{ !O{} }
 {
  \group_begin:
  \IfNoValueF {#1} { \keys_set:nn { scontent } {#1} }
  \filecontentsdef{\jobname.tsc}{\macro}
 }{
  \endfilecontentsdef %
  \group_end:
  % Copy \macro every time in \tl_var (at definition time) and pass to list
  %\cs_set_eq:NN \l_my_macro_copy_tl \macro
  %\expandafter\envtolist\expandafter\showme{\l_my_macro_copy_tl}
  %\IfBooleanT { \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }    
 }
\ExplSyntaxOff
% set name of lists
\Setscontent{ save-env=test-env, save-cmd=test-cmd }
\begin{document}
\section{Using \texttt{scontent} environment whit new \texttt{+b} argument from \texttt{xparse}}
\subsection{Whit \texttt{[show-env=false]}}
Text save in \verb|\begin{scontent}[show-env=false]| (hidden)

\begin{scontent}[show-env=false]
Some first text whit verbatim inline saved in \Verb{\usecontent[1]{test-env}} \par
We have coded this in \LaTeX: both $E=mc^2$.
\end{scontent}

OK
\subsection{Whit \texttt{[show-env=true]}}
Text save in \verb|\begin{scontent}[show-env=true]| (Not hidden)

\begin{scontent}[show-env=true]
Some second text whit verbatim inline saved in \Verb{\usecontent[2]{test-env}}...more text \par
We have coded this in \LaTeX: both $E=mc^2$.
\end{scontent}

OK
\subsection{Using \Verb{\usecontent[1]{test-env}}}
Now see saved text in list:\par
\usecontent[2]{test-env}\par
\usecontent[1]{test-env}

\section{Using \Verb*{\Scontent[...]{...}}}
Text save whit \verb|\Scontent{....}| (hidden)\par
\Scontent{
using a \Verb*{\Scontent[...]{...}} \textcolor{red}{whit verbatim}  \Verb*{\Verb[...]{...}}\par
(by \Verb*{fvextra}) \textcolor{magenta}{inline}
}\par

And see saved text in list using \verb|\usecontent[1]{test-cmd}| \par
\usecontent[1]{test-cmd}\par
OK
\section{Using \texttt{scontent*} environment wraped \texttt{filecontentsdef} using \texttt{xparse}}

\subsection{Whit \texttt{[show-env=false]}}
Some Text save using \verb|\begin{scontent*}[show-env=false]| save in \verb|\macro| (hidden)

\begin{scontent*}[show-env=false]
Some text in whit verbatim environment ¿saved in list ...\verb+\usecontent[3]{test-env}+?(not get for now).\par
\begin{Verbatim}
           This is from the verbatim environment:  &%{}_"`´~
      xxxxx
\end{Verbatim}
\end{scontent*}\par
OK...it's posible to see \verb|\macro| whit \verb|\showme{\macro}|:\par
\showme{\macro}\par
or pass to list using \verb|\Scontent{\showme{\macro}}| and see in list whit \verb+\usecontent[2]{test-cmd}+:\par
\Scontent{\showme{\macro}}
\usecontent[2]{test-cmd}
\subsection{The idea whit \texttt{[show-env=true]}}
\Setscontent{ save-cmd=test-other }
XXXXXXXXX\par
\begin{scontent*}[show-env=false]
Some text in whit verbatim A
\begin{Verbatim}
   verbatim environment A:  &%{}_"`´~
\end{Verbatim}
\end{scontent*}
\Scontent[show-cmd=true]{\showme{\macro}}\par
XXXXXXXXX\par
\begin{scontent*}[show-env=false]
Some text in whit verbatim B
\begin{Verbatim}
   verbatim environment B:  &%{}_"`´~
\end{Verbatim}
\end{scontent*}
\Scontent[show-cmd=true]{\showme{\macro}}
XXXXXXXXX\par
And see in reverse order:\par
\usecontent[2]{test-other}\par
\usecontent[1]{test-other}\par
NOT OK,... 
\subsection{The problem whit \texttt{[show-env=true]}}
\begin{scontent*}[show-env=true]
Some text in whit verbatim C
\begin{Verbatim}
   verbatim environment C:  &%{}_"`´~
\end{Verbatim}
\end{scontent*}
\end{document}

regards

  • 1
    Could you please state clearly at the beginning what the aim is? – egreg Apr 6 at 8:53
  • @egreg Thanks for the comment, I added the clarification, apologies for the writing, (my english base + google translator sometimes fails). Can you give me a hand with this? – Pablo González L Apr 6 at 14:46
1

After reviewing the documentation well and reading a lot in this forum, I managed to do it by myself ...

% arara: lualatex
% arara: clean: { extensions: [ aux, log, tsc] }
\documentclass{article}
\usepackage{filecontentsdef,xparse,fvextra,xcolor}
\usepackage[margin=0.6in,noheadfoot,papersize={8.5in,13in}]{geometry}
\setlength{\parindent}{0pt}
\pagestyle{empty}
\makeatletter
\ExplSyntaxOn
% \elementin{listname}
\cs_new:Npn \elementin #1
 {
  \seq_count:c { l_savecontent_content_#1_seq }
 }

% \clearlist{listname}
\cs_new:Npn \clearlist #1
 {
  \seq_clear_new:c { l_savecontent_content_#1_seq }
 }

% \@add@content{listname}{{#1}} ...need double {{...}}
\NewDocumentCommand{\@add@content}{ m +m }
 {
  \savecontent_add_content:nn { #1 } { #2 }
 }

% \usecontent[index]{listname}
\DeclareExpandableDocumentCommand{\usecontent}{ O{1} m }
 {
  \savecontent_use_content:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \savecontent_add_content:nn #1 #2
 {
 \seq_if_exist:cF { l_savecontent_content_#1_seq }
    { \seq_new:c { l_savecontent_content_#1_seq } }
 \__savecontent_add_content:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \__savecontent_add_content:nn #1 #2
 {
    \tl_map_inline:nn { #2 }
  {
    \seq_gput_right:cn { l_savecontent_content_#1_seq } { ##1 }
  }
 }

\cs_new:Npn \savecontent_use_content:nn #1 #2
 {
  \seq_item:cn { l_savecontent_content_#2_seq } { #1 }
 }

\keys_define:nn { scontent }
 {
  save-cmd .tl_set:N         = \l_scontent_cmd_save_tl,%
  save-cmd .initial:n        = content,%
  save-env .tl_set:N         = \l_scontent_env_save_tl,%
  save-env .initial:n        = content,%
  show-cmd .bool_set:N       = \l_scontent_cmd_show_tl,%
  show-cmd .initial:n        = false,%
  show-cmd .value_required:n = true,%
  show-env .bool_set:N       = \l_scontent_env_show_tl,%
  show-env .initial:n        = false,%
  show-env .value_required:n = true,%
  show-all .meta:n           = { show-env = true , show-cmd = true },%
 }

\NewDocumentCommand{\Setscontent}{ +m }
 {
  \keys_set:nn { scontent } {#1}
 }

% \Scontent[...]{...} NO verbatim env support, but \Verb[...]{...} yes
\NewDocumentCommand{\Scontent}{ O{} +m }
 {
  \group_begin:
  \IfNoValueF{ #1 } { \keys_set:nn { scontent } {#1} }
  \@add@content{ \l_scontent_cmd_save_tl }{ { #2 } } % pass direct to list
  \IfBooleanT{ \l_scontent_cmd_show_tl } { \usecontent[-1]{ \l_scontent_cmd_save_tl} }
  \group_end:
 }

% \begin{scontent}[...] NO verbatim env suport, but \Verb[...]{...} yes
\NewDocumentEnvironment{scontent}{ !o +b }
 {
  \group_begin:
  \IfNoValueF{ #1 } { \keys_set:nn { scontent } {#1} }
 }{
  \@add@content{ \l_scontent_env_save_tl }{ { #2 } } % pass direct to list
  \IfBooleanT{ \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }
  \group_end:
 }

% \begin{scontent*}[...] verbatim env suport in \macro
\tl_new:N \l_add_@temp@save@content_tl
\NewDocumentEnvironment{scontent*}{ !O{} }
 {
  \group_begin:
  % save a tmp file.tsc in \@temp@save@content
  \filecontentsdef{\jobname.tsc}{\@temp@save@content}
 }{
  \endfilecontentsdef%
  \group_end:
  \group_begin:
  \IfNoValueF{ #1 } { \keys_set:nn { scontent } {#1} }
  % copy \@temp@save@content in \l_tmpa_tl
  \tl_set:Nx \l_tmpa_tl \@temp@save@content
  % expand \l_tmpa_tl in \l_tmpb_tl
  \tl_put_right:Nx \l_tmpb_tl
    {
     \tex_newlinechar:D = 13 \tex_everyeof:D = {\noexpand}
     \exp_not:N \scantokens \exp_after:wN { \l_tmpa_tl }
    }
  % pass \l_tmpb_tl to list
  \tl_put_right:Nx \l_add_@temp@save@content_tl
    {
     \exp_not:N \@add@content { \exp_not:V \l_scontent_env_save_tl } { {\exp_not:V \l_tmpb_tl } }
    }
  \l_add_@temp@save@content_tl
  \IfBooleanT{ \l_scontent_env_show_tl } { \usecontent[-1]{ \l_scontent_env_save_tl} }
  \group_end:
  }
\ExplSyntaxOff
\makeatother
% set name of lists
\Setscontent{ save-env=test-env, save-cmd=test-cmd }
\begin{document}
\section{Using \Verb{scontent} environment (\Verb{+b} argument from \Verb{xparse})}
\subsection{Whit \texttt{[show-env=false]}}
Text save in \verb|\begin{scontent}[show-env=false]| (hidden)

\begin{scontent}[show-env=false]
first text whit verbatim inline saved in \Verb{\usecontent[1]{test-env}} \par
We have coded this in \LaTeX: both $E=mc^2$.
\end{scontent}

\subsection{Whit \Verb{[show-env=true]}}
Text save in \verb|\begin{scontent}[show-env=true]| (Not hidden)\par

\begin{scontent}[show-env=true]
second text whit verbatim inline saved in \Verb{\usecontent[2]{test-env}}\par
More code in \LaTeX: both $E=mc^2$.
\end{scontent}

\section{Using \Verb{scontent*} environment (wraped \Verb{filecontentsdef})}

\subsection{Whit \Verb{[show-env=false]}}
Some Text save using \verb|\begin{scontent*}[show-env=false]| save in \verb|\macro| (hidden)

\begin{scontent*}[show-env=false]
Text in whit verbatim  environment ... saved in list ...\verb+\usecontent[3]{test-env}+.\par
\begin{Verbatim}
      (A) verbatim environment:  &%{}_"`´~
\end{Verbatim}
\end{scontent*}

\subsection{Whit \Verb{[show-env=true]}}
Some Text save using \verb|\begin{scontent*}[show-env=true]| save in \verb|\macro| (Not hidden)

\begin{scontent*}[show-env=true]
Text in whit verbatim  environment ... saved in list ...\verb+\usecontent[4]{test-env}+.\par
\begin{Verbatim}
      (B) verbatim environment:  &%{}_"`´~
\end{Verbatim}
\end{scontent*}

\section{Using \Verb{\Scontent[...]{...}}}
\subsection{Whit \texttt{[show-cmd=false]}}
Text save whit \verb|\Scontent[show-cmd=false]{....}| (hidden)\par

\Scontent[show-cmd=false]{
using a \Verb*{\Scontent[show-cmd=false]{...}} \textcolor{red}{whit verbatim}  saved in \Verb*{\usecontent[1]{test-cmd}}\par
(by \Verb*{fvextra}) \textcolor{magenta}{inline}
}\par

\subsection{Whit \Verb{[show-cmd=true]}}
Text save whit \verb|\Scontent[show-cmd=true]{....}| (Not hidden)\par
\Scontent[show-cmd=true]{
using a \Verb*{\Scontent[show-cmd=true]{...}} \textcolor{green}{whit verbatim} saved in \Verb*{\usecontent[2]{test-cmd}}\par
(by \Verb*{fvextra}) \textcolor{blue}{inline}
}

\section{Using \Verb{\usecontent[index]{list name}}}

\subsection{\Verb{\usecontent[index]{test-env}}}
Now see the \elementin{test-env} environment saved in list (reverse order):\par
\usecontent[4]{test-env}\par
\usecontent[3]{test-env}\par
\usecontent[2]{test-env}\par
\usecontent[1]{test-env}

\subsection{\Verb{\usecontent[index]{test-cmd}}}
Now see the \elementin{test-cmd} command saved in list (reverse order):\par
\usecontent[2]{test-cmd}\par
\usecontent[1]{test-cmd}\par
\end{document}

Now it works as expected Work OK I clarify that this would not have been possible without joining the great answers of:

  1. expl3: \tl_put_right:Nx chokes on {
  2. How to do \scantokens inside \edef without triggering “Runaway definition”
  3. Storing an array of strings in a command
  4. Collecting contents of environment and store them for later retrieval

Thank you very much to all who participate in this community...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.