# Custom environment with parameter: You can't use macro parameter character #' in vertical mode

I want to define a new environment to display blocks of plain text in a titled box, with whitespace reproduced exactly. Something like this

\begin{PlainText}{My Title}
Foo
Bar
\end{PlainText}


I'm putting a definition together by gathering various tips, but it doesn't work.

\newenvironment{TextFile}[1]{\ttfamily}{\par}
{
#1\\[1ex]
\begin{center}
\begin{tabular}{|p{0.9\textwidth}|}
\hline
\\
}
{
\\ \\
\hline
\end{tabular}
\end{center}
}


I only 80% understand how this is intended to work, I read the first line as meaning

TextFile is a new environment which takes one parameter, within it the font is monospace and \par means retain whitespace like HTML <pre>

I get an error at the #1\\[1ex] line

 You can't use macro parameter character #' in vertical mode.


When it works, it should look like this:

• \newenvironment{TextFile}[1]{\ttfamily}{\par} is wrong, of course and 'plain' text could be difficult. You should rather think of a verbatim environment. And don't forget to accept answers to your other questions – user31729 Jan 15 '17 at 17:24
• The intented code is not making use of #1, even worse, it's outside of the environment definition – user31729 Jan 15 '17 at 17:27

## 2 Answers

The definition of

\newenvironment{TextFile}[1]{\ttfamily}{\par}
{
#1\\[1ex]
\begin{center}
\begin{tabular}{|p{0.9\textwidth}|}
\hline
\\
}
{
\\ \\
\hline
\end{tabular}
\end{center}
}


is wrong, at least the parts with { #1\\ }{...}, which are surely meant as the real document body, not something outside after the {\par} statement which is the end code part of the environment.

This way #1 ... etc. is meant as typesetting after the environment definition which must fail unless the definition is wrapped itself in another command or environment.

\documentclass{article}

\newenvironment{TextFile}[1]{\ttfamily%
#1 \\[1ex]
\begin{center}
\begin{tabular}{|p{0.9\textwidth}|}
\hline
\\
}{%
\\ \\
\hline
\end{tabular}
\end{center}
\par
}

\begin{document}

\begin{TextFile}{Foo}
Learning \LaTeXe\ is fun!
\end{TextFile}

\end{document}


Your definition doesn't work because \newenvironment has the following syntax:

\newenvironmnt{<envname>}[<parms>][<opt>]
{<begin envname>}% \begin{<envname>}
{<end envname>}% \end{<envname>}


You've used it with no optional arguments (so [<opt>] has been removed) but supplied four mandatory arguments instead of two (the two being {<begin envname>} and {<end envname>}). Any of the arguments specified in [<parms>] are only available within {<begin envname>}, yet you've attempted to use it inside the third mandatory argument, where it doesn't exist.

The following approaches ensure that the title and subsequent block stay together and fit within the text block width.

\documentclass{article}

\usepackage{tabularx}

\newenvironment{TextFile}[1]
{% \begin{TextFile}{#1}
\par\ttfamily
\noindent
% http://tex.stackexchange.com/a/42331/5764
\tabularx{\linewidth}{|X|}
\multicolumn{1}{c}{#1} \\[1ex]
\hline \\
}{% \end{TextFile}
\\ \\
\hline
\endtabularx
\par\medskip
}

\begin{document}

\begin{TextFile}{My Title}
Foo \\
Bar
\end{TextFile}

\end{document}


Another option using listings:

\documentclass{article}

\usepackage{listings}

\lstnewenvironment{TextFile}[1]
{\lstset{
basicstyle = \ttfamily,
frame      = lrtb,
title      = {\ttfamily #1}}}
{}

\begin{document}

\begin{TextFile}{My Title}
Foo
Bar
\end{TextFile}

\end{document}