# Create a fake “\meaning” (verbatimized) for content stored in seq?

I'm trying to create a command that represents the code that is stored in a sequence without executing it (something like \meaning) . When using \cs_log:N \l_scontents_macro_tmp_tl I get in the .log the content recorded in scontents environment before passed to seq.

Can I create a command like \typestored[number]{seqname} that gives me the same result in the document?

Which when run \typestored[1]{contents} take content stored in the sequence and shows in document:

Using \verb+scontents+ env no \verb+[key=val]+, save in \verb+contents+
with index $1$\footnote{AND footnotes !!}.%

Prove new \Verb*{ new fvextra whit braces } and environment \verb+Verbatim+

\begin{Verbatim}
(A) verbatim environment                                               %
many space here and percent at end of line                             %
many space
\end{Verbatim}
No espace after, see \verb+https://tex.stackexchange.com/a/460967/7832+.\par
Use \verb|\relax|.\relax


I've tried to use :

% Fake \meaning
\tl_const:Nn \c_catcode_specials_tl { \  \\ \{ \} \$\& \# \^ \_ \% \~ } \cs_new_protected:Npn \_catcode_dospecials: { \tl_map_inline:Nn \c_catcode_specials_tl { \char_set_catcode_other:N ##1 } } \ProvideDocumentCommand{ \typestored }{ O{1} m } { \tl_put_right:Nx \l_tmpb_tl { \_catcode_dospecials: \_scontents_getfrom_seq:nn { #1 }{ #2 } } \tl_show:N \l_tmpb_tl }  But it doesn't work, I just want the representation of what's kept in the verbatim style, \l_tmpb_tl does not contain content that is stored in the sequence. This is my MWE. \documentclass{article} \usepackage{filecontentsdef}[2019/04/20] \usepackage{xparse} \usepackage{fvextra} \setlength{\parindent}{0pt} % just for the example \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_bool, 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 scontents (wrap \filecontentsdefmacro) whit [key=val] Delaying % 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: } \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 group for env \use:c { filecontentsdefmacro } { \l_scontents_macro_tmp_tl } ^^M } \group_end: % Stop environment \cs_new_protected:Nn \scontents_stop_environment: { \endfilecontentsdefmacro \group_end: % close group for env } % A variant to replace \^^M for \^^J (need by Verb{..} from fvextra) % https://tex.stackexchange.com/a/8971/7832 \cs_generate_variant:Nn \tl_replace_all:Nnn { Nxx } % Expand \l_tmpa_tl and pass to seq \cs_gset_protected:Nn \_scontents_macro_to_seq: { \regex_replace_all:nnN { \^^M } { \^^J } \l_scontents_macro_tmp_tl \cs_log:N \l_scontents_macro_tmp_tl \exp_args:NNx \_scontents_append_contents:nn \l_scontents_name_seq_tl { \exp_not:N \scantokens \exp_after:wN { \tl_use:c { l_scontents_macro_tmp_tl} } % } } % Code after scontent environment \seq_item:cn { g_scontents_seq_name_#2_seq } { #1 } \cs_new_protected:Nn \scontents_atend_environment: { \_scontents_macro_to_seq: \bool_if:NT \l_scontents_show_env_bool { \_scontents_getfrom_seq:nn { -1 }{ \l_scontents_name_seq_tl } } \cs_undefine:N \l_scontents_macro_tmp_tl } % Fake \meaning \tl_const:Nn \c_catcode_specials_tl { \ \\ \{ \} \$ \& \# \^ \_ \% \~ }
\cs_new_protected:Npn \_catcode_dospecials:
{
\tl_map_inline:Nn \c_catcode_specials_tl
{
\char_set_catcode_other:N ##1
}
}

\ProvideDocumentCommand{ \typestored }{ O{1} m }
{
\tl_put_right:Nx \l_tmpb_tl
{
\_catcode_dospecials:
\_scontents_getfrom_seq:nn { #1 }{ #2 }
}
%\tl_show:N \l_tmpb_tl
}

\ExplSyntaxOff
\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 !!}.%

Prove new \Verb*{ new fvextra whit braces } and environment \verb+Verbatim+

\begin{Verbatim}
(A) verbatim environment                                               %
many space here and percent at end of line                             %
many space
\end{Verbatim}
No espace after, see \verb+https://tex.stackexchange.com/a/460967/7832+.\par
Use \verb|\relax|.\relax
\end{scontents}

\section*{Show stored contents}
XX\getstored[1]{contents}NO space here :)\par

\section*{typestored}
%\typestored[1]{contents} % not work
\end{document}


If I remove the comments from \tl_show:l \l_tmpb_tl and \typestored[1]{contents} I get in log file:

\l_tmpb_tl=\_catcode_dospecials: \_scontents_getfrom_seq:nn {1}{contents}


As @David Carlisle put in his comment, which is not what I want. I hope it contains :

\l_tmpb_tl=Using \verb+scontents+ env no \verb+[key=val]+, save in
\verb+contents+
with index $1$\footnote{AND footnotes !!}.%

Prove new \Verb*{ new fvextra whit braces } and environment \verb+Verbatim+

\begin{Verbatim}
(A) verbatim environment                                               %
many space here and percent at end of line                             %
many space
\end{Verbatim}
No espace after, see \verb+https://tex.stackexchange.com/a/460967/7832+.\par
Use \verb|\relax|.\relax


The author of the package provides the macro \filecontentsprint which I try to imitate using the content stored in the sequences. It should look something like this (or similar):

EDIT 1

A first attempt, by defining '\typestored' as follows:

\ProvideDocumentCommand{ \typestored }{ O{1} m }
{
\tl_put_right:Nx \l_tmpb_tl
{
\seq_item:cn { g_scontents_seq_name_#2_seq } { #1 }
}
\regex_replace_once:nnN { ^ \c{scantokens} } { \c{#2[#1]} } \l_tmpb_tl
\tl_show:N \l_tmpb_tl
\small\texttt{\meaning\l_tmpb_tl}
}


I get: which is almost exactly what I want, of course, breaks the title of the question (I don't need to modify catcode), I would need to replace Ω and ΩΩ with a regex(I don't know how). I hope this clarifies better what I want (my English is not the best, Spanish is my language).

EDIT 2

Second attempt, I copied the definition of \filecontentsprint from the style file and added the newvbtm package to avoid conflicts with the classic verbatim environment. It's not at all elegant and doesn't follow the line I'm looking for, the code is a bit "obfuscated" for me but it works.

% Fake \meaning, copy direct from filecontensdef package
% Add \usepackage{newvbtm} to solve conflict whit verbatim nested
\newverbatim{typescverb}{}{}{}{}
\makeatletter
\gdef\filecontentsprint{\filecontentsdef@get\filecontents@print}%
\catcode\^^M\active%
\gdef\filecontents@print #1{\let\filecontents@print@EOL^^M\let^^M\relax%
\begingroup\toks@\expandafter{#1}\edef\x{\endgroup%
\noexpand\begin{typescverb}^^M%
\the\toks@\@backslashchar end\string{typescverb\string}}\x^^M%
\filecontents@print@resetEOL}%
\gdef\filecontents@print@resetEOL{\let^^M\filecontents@print@EOL}%
\makeatother

\ProvideDocumentCommand{ \typestored }{ O{1} m }
{
\group_begin:
\tl_put_right:Nx \l_tmpb_tl
{
\seq_item:cn { g_scontents_seq_name_#2_seq } { #1 }
}
\filecontentsprint\l_tmpb_tl
\group_end:
}


The output obtained is:

What I was looking for, of course, in doing this you lose the spirit of using expl3 by mixing LaTeX2e code.

Greetings.

• why can't you just use \meaning that will put essentially the same in the document as \show will show in the log? I must be missing something... – David Carlisle Jun 23 '19 at 18:11
• I think it's because of the use of \scantokens, the filecontentsdef package plays with catcodes in ways I don't understand and I can't get the result I'm hoping for. – Pablo González L Jun 23 '19 at 18:14
• it would help if you said what was wrong with the output of \meaning (\meaning returns all characters with catcode 12 or 10 so initial catcodes should not matter) – David Carlisle Jun 23 '19 at 18:16
• I think I have a problem with concepts, what I hope is that the output looks like the content is inside \begin{verbatim}...\end{verbatim}, I've played a little and get " instead of , and other symbol... – Pablo González L Jun 23 '19 at 18:25
• \texttt{\meaning\zzzzz} should be the same except possibly you need to do something about line ends, but that is all. – David Carlisle Jun 23 '19 at 18:26

Since it seems you are keen to follow the expl3 guidelines, I suggest you take a look at “The expl3 package and LaTeX3 programming” (texdoc expl3) and “The LaTeX3 kernel: style guide for code authors” (texdoc l3styleguide). These are two short documents introducing the basic concepts of expl3 and a preferable coding style.

That said, I translated the code in your question to expl3 syntax and changed your code a bit to incorporate the guidelines above.

First, the translation of the code.
This answer is more conceptual than code, so I kept the \newverbatim thing as it was already working. As I said in the comment: you are interfacing LaTeX2ε with LaTeX3, so you will eventually have to put some 2ε in there, mainly if that code comes from a package. Since you are already using \filecontentsdefmacro, then I guess \newverbatim is fine.

I dropped \makeatletter (that’s yelling “I’m LaTeX2ε c@de!” :-). I made a copy of filecontentsdef@get to be used in expl3 code with \cs_new_eq:Nc, so that you don't need to \makeatletter:

\cs_new_eq:Nc \__scontents_fcdef_get:NN { filecontentsdef@get }


Next, we make ^^M active (inside a group) with:

\group_begin:
\char_set_catcode_active:N \^^M


Now comes the main macro. First, untangling the code a bit:

\gdef\filecontents@print#1{%
\let\filecontents@print@EOL^^M%
\let^^M\relax%
\begingroup%
\toks@\expandafter{#1}%
\edef\x{%
\endgroup%
\noexpand\begin{typescverb}^^M%
\the\toks@%
\@backslashchar end\string{typescverb\string}%
}\x^^M%
\filecontents@print@resetEOL%
}


First the code saves the definition of ^^M and makes it a no-op with \let^^M\relax. We do the same:

  \cs_new_protected:Npn \__scontents_fcdef_print:N #1
{
\cs_set_eq:NN \__scontents_fcdef_saved_EOL: ^^M
\cs_set_eq:NN ^^M \scan_stop:


Notice that the scope of \cs_new_protected: is global, so \gdef is already covered. Also the function contains assignments, so it can't expand in expansion-only contexts, thus you need protected.

Now the code saves the expansion of a macro into \toks@, which is then used in an \edef with \the\toks@. This is used because \the\toks@ expands only once, even inside an \edef, thus it allows one to use something like an ε-TeX \unexpanded in TeX (Actually it's the other way around: \unexpanded{<stuff>} does more or less \toks@{<stuff>}\the\toks@ internally to prevent further expansion of <stuff>). The same can be accomplished with (in the \edef) \unexpanded\expandafter{#1}, without needing the \toks@. Since expl3 (and LaTeX2ε, for that matter) requires ε-TeX anyway, there's no harm in that. A more expl3y version of that is \exp_not:V #1, which retrieves the contents of #1 and prevents further expansion.

This bit of code also uses the \begingroup\edef\x{\endgroup<stuff to be expanded>}\x. This is precisely what an x expansion does in expl3, except that the grouping is not used because a private temporary macro is used. So we can just replace all that by \use:x.

Finally, the \@backslashchar end\string{typescverb\string} is replaced by the expl3 equivalent string. Putting all that together:

      \use:x
{
\exp_not:N \begin{typescverb} ^^M
\exp_not:V #1
\c_backslash_str end \c_left_brace_str typescverb \c_right_brace_str
}
^^M


Finally we reset ^^M and end the group we started back there:

      \cs_set_eq:NN ^^M \__scontents_fcdef_saved_EOL:
}
\group_end:


Now, some notes on the code in general.
In expl3 there is a clear distinction of internal, code-level, and user-level functions and variables. User level is code defined with xparse's \NewDocumentCommand and the like, which the final user will use in the document.

Code level functions and variables will be used in the implementation of the user level code and across different modules. These should be documented and they are named \<module>_function_name:<args> for functions and \(l|g|c)_variable_name_<type> for variables. Examples of these are \seq_item:Nn and \l_tmpa_tl, respectively.

Finally, internal code is used in the implementation and gory details of the former level. These functions should never be used outside the module they are defined in. These are named \__<module>_macro_name:<args> and \(l|g|c)__variable_name_<type>. Notice the double underscore in both cases. Examples of these are \__seq_item:wNn and \l__char_tmp_tl.

In your code you used many \_scontents..., which is midway between code-level an internal. You should decide: If you expect other programmers to use that then \scontents..., otherwise it is internal code and should be \__scontents.... The same goes for the variables.

You should also remeber to use the proper \cs_new... function. If the definition is expandable and you need it to be expandable, then you need \cs_new:Npn (or similars). In every other case the function should be defined with \cs_new_protected:Npn (or similar). \__scontents_getfrom_seq:nn uses \seq_item:Nn (which is expandable) to fetch contents from a seq variable. If you expect this function to expand in an x-type expansion you can't define it with \cs_new_protected:Npn, or it won't expand. Use just \cs_new:Npn here.

Remember also to use the proper variants depending on what type of argument you are passing to the function. Suppose you define a function, say, \cs_new:Npn \my_use:n #1 { \use:c { my_#1_command_name: } }, to use as \my_use:n { funny } and get \my_funny_command_name: (sorry for the dumb example), TeX allows you to do \tl_set:Nn \l_my_tl { funny } and then \my_use:n { \l_my_tl } because \use:c (\csname) expands \l_my_tl as it goes. But you should really not do that! In this particular case, no problem occurs. However suppose that now you want to disallow an empty argument to \my_use:n, then you define it with:

\cs_new:Npn \my_use:n #1
{
\tl_if_empty:nTF {#1}
{ \msg_error:nn { mymodule } { empty-arg } }
{ \use:c { my_#1_command_name: } }
}


If you use \my_use:n { } the error message is issued, but if you do \tl_clear:n \l_my_tl and then \my_use:n { \l_my_tl } the error will not show up! The correct way to use \my_use:n with \l_my_tl here would be \exp_args:NV \my_use:n \l_my_tl or simply \my_use:V \l_my_tl with the proper variant definition.

Somewhere you had \cs_undefine:N \l__scontents_macro_tmp_tl. That's very wrong! \cs_undefine:N should be used to make a control sequence undefined, but \l__scontents_macro_tmp_tl is a token list. Yes, it does work, and yes, a token list is, deep down, a control sequence, but it's conceptually wrong. A variable, once allocated with \<type>_new:N should exist “forever” and be reused accordingly. What you want here is probably \tl_clear:N to clear the contents of that token list.

The function \_catcode_dospecials: and the variable \c_catcode_specials_tl should be named \__scontents_catcode_dospecials: and \c_scontents_catcode_specials_tl because the module you are creating is scontents, not catcode. Note also that expl3 defines a seq variable \l_char_special_seq which contains the special characters you need, so you don't need to define the sequence yourself, and can simplify the definition of \__scontents_catcode_dospecials: to:

\cs_new_protected:Npn \__scontents_catcode_dospecials:
{ \seq_map_function:NN \l_char_special_seq \char_set_catcode_ignore:N }


but you aren't using it in the code, so I removed it.

You should only use \ProvideDocumentCommand and \DeclareDocumentCommand only when you have a good reason to. In all other cases you should stick to \NewDocumentCommand (Or \RenewDocumentCommand if redefining) to avoid surprises. Usually the “command already defined” error is helpful.

You should also avoid \l_tmpa_tl and other scratch variables defined by the LaTeX3 kernel. They can, of course, be used, but should be only in temporary code (if you are testing something, for example). If the code goes beyond temporary you should declare a variable and use that instead. This will avoid undesired interaction between packages which use the same scratch variable.

I also changed, in the definition of \typestored, \tl_put_right:Nx to \tl_set:Nx because you don't actually want to add to the existing contents of the token list. This would cause problems in longer stretches of code if you forgot to clear the token list (for example, if some other package code used \l_tmpb_tl and forgot to clear it, their contents would creep in your code).

To allow the usage of fancyvrb instead of newvbtm I had to change the timing of the \scantokens a tad. Apparently a verbatim environment like this:

\begin{typescverb}
\scantokens{<stuff>}
\end{typescverb}


(which is what the code was doing), defined with newvbtm will expand the \scantokens (somehow) and things will go as planned. However the same environment defined with fancyvrb does not, and it thinks the whole thing is just one line of code and typesets it as such. To have it working with fancyvrb you need to change to:

\scantokens{
\begin{typescverb}
<stuff>
\end{typescverb}
}


However, to do that you need to remove the \scantokens from around the <stuff>, so I pass the token list variable to a \__scontents_strip_scantokens:N macro which expands the token list, checks if the first token is \tex_scantokens:D. If it is (that is, the token list is \scantokens{<stuff>}) then it expands to \unexpanded{<stuff>}. Otherwise it returns the token list unchanged.

After all that talking, here's your modified code:

\documentclass{article}
\usepackage{filecontentsdef}[2019/04/20]
\usepackage{xparse}
\usepackage{fvextra}
\setlength{\parindent}{0pt} % just for the example
\ExplSyntaxOn
\tl_new:N \l__scontents_macro_tmp_tl
\tl_new:N \l__scontents_tmpa_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_bool,
show-env  .initial:n  = false
}
\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:Npn \__scontents_getfrom_seq:nn #1#2
{ \seq_item:cn { g__scontents_seq_name_#2_seq } {#1} }
\NewExpandableDocumentCommand { \getstored } { O{1} m }
{ \__scontents_getfrom_seq:nn {#1} {#2} }
% Define scontents (wrap \filecontentsdefmacro) whit [key=val] Delaying
\NewDocumentEnvironment { scontents } { }
{
\char_set_catcode_active:N \^^M
\scontents_start_environment:w
}
{
\scontents_stop_environment:
\scontents_atend_environment:
}
\cs_new_protected:Npn \scontents_environment_keys:w [ #1 ]
{ \keys_set:nn { scontents } {#1} }
\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 group for env
\filecontentsdefmacro { \l__scontents_macro_tmp_tl } ^^M
}
\cs_new_protected:Nn \scontents_stop_environment:
{
\endfilecontentsdefmacro
\group_end: % close group for env
}
\group_end:
\exp_args_generate:n { Vx }
\cs_gset_protected:Nn \__scontents_macro_to_seq:
{
\regex_replace_all:nnN { \^^M } { \^^J } \l__scontents_macro_tmp_tl
\cs_log:N \l__scontents_macro_tmp_tl
\exp_args:NVx \__scontents_append_contents:nn \l__scontents_name_seq_tl
{ \exp_not:N \tex_scantokens:D { \tl_use:N \l__scontents_macro_tmp_tl } }
}
% Code after scontent environment \seq_item:cn { g__scontents_seq_name_#2_seq } { #1 }
\cs_new_protected:Nn \scontents_atend_environment:
{
\__scontents_macro_to_seq:
\bool_if:NT \l__scontents_show_env_bool
{ \exp_args:NnV \__scontents_getfrom_seq:nn { -1 } { \l__scontents_name_seq_tl } }
\tl_clear:N \l__scontents_macro_tmp_tl
}
\DefineVerbatimEnvironment{typescverb}{Verbatim}{}
\cs_new_eq:Nc \__scontents_fcdef_get:NN { filecontentsdef@get }
\quark_new:N \q__scontents_strip_quark
\cs_new:Npn \__scontents_strip_scantokens:N #1
{ \exp_args:NV \__scontents_strip_scantokens:n #1 }
\cs_new:Npn \__scontents_strip_scantokens:n #1
{
{
\__scontents_if_scantokens:NwTF #1 \q__scontents_strip_quark
{ \exp_not:o { \use_ii:nn #1 } }
{ \exp_not:n {#1} }
}
{ \exp_not:n {#1} }
}
\prg_new_conditional:Npnn \__scontents_if_scantokens:Nw
#1 #2 \q__scontents_strip_quark { TF }
{
\token_if_eq_meaning:NNTF \tex_scantokens:D #1
{ \prg_return_true: }
{ \prg_return_false: }
}
\group_begin:
\char_set_catcode_active:N \^^M
\cs_new_protected:Npn \__scontents_fcdef_print:N #1
{
\cs_set_eq:NN \__scontents_fcdef_saved_EOL: ^^M
\cs_set_eq:NN ^^M \scan_stop:
\use:x
{
\exp_not:N \tex_scantokens:D
{
\exp_not:N \begin{typescverb} ^^M
\__scontents_strip_scantokens:N #1
\c_backslash_str end \c_left_brace_str typescverb \c_right_brace_str ^^M
}
}
\cs_set_eq:NN ^^M \__scontents_fcdef_saved_EOL:
}
\group_end:
\NewDocumentCommand { \typestored } { O{1} m }
{
\group_begin:
\tl_set:Nx \l__scontents_tmpa_tl
{ \seq_item:cn { g__scontents_seq_name_#2_seq } {#1} }
\__scontents_fcdef_get:NN \__scontents_fcdef_print:N \l__scontents_tmpa_tl
\group_end:
}
\ExplSyntaxOff
\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 !!}.%

Prove new \Verb*{ new fvextra whit braces } and environment \verb+Verbatim+

\begin{Verbatim}
(A) verbatim environment                                               %
many space here and percent at end of line                             %
many space
\end{Verbatim}
No espace after, see \verb+https://tex.stackexchange.com/a/460967/7832+.\par
Use \verb|\relax|.\relax
\end{scontents}

\section*{Show stored contents}
XX\getstored[1]{contents}NO space here :)\par

\section*{typestored}
\typestored[1]{contents} % not work
\end{document}

• Thank you so much for the response and clarification of concepts, in my mind \l__scontents_macro_tmp_tl became \cs as I went through \filecontentsdefmacro. Now I will be able to adapt it to the idea I have in mind, which is to put together a small package (that's why \ProvideDocumentCommand) for a future feature request to the LaTeX3 team. Greetings – Pablo González L Jun 27 '19 at 12:51
• @PabloGonzálezL As I said, deep down a tl is just a macro. Roughly speaking \tl_set:Nn \l__my_tl {hello} does \def\l__my_tl{hello}, so \cs_undefine:N does what it advertises and it works in \filecontentsdefmacro. And that's one of the problems with interfacing stuff: trying not to mess up data types. However the whole purpose of variables is to be declared once and used throughout the code for the same data type, akin to a variable in other programming languages, so you should never undefine them, only clear. Good luck with your package! – Phelype Oleinik Jun 27 '19 at 13:55
• With this answer, I think I can finish with my idea, I think I have clarified all my doubts and I can finish writing a package with dignity :). I will read with more attention l3styleguide. Greetings – Pablo González L Jun 27 '19 at 18:26
• Hi, I tried to adapt your answer using fancyvrb package (which I use in a regular way) by placing \DefineVerbatimEnvironment{typescverb}{Verbatim}{}, but don't respect ^^M and keep looking [opt arg] and you can't prevent the error. If you have some time, could you extend your answer by adding this? Greetings – Pablo González L Jun 29 '19 at 20:18
• @PabloGonzálezL Hello, Pablo. Sorry for the delay, I could only look at it now. I changed the code a bit to make it work with fancyvrb. Apparently fanvyvrb does things in a different order than newvbtm and the \scantokens stored in the token list doesn't get expanded. I changed the code to remove the \scantokens initially used for typesetting, and then inserted an outer \scantokens` that goes around the entire verbatim environment and it seems to work. See if it works; if it does I'll change the answer. Here it is: pastebin.com/Cx6Jvg4X – Phelype Oleinik Jun 30 '19 at 22:00