\NewDocumentEnvironment eats the first non-letter token when used for verbatim environment

environmentslatex3verbatimxparse

I was messing around with creating verbatim environment saving its contents to a file like the one described in verbatim package documentation (end of section 2.2), but using latex3 features. It worked fine initially until I've tried to add an optional argument. For some reason when it is not provided and the first token is not a letter then it is missing from the output.

After executing the following code using lualatex

\documentclass{minimal}

\ExplSyntaxOn

\RequirePackage{verbatim}
\makeatletter
% L3 interface for verbatim
\cs_new_eq:NN \verbatim_start: \verbatim@start
\cs_new:Nn \verbatim_set_processline:n {
    \cs_set:Nn \__func_temp:n {#1}
    \tl_set:Nn \verbatim@processline {
        \__func_temp:n {\the\verbatim@line}
    }
}
\makeatother

\NewDocumentEnvironment{verbexport}{O{export.tex}} {
    \group_begin:
    \iow_open:Nn \g_tmpa_iow {#1}
    \seq_map_inline:Nn \l_char_special_seq {\char_set_catcode_other:N ##1}
    \char_set_catcode_active:N \^^M
    \verbatim_set_processline:n {
        \iow_now:Nx \g_tmpa_iow {##1}
    }
    \verbatim_start:
} {
    \iow_close:N \g_tmpa_iow
    \group_end:
}

\ExplSyntaxOff

\begin{document}
\begin{verbexport}
\LaTeX a
\end{verbexport}
\begin{verbexport}[export2.tex]
\LaTeX a
\end{verbexport}
\end{document}

the contents of the export.tex file are

 a

while those of export2.tex are

\LaTeX a

My latex environment is

This is LuaHBTeX, Version 1.13.2 (TeX Live 2021/Arch Linux) 
 restricted system commands enabled.
LaTeX2e <2021-11-15> patch level 1
L3 programming layer <2022-04-10>

What am I doing wrong?

Best Answer

You want to disable lookup of spaces before the optional argument.

\documentclass{article}
\usepackage{verbatim}

\ExplSyntaxOn
\makeatletter
% L3 interface for verbatim
\cs_new_eq:NN \verbatim_start: \verbatim@start

\cs_new_protected:Nn \verbatim_set_processline:n
  {
    \cs_set_protected:Nn \__func_temp:n {#1}
    \tl_set:Nn \verbatim@processline
      {
        \__func_temp:n {\the\verbatim@line}
      }
  }

\NewDocumentEnvironment{verbexport}{!O{export.tex}}
  {
    \group_begin:
    \iow_open:Nn \g_tmpa_iow {#1}
    \seq_map_inline:Nn \l_char_special_seq {\char_set_catcode_other:N ##1}
    \char_set_catcode_active:N \^^M
    \verbatim_set_processline:n
      {
        \iow_now:Nx \g_tmpa_iow {##1}
      }
    \verbatim_start:
  }
  {
    \iow_close:N \g_tmpa_iow
    \group_end:
  }

\makeatother
\ExplSyntaxOff

\begin{document}
\begin{verbexport}
\LaTeX a
\end{verbexport}
\begin{verbexport}[export2.tex]
\LaTeX a
\end{verbexport}
\end{document}

I changed something, in particular made protected the functions that do settings.

The content of both files will be

\LaTeX a