this query is related to How to pass an optional argument to an environment with verbatim content? (whose solution did not work in my case) and with Emulating @ifnextchar in expl3 (which is the one I'm trying to adapt).
I have defined an environment (listcontents
) using xparse
which encapsulates \filecontentsdef
(which is verbatim
plus \macro
) using the argument !O{}
and [key = val]
which works well if ALWAYS pass the optional argument.
My idea is to be able to write the environment without having to use an empty optional argument []
, this is where I am lost, I have read the documentation of \peek_meaning:NF
but I do not understand it at all (the \catcodes
is confusing for me).
It works correctly if use:
\begin{listcontents}[]
\begin{listcontents}[key=val]
\begin{listcontents}[
key=val
]
and I would like to do it in the following way:
\begin{listcontents}
\begin{listcontents}
[not key = value, only a bracket whit text]
that is, if you do not find [key = val]
right after }
, insert a line ending \^^M
and [not key = value, just a square bracket with text]
would be recorded by the environment.
The package xsim
(which is written only usingexpl3
) works similar to filecontents
, has a code to solve this problem, but, it is very complicated to adapt for me.
This is my sample file:
\documentclass{article}
\usepackage{fancyvrb,filecontentsdef,xparse}
\pagestyle{empty}
\begin{document}
\makeatletter
\ExplSyntaxOn
\keys_define:nn { listcontents }
{
save-env .tl_set:N = \l_env_save_tl,
save-env .initial:n = content,
show-env .bool_set:N = \l_env_show_tl,
show-env .initial:n = true,
name-tmp .tl_set:N = \l_tmp_name_tl,
name-tmp .initial:n = \jobname.tsc,
}
\NewDocumentEnvironment{ listcontents }{ !O{} }
{
\group_begin:
\IfNoValueF { #1 } { \keys_set:nn { listcontents } { #1 } }
%\peek_meaning_ignore_spaces:NF [ { \char_set_catcode_active:N \^^M \char_set_catcode_end_line:N \^^M \\ }
%\peek_meaning:NF \c_space_tl { \char_set_catcode_active:N \^^M \char_set_catcode_end_line:N \^^M \^^M }
% Acording a doc of v1.4 this its a correct line
\csname filecontentsdef*\endcsname{ \l_tmp_name_tl }{ \l_tmpa_tl }
}
{
\endfilecontentsdef
\group_end:
\group_begin:
\IfNoValueF { #1 } { \keys_set:nn { listcontents } { #1 } }
\IfBooleanT{ \l_env_show_tl } { \filecontentsexec\l_tmpa_tl }
\group_end:
}
\ExplSyntaxOff
\makeatother
\section{[not key = value, just a square bracket with text]}
\begin{listcontents}
[not key = value, just a square bracket with text]
This is correct for key=val, but space between letters in [...] disappeared
% some comented lines
\begin{verbatim*}
\begin{listcontents}
[not key = value, just a square bracket with text]
\end{verbatim*}
and \verb+[not key = value, just a square bracket with text]+ its not save
in \verb+\jobname.tsc+ and \verb+\l_tmpa_tl+.
\end{listcontents}
The \textbf{file generate} is:
\VerbatimInput[frame=single]{\jobname.tsc}
\section{Omit a [optional argument] after begin\{listcontents\} }
\begin{listcontents}
This is what I want to happen when omit []
% some comented lines
\begin{verbatim*}
\begin{listcontents}
This is what I want to happen when omit []
% some comented lines
\end{verbatim*}
if ommit \verb*+[ ]+ the first lines and and space between
letters disappeared, the contents of environments not save
in \verb+\jobname.tsc+ and \verb+\l_tmpa_tl+.
\end{listcontents}
The \textbf{file generate} is:
\VerbatimInput[frame=single]{\jobname.tsc}
\end{document}
The output looks like this:
Can this be done using
xparse/expl3
?
regards
\NewDocumentEnvironment{ listcontents }{o}
and then continue with\IfNoValueF { #1 }{...}
in the environment definition. Now both\begin{listcontents}...\end{listcontents}
and\begin{listcontents}[show-env=true]...\end{listcontents}
are valid.{o}
is not enough for what I want.{o!}
give what you want? Certainly using{O{}}
followed by\IfNoValueF{#1}{...}
makes no sense becauseO
sets#1
to{}
if no argument is given so\IfNoValueF{#1}{...}
will always execute{...}
.\filecontentsdef
juggles with the category code of the endline character; when no optional argument is used, it's too late because the endline character after\begin{listcontents}
has already been scanned and converted to a space, which has the effect of not including the following line in the contents; the text is typeset that way because of how\filecontentsdef
sets things up.