marcel@cs.caltech.edu (Marcel van der Goot) (05/16/91)
[Note: This posting is not so easy. However, it is very worthwhile to try and understand it, both for plain TeX users and for LaTeX users who want to write their own macros. Category codes are rather essential in TeX, and the source of many problems with macros. ] Binod K. Taterway (lubkt@spectrum.CC.Lehigh.EDU) writes > I want to place a box around the verbatim environment. Unfortunately, > when I do the following, > > % Make boxes. Inspired from Exercise 21.3 from TeXbook. > \def\boxit#1{\vbox{\hrule\hbox{\vrule \kern1.2pt > \vbox{\kern1.2pt{ \parindent 0pt > \tt #1}\kern1.2pt}\kern1.2pt\vrule} > \hrule}} > > \boxit{ > \begin{verbatim} > this better come out in boxed verbatim mode ... > \end{verbatim} > } > > I get the following error message: > [...] First the reason your solution doesn't work (this is the hard part): As you are probably aware, character tokens in TeX have the form <character code, category code>. The character code is just the ascii code, the catcode (which is the culprit in this case) is the catcode of that character when TeX first read it. E.g., the catcode of @ is normally 12, but if you set \catcode`@=11, then from that point on all @ characters \em{that are read from the file} will be assigned catcode 11. However, each character token gets its catcode only once, namely when it is read from the file. Once a character is read, its catcode cannot be changed. Now, for your problem: When you do \begin{verbatim}, a lot of catcodes are changed. Basically, the catcodes of all special characters (such as \, $, and #) are set to 12 (which indicates a normal character rather than a special one). Then the text that must be set is read, which now consists of normal characters only. However, in your case, that text is already read, namely as argument of the \boxit macro. Therefore, all the catcodes of that text are already fixed, and cannot be changed. Hence, nothing happens when the \begin{verbatim} is executed. The solution: We have to prevent reading the verbatim text before we do \begin{verbatim}. Therefore, the \boxit macro is split into two macros: \Beginboxit for the part that comes before the boxed text, and \Endboxit for the part that comes after the boxed text. That way the boxed text is not read too early. To split the definition of \boxit, every { is replaced by \bgroup, every } by \egroup. (The definition was also reformatted ...) %%%%%%%%%%%%%%%%%%%% \def\Beginboxit {\vbox\bgroup \hrule \hbox\bgroup \vrule \kern1.2pt % \vbox\bgroup\kern1.2pt } \def\Endboxit{% \kern1.2pt \egroup \kern1.2pt\vrule \egroup \hrule \egroup } \newenvironment{boxit}{\Beginboxit}{\Endboxit} %%%%%%%%%%%%%%%%%%%% Now you can say: \begin{boxit} \begin{verbatim} this better come out in boxed verbatim mode ... \end{verbatim} \end{boxit} This does not change the margin; you'll have to do that yourself (or find someone else to do it). An interesting experiment for LaTeX hackers: In the above macro definition, change \Beginboxit to \beginboxit, and \Endboxit to \endboxit. Marcel van der Goot .---------------------------------------------------------------- | Blauw de viooltjes, marcel@vlsi.cs.caltech.edu | Rood zijn de rozen; | Een rijm kan gezet | Met plaksel en dozen. |