# Re: Lack Of Optional Argument Makes 1st Item Of Environment Get Executed As If It Were Optional Argument

\documentclass{article}
\usepackage{verbatim}
%\usepackage{fancyvrb}
\usepackage{xcolor}
\usepackage{xkeyval}

%RE: LACK OF OPTIONAL ARGUMENT MAKES 1ST ITEM OF ENVIRONMENT GET EXECUTED AS IF IT WERE OPTIONAL ARGUMENT

\makeatletter
\newwrite\verbatim@out%

\def\verbatimout#1{
\begingroup%group to localise cat code reassignment?
\immediate\openout\verbatim@out#1%
\let\do\@makeother\dospecials%
\catcode\^^M\active%
\def\verbatim@processline{%
%\the\verbatim@line%
%\typeout{VERBATIM: \the\verbatim@line}%
\immediate\write\verbatim@out{\the\verbatim@line}}%
\verbatim@start%
}

%\def\setverbatimout#1{
% \begingroup
%  \immediate\openout\verbatim@out#1%
%  \def\verbatim@processline{%
%   \typeout{VERBATIM: \the\verbatim@line}%
%   \immediate\write\verbatim@out{\the\verbatim@line}}%
%}

\def\endverbatimout{%
%\endverbatim
\immediate\closeout\verbatim@out%\@esphack%
\endgroup
}

\def\mykeys@color{black}
\define@key{mykeys}{color}{\def\mykeys@color{#1}}

\newenvironment{verboptfail}[1][]{\verbatim}{\endverbatim}

\newenvironment{verbopt}{\verbatim\verboptarg}{\endverbatim}
\newcommand\verboptarg[1][]{\setkeys{mykeys}{#1}\color{\mykeys@color}\typeout{:::#1:::}}

%NOTE: replacing \verbatim with \verbatimout{filename} and \endverbatim with \endverbatimout does not work, as \verboptarg is simply not picked up.  Why? catcodes?

\gdef\opts{}

%\newenvironment{verbout}{\setverbatimout{1.temp}\verbatim\verboutarg}{\endverbatimout\setkeys{mykeys}{\opts}\color{\mykeys@color}\verbatiminput{1.temp}}
\newenvironment{verbout}{\verbatimout{1.temp}\verboutarg}{\endverbatimout\setkeys{mykeys}{\opts}\color{\mykeys@color}\verbatiminput{1.temp}}

%\newcommand\verboutarg[1][]{{\nfss@catcodes\scantokens{\gdef\opts{#1}\typeout{***\opts***}}}}%typeout never gets executed!
\newcommand\verboutarg[1][]{\gdef\opts{#1}\typeout{***\opts***}}%typeout never gets executed!

\makeatother
\begin{document}
standard verbatim environment with a problem - well that's where we started!

\begin{verbatim}\more\verb
\x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| \end{verbatim} %the following fails to compile when we remove REMOVEME! \begin{verboptfail}REMOVEME\more\verb \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\|
\end{verboptfail}

our verbopt environment works fine

\begin{verbopt}
\x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| without arg \end{verbopt} \begin{verbopt}\more\verb \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| without arg
\end{verbopt}

\begin{verbopt}[color=blue]\more\verb
\x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| with arg \end{verbopt} \begin{verbopt}[] \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\|
with EMPTY optional arg
\end{verbopt}

************ we can't get our verbout environment to work - we find [color=blue]' etc in the output file, and keyvalues have not been set! *************

\begin{verbout}
\x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| \end{verbout} \begin{verbout}\more\verb \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\|
\end{verbout}

\begin{verbout}[color=blue]
\x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| \end{verbout} \begin{verbout}[] \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\|
with EMPTY optional arg
\end{verbout}
\end{document}


standard verbatim environment with a problem - well that’s where we started!

\more\verb
\x\y\z !"$%^&*()_+-=[]{};’#:@~,./<>?\| REMOVEME\more\verb \x\y\z !"$%^&*()_+-=[]{};’#:@~,./<>?\|


our verbopt environment works fine

\x\y\z !"$%^&*()_+-=[]{};’#:@~,./<>?\| without arg \more\verb \x\y\z !"$%^&*()_+-=[]{};’#:@~,./<>?\| without arg
\more\verb
\x\y\z !"$%^&*()_+-=[]{};’#:@~,./<>?\| with arg \x\y\z !"$%^&*()_+-=[]{};’#:@~,./<>?\|


with EMPTY optional arg **** we can’t get our verbout environment to work - we find ‘[color=blue]’ etc in the output file, and keyvalues have not been set! ************ ************* ************** *********** **************** ******* ************* ************** *********** ****************

\x\y\z !"$%^&*()_+-=[]{};’#:@~,./<>?\| \more\verb \x\y\z !"$%^&*()_+-=[]{};’#:@~,./<>?\|
[color=blue]
\x\y\z !"$%^&*()_+-=[]{};’#:@~,./<>?\| [] \x\y\z !"$%^&*()_+-=[]{};’#:@~,./<>?\|


with EMPTY optional arg

• All caps means shouting. Please, don't. – egreg May 12 '18 at 20:56
• @egreg: How should one write to squeak ? :o) – Bernard May 12 '18 at 21:01
• Is there a question here and a description of the what you're doing, or do we have to read through all the code and figure it out for ourselves? – Alan Munn May 12 '18 at 21:52

This should get you a bit further.

First, your verbopt environment doesn't really work fine. It produces an empty line, if there is no text in the line with \begin{verbopt}.

The environment verbiopt fixes this by defining it with the optional argument for the environment. But without the optional argument text in the same line as \begin{verbiopt} will produce an error, if it starts with a TeX command, \more in the example, which is also swallowed. If the text doesn't start with a command or there is no text in that line, there is no problem.

For the verbout environment, it also makes more sense, to give the argument to the environment. In your example, you can set the key at the beginning of the environment (commented out version). But this may not always be possible. Therefore the used version uses the argument at the end of the environment.

Here it's important to know, that \setkeys{mykeys}{\verbopts} will not work, because \verbopts is expanded to late. \setkeys will treat color=blue as the key (with no value) and then complain about an unknown key. To fix this, the macro \setmykeys is used. It is called with the already expanded \verbopts, using \expandafter\setmykeys\expandafter{\verbopts}.

The new verbout environment has also problems with text in the same line as \begin{verbout}. But here a command is only swallowed, there is no error.

There is also the environment verboutfile, which has an additional mandatory argument for the file name, so the text can be stored in different files. This environment has no problems with text in the same line as \begin{verboutfile}.

The code (will produce an error, see above):

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{verbatim}
%\usepackage{fancyvrb}
\usepackage{xcolor}
\usepackage{xkeyval}

%RE: LACK OF OPTIONAL ARGUMENT MAKES 1ST ITEM OF ENVIRONMENT GET EXECUTED AS IF IT WERE OPTIONAL ARGUMENT

\makeatletter
\newwrite\verbatim@out%

\def\verbatimout#1{
\begingroup%group to localise cat code reassignment?
\immediate\openout\verbatim@out#1%
\let\do\@makeother\dospecials%
\catcode\^^M\active%
\def\verbatim@processline{%
\immediate\write\verbatim@out{\the\verbatim@line}}%
\verbatim@start%
}

\def\endverbatimout{%
\immediate\closeout\verbatim@out
\endgroup
}

\def\mykeys@color{black}
\define@key{mykeys}{color}{\def\mykeys@color{#1}}

\newenvironment{verboptfail}[1][]{\verbatim}{\endverbatim}

\newenvironment{verbopt}{\verbatim\verboptarg}{\endverbatim}
\newcommand\verboptarg[1][]{\setkeys{mykeys}{#1}\color{\mykeys@color}\typeout{:::#1:::}}

\newenvironment{verbiopt}[1][]{%
\setkeys{mykeys}{#1}\typeout{:::#1:::}%
\color{\mykeys@color}%
\verbatim
}{%
\endverbatim
}

% with key set at start of environment, would work here
%\newenvironment{verbout}[1][]{%
%    \setkeys{mykeys}{#1}\typeout{***#1***}\verbatimout{1.temp}%
%}{%
%    \endverbatimout\color{\mykeys@color}\verbatiminput{1.temp}%
%}

% optional argument used at end of environment
\newenvironment{verbout}[1][]{%
\verboutarg{#1}\verbatimout{1.temp}%
}{%
\endverbatimout
\expandafter\setmykeys\expandafter{\verbopts}%
\color{\mykeys@color}\verbatiminput{1.temp}%
}
\newcommand\verboutarg[1]{\gdef\verbopts{#1}\typeout{***#1***}}
\newcommand\setmykeys[1]{\setkeys{mykeys}{#1}}

% file name as second mandatory argument, both used at end of environment
\newenvironment{verboutfile}[2][]{%
\verboutfilearg{#1}{#2}\verbatimout{#2}%
}{%
\endverbatimout
\expandafter\setmykeys\expandafter{\verbopts}%
\color{\mykeys@color}\verbatiminput{\verbfile}%
}
\newcommand\verboutfilearg[2]{%
\gdef\verbopts{#1}\typeout{***#1***}%
\gdef\verbfile{#2}\typeout{>>>#2<<<}%
}
%same as above
%\newcommand\setmykeys[1]{\setkeys{mykeys}{#1}}

\makeatother
\begin{document}
\noindent
using verbopt environment; issue: empty first line in (1) and (4) example

\noindent
XXXXXXXXXXXX
\begin{verbopt}
(1) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| without arg \end{verbopt} XXXXXXXXXXXX \begin{verbopt}\more\verb (2) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| without arg
\end{verbopt}
XXXXXXXXXXXX

\begin{verbopt}[color=blue]\more\verb
(3) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| with arg \end{verbopt} XXXXXXXXXXXX \begin{verbopt}[] (4) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\|
with EMPTY optional arg
\end{verbopt}
XXXXXXXXXXXX

\vfill
\noindent
using verbiopt environment; issue: \verb|\more| in (2) is expanded, therefore error

\noindent
XXXXXXXXXXXX
\begin{verbiopt}
(1) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| without arg \end{verbiopt} XXXXXXXXXXXX \begin{verbiopt}\more\verb (2) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| without arg
\end{verbiopt}
XXXXXXXXXXXX

\begin{verbiopt}[color=blue]\more\verb
(3) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| with arg \end{verbiopt} XXXXXXXXXXXX \begin{verbiopt}[] (4) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\|
with EMPTY optional arg
\end{verbiopt}
XXXXXXXXXXXX

\newpage
\noindent
using verbout environment, issue: swallows \verb|\more| in (2)

\noindent
XXXXXXXXXXXX
\begin{verbout}
(1) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| \end{verbout} XXXXXXXXXXXX \begin{verbout}\more\verb (2) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\|
\end{verbout}
XXXXXXXXXXXX

\begin{verbout}[color=blue]
(3) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| \end{verbout} XXXXXXXXXXXX \begin{verbout}[] (4) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\|
with EMPTY optional arg
\end{verbout}
XXXXXXXXXXXX

\vfill
\noindent
using verboutfile environment with file name as argument

\noindent
XXXXXXXXXXXX
\begin{verboutfile}{1.tmp}
(1) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| \end{verboutfile} XXXXXXXXXXXX \begin{verboutfile}{2.tmp}\more\verb (2) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\|
\end{verboutfile}
XXXXXXXXXXXX

\begin{verboutfile}[color=blue]{3.tmp}
(3) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\| \end{verboutfile} XXXXXXXXXXXX \begin{verboutfile}[]{4.tmp} (4) \x\y\z !"£$%^&*()_+-=[]{};'#:@~,./<>?\|
with EMPTY optional arg
\end{verboutfile}
XXXXXXXXXXXX
\end{document}

• Thank you for deciphering my garbled late night post. Yes, my ‘verbopt’ environment produces a extra blank line - thank you for noticing that. I had noticed this in my other endeavours but missed it here. Does anyone know why the first ‘item’ gets swallowed if and only if it’s a macro, in our example the ‘item’ is \more ? If we put a \relax in the right place (that is, after \verbabimout{1.temp} ) then \more gets coughed back up and appears in the typeset, but with the consequence that it is followed by an addition single space! – Dave R. Cole May 14 '18 at 9:17
• Well, I have another solution but it's too long to fit in the Add Comment box! Do I post it or just keep it to myself? – Dave R. Cole May 14 '18 at 9:21

Regarding the use of a mandatory argument. Well my non-minimal (or real) environment actually invents the filename based on a counting mechanism, so I don’t want a mandatory argument. We could always write an empty mandatory arg , but if we forget then we are right back to where we started! Of course, there is no problem if we assume that the ‘optional’ arg is, well mandatory - I mean if we always write the optional arg even if its empty []. So that we don’t forget to write [] then we could test for it in the environment definition and report an error message. With that said, I am considering the following as a solution:

\documentclass{article}
\usepackage{verbatim,xcolor,nopageno}
\makeatletter
\newwrite\verbatim@out%
\def\verbatimout#1{\begingroup\immediate\openout\verbatim@out#1\let\do\
@makeother\dospecials\catcode  \^^M\active\def\verbatim@processline{\
typeout{VERBATIM: \the\verbatim@line}\immediate\write\verbatim@out{\the\
verbatim@line}}\verbatim@start}
\def\endverbatimout{\immediate\closeout\verbatim@out\endgroup}
\newenvironment{myenv}{\@ifnextchar[{\@myarg}{\errmessage{some error
message}\verbatimout{1.temp}}}{\endverbatimout\verbatiminput{1.temp}}
\def\@myarg[#1]{{\color{red}[#1]}\verbatimout{1.temp}}%delimited arg
\makeatother
\begin{document}\noindent
xxxxxxxxxxxxxxxxxxxx
\begin{myenv}\more\verb
\x\y\z␣!" $%^&*() + \end{myenv} xxxxxxxxxxxxxxxxxxxx \begin{myenv}[]\more\verb \x\y\z␣!"$ %^&*() +
\end{myenv}
xxxxxxxxxxxxxxxxxxxx
\end{document}


which gives

xxxxxxxxxxxxxxxxxxxx
\verb
\x\y\z !"$%^&*()_+ xxxxxxxxxxxxxxxxxxxx [] \more\verb \x\y\z !"$%^&*()_+
xxxxxxxxxxxxxxxxxxxx


This now seems to behave like the (V)erbatim(O)out{} macro of the fan- cyvrb package. The fancyvrb package gives a garbled error message through: ‘Extraneous input between \beginmyenv[key-value] and line end’ even when we have no [] and even when we’re not using key-values at all!