6

[EDITED to show where I actually want to use the optional argument]

This question may be answered at How to pass an optional argument to an environment with verbatim content?, but I'm having a hard time trying to apply that answer to my problem. I will delete this query if it is deemed duplicative.

When I utilize a verbatim-like environment that takes an optional argument (vb in the MWE below), then for cases where no optional argument is specified the first token in the environment is sometimes excuted outside of the environment.

\documentclass{article}
\usepackage{verbatim}
\parskip 1ex\parindent 0em

\makeatletter
\newenvironment{va}{%
  \def\verbatim@processline{%
    {\setbox0=\hbox{\the\verbatim@line}%
    \hsize=\wd0 \the\verbatim@line\par}}%
  \setbox0=\vbox\bgroup \verbatim
}
{%
  \endverbatim
  \unskip\setbox0=\lastbox %
  \egroup
  \usebox0
}

\newenvironment{vb}[1][]{%
  \def\verbatim@processline{%
    {\setbox0=\hbox{\the\verbatim@line}%
    \hsize=\wd0 \the\verbatim@line\par}}%
  \setbox0=\vbox\bgroup #1 \verbatim
}
{%
  \endverbatim
  \unskip\setbox0=\lastbox %
  \egroup
  \usebox0
}

\makeatother
\begin{document}

I created two environments based on \verb|boxedverbatim| environment.
Environment \verb|va| takes no arguments.  Environment \verb|vb| is
identical but takes an optional argument (which is not actually used for
anything in this MWE). In all the following cases, no optional argument
is actually passed to the \verb|vb| environment

Starting either environment with a letter works:

\begin{va}I will set \def\x{1}\end{va}

\begin{vb}I will set \def\x{1}\end{vb}

But if I start the environments with a command like \verb|\Huge|, the
\verb|vb| environment executes that command outside the environment, even
though it was not in brackets:

\begin{va}\Huge I will set \def\x{1}\end{va}

\begin{vb}\Huge I will set \def\x{1}\end{vb}

If I start the verbatim with a \verb|\def|, the \verb|vb|
environment breaks

\begin{va}\def\x{1}\end{va}

%\begin{vb}\def\x{1}\end{vb}

\end{document}

enter image description here

  • I think this deals with the particular way in which optional arguments are absorbed. Using an optional argument fundamentally requires a scanning of the first token after the command name and may lead to execution (don't know why). Using xparse's \NewDocumentEnvironment{vc}{ o }{<begin>}{<end>} works, since it uses a different method/technique for picking up arguments (I think). Lots of uncertainty on my end; a heavy-weight can chip in. – Werner Apr 15 '13 at 19:35
  • @Werner You are a heavyweight :^) – Steven B. Segletes Apr 15 '13 at 19:37
7

As for all verbatim commands you need to switch the catcode regime before parsing for arguments. Once a character has been tokenised, the catcode values set by verbatim have no effect as catcodes do not affect tokens once created, they only determine how tokens are created from the file input.

In

\begin{vb}\Huge

\vb looks at the next token to see if it is [. TeX has to read the file to generate the next token so reads all of \Huge and makes a cs token, after which any settings of catcode only affect characters that are read from the file; they don't affect the Huge.

You just need to parse for arguments after setting up catcodes:

\newcommand\innervb[1][]{}

\newenvironment{vb}{%
  \def\verbatim@processline{%
    {\setbox0=\hbox{\the\verbatim@line}%
    \hsize=\wd0 \the\verbatim@line\par}}%
  \setbox0=\vbox\bgroup \verbatim\innervb
}
{%
  \endverbatim
  \unskip\setbox0=\lastbox %
  \egroup
  \usebox0
}
  • @IanThompson thanks for the edit, even for me that typo rate looked a bit excessive, sorry:-) – David Carlisle Apr 15 '13 at 21:14
  • Follow up question: What if I wanted that optional argument to be executed just prior to the invocation of \verbatim but within the \bgroup? In the present form, the optional argument is not known at that point. I tried moving the \innervb earlier in the environment (but that's not after setting up catcodes). It didn't break anything, but nor did it work. In other words, if I put \Huge in [] brackets, I would want it to behave like it originally did. – Steven B. Segletes Apr 16 '13 at 10:22
  • 1
    @StevenB.Segletes you could use etex scantokens to re-tokenize the optional argument – David Carlisle Apr 16 '13 at 11:27

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.