1

I am designing a library that needs to deal with some verbatim code. For now, I use the great xsimverb package that provides nice things, like gobble, deal with basically all kinds of characters… I need to provide some arguments to my command, but the list of argument can sometime be annoying to add, and I'd like to provide some wrappers to the package, like:

\NewDocumentEnvironment{wrapperCode}{}%
  {\begin{robExtCode}{some arguments}}%
  {\end{robExtCode}}

but if I try to do that it fails with some errors:

! File ended while scanning use of ^^M.

How could I solve them? It would be even better if the wrapping environment could itself use robExt multiple times before the wrapping, but I can live without this. Of course, I could duplicate the code but I'd prefer to avoid it as I want my final users to be able to create new wrappers easily and they will not have access to my code (that might change). Therefore, if no simple solution exists, it is fine to create a function that automatically creates a new wrapping environment with the provided arguments.

MWE:

\documentclass[]{article}
\usepackage{xsimverb}
\usepackage{verbatim}

\ExplSyntaxOn

\ior_new:N \g_robExt_read_ior

\NewDocumentEnvironment{robExtCode}{m}{
  \XSIMfilewritestart*{tmp-file-you-can-remove.tmp}
}{
  \XSIMfilewritestop
  %% Loop on all lines of the file to put it in l_robExt_content_named
  %% but I might want to do other stuff here.
  \ior_open:Nn \g_robExt_read_ior {tmp-file-you-can-remove.tmp}
  \str_gclear:c {l_robExt_content_named}
  \ior_str_map_inline:Nn \g_robExt_read_ior {
    \str_gput_right:cx {l_robExt_content_named} {\tl_to_str:N{##1}^^J}
  }
  I ~ am ~ the ~ argument ~ ``#1'' ~and~ why~ not~ printing~ the~ file:~ \verbatiminput{tmp-file-you-can-remove.tmp}
}

\ExplSyntaxOff

\NewDocumentEnvironment{wrapperCode}{}{\begin{robExtCode}{some arguments}}{\end{robExtCode}}

\begin{document}

\begin{robExtCode}{some arguments}
# Here is a comment
print(1 % 2)
\end{robExtCode}

%%% DO NOT WORK
\begin{wrapperCode}
# Here is a second test
print(1 % 2)
\end{wrapperCode}

\end{document}

1 Answer 1

1

The name of the string variable is wrong: it should start with \g and end with _str. No need for c.

The \tl_to_str:N function is incorrectly used; maybe \tl_to_str:n, but the argument is already in string format because of \ior_str_map_inline:Nn.

But the most important change is to use the “internal“ version of the environment.

\documentclass[]{article}
\usepackage{xsimverb}
\usepackage{verbatim}

\ExplSyntaxOn

\ior_new:N \g_robExt_read_ior
\str_new:N \g_robExt_content_str

\NewDocumentEnvironment{robExtCode}{m}{
  \XSIMfilewritestart*{\jobname-tmp.tmp}
}{
  \XSIMfilewritestop
  %% Loop on all lines of the file to put it in \g_robExt_content_str
  %% but I might want to do other stuff here.
  \ior_open:Nn \g_robExt_read_ior {\jobname-tmp.tmp}
  \str_gclear:N \g_robExt_content_str
  \ior_str_map_inline:Nn \g_robExt_read_ior
   {
    \str_gput_right:Nx \g_robExt_content_str {##1^^J}
   }
  I ~ am ~ the ~ argument ~ ``#1'' ~and~ why~ not~ printing~ the~ file:~ 
  \verbatiminput{\jobname-tmp.tmp}
}

\ExplSyntaxOff

% see how the inner environment is called!
\NewDocumentEnvironment{wrapperCode}{}{%
  \robExtCode{some arguments}%
}{\endrobExtCode}

\begin{document}

\begin{robExtCode}{some arguments}
# Here is a comment
print(1 % 2)
\end{robExtCode}

%%% DO NOT WORK
\begin{wrapperCode}
# Here is a second test
print(1 % 2)
\end{wrapperCode}

\end{document}

enter image description here

You know what to do with the string variable, I don't. In this code it's completely unused.

3
  • Oh, thanks a lot! Regarding the :c, it is reminiscent of the actual code that uses a csname to give a different name to the variable depending on the value of some macro. Regarding _str, you are right (and thanks for the \tl_to_str), but this is purely conventional right, to help people identify the type of a macro right? (if only LaTeX3 was taking the point of view of most languages nowadays, starting from a clean basis and introducing a true typing system, the LaTeX code could have been much clearer…)
    – tobiasBora
    Jun 19, 2023 at 23:09
  • @tobiasBora Unrelated: aren't all macro languages "just" textual substitution (expansion), or, isn't everything a pointer, and only one "type"? :) I need everything to be at meta-level and above.
    – Cicada
    Jun 20, 2023 at 11:13
  • @Cicada I guess yes but you might represent your data in different ways (comma separated list, possibly list of tokens with a special treatment on there catcode (which is how I understand strings)…) so that still make sence to introduce a notion of type I guess, even if it's not stricly enforced. But egreg can correct me if I'm wrong.
    – tobiasBora
    Jun 20, 2023 at 13:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .