4

(I'm aware there has been a similar question before, but this one has a twist)

I wanted a verbatim macro to use which would use an unlikely character as an end-of-verbatim -marker (unlikely as in it would be unlikely to be included in the text that would become verbatim), and looked up a couple of suggestions from Appendix D of The TeXbook, until something caught my eye:

Another approach is to keep one character untouchable. For example, it’s possible to define things so that \verbatim⟨char⟩⟨text⟩⟨char⟩ will typeset the ⟨text⟩ verbatim, where the ⟨text⟩ is not supposed to contain any occurrences of the repeated delimiter ⟨char⟩:

\def\verbatim{\begingroup\setupverbatim\doverbatim}
\def\doverbatim#1{\def\next##1#1{##1\endgroup}\next}

Now, combining this with XeTeX would allow me to use a character from the wide, wide Unicode range as the end-marker. (Based on the finding that I can do eg. \def\fi{foo}, and it works.)

Alas, adding to the above the previously mentioned macros from Appendix D:

\def\setupverbatim{\tt\def\par{\leavevmode\endgraf} \catcode`\`=\active
   \obeylines\uncatcodespecials\obeyspaces}
\def\uncatcodespecials{\def\do##1{\catcode`##1=12 }\dospecials}

and trying it out (the fi -character is the Unicode fi-ligature),

\verbatim fi |\%_^foo{\it bar}
baz
fi
\bye

gives me an error about Missing $, which means there is something not working with the \verbatim macro. I just can't figure out what.

3 Answers 3

3

It's the space character after \verbatim.

After you change the catcode of the space character, it's not considered space anymore. Consider the output of

\def\a#1\relax{`#1'}
\def\b{\catcode`\ =12 \a}

\a \relax

\b \relax

\bye

enter image description here

Thus, your example only typesets in verbatim mode, and returns to normal after encountering the second space after .

It follows that you need to have a delimiter character immediately after \verbatim. Therefore its catcode can't be "letter", because otherwise it will be taken as a part of the control sequence name.

2
  • 3
    One should note that the space after \verbatim terminates the scanning for the control sequence name, but it's not tokenized right away, because after a control sequence name TeX must enter "skipping blanks state"; therefore the space is effectively read after \verbatim has been expanded and \setupverbatim has changed the category code of the space.
    – egreg
    Sep 16, 2011 at 15:55
  • Oooh, the catcode change! I assume every char (outside the chars TeX knows) has a catcode of letter in the eyes of XeTeX, then. Thanks!
    – morbusg
    Sep 16, 2011 at 16:02
2

The following codes defines \verb command:

\catcode`\@=11%
\def\verb{\expandafter\verb@make\string}%
\def\verb@make#1{\begingroup\tt%
  \let\verb@delim=#1%  Save the delimiter.
  \def\verb@print##1{%
    \if##1\verb@delim% If we found the end delimiter, end the group.
      \def\verb@print{\def\verb@print{}\endgroup}%
    \else%
      ##1% Print the char
    \fi%
    \expandafter\verb@print\string% Continue reading the next char.
  }%
  \expandafter\verb@print\string% Start reading.
}%
\catcode`\@=12%

Some examples:

\verb|{$x^y{}$\abc}|

\verb!{$x^y{}$\abc}!

\verb~${x^y{}$\abc}~

All the above produces verbatim ${x^y{}$\abc}.

1
  • It doesn't respect spaces, though.
    – egreg
    Jan 28, 2012 at 22:06
1

The problem is in the space following \verbatim, as found out by Andrey. One should note that the space after \verbatim terminates the scanning for the control sequence name, but it's not tokenized right away, because after a control sequence name TeX must enter "skipping blanks state"; therefore the space is effectively read after \verbatim has been expanded and \setupverbatim has changed the category code of the space.

If you don't want to have a limitation on what characters can delimit the verbatim snippet, it's possible to improve \doverbatim:

\def\doverbatim#1{%
  \def\next{#1}%
  \ifx\next\activespacemacro
     \expandafter\doverbatim
  \else
    \def\next##1#1{##1\endgroup}%
    \expandafter\next
  \fi}
{\obeyspaces\gdef\activespacemacro{ }}

End-of-line can't be used as a delimiter (it would be possible to add another test for it). Any number of spaces can follow \verbatim.

It's curious to understand why your code gave that error, but also easy: the space after made \verbatim terminate its effect, typesetting as verbatim just the .

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .