13

I'm trying to make a verbatim environment called "my-environ"

\documentclass{article}

\usepackage{fancyvrb}

\DefineVerbatimEnvironment{myenviron}{Verbatim}{numbers=left,frame=lines,label=My Environ,labelposition=topline}

%\DefineVerbatimEnvironment{my-environ}{Verbatim}{numbers=left,frame=lines,label=My-Environ,labelposition=topline}

\begin{document}

\begin{myenviron}
Hello
\end{myenviron}

%\begin{my-environ}
%Hello
%\end{my-environ}

\end{document}

If you uncomment the code, you'll see that it doesn't compile. I don't have to use fancyvrb, but I would like similar functionality.

1
  • 2
    Because dashes are not allowed in control words (control sequences consisting of an escape character and followed by one or more letters), dashes are not allowed in environment names either. Suggestion: use myEnviron instead.
    – jub0bs
    Apr 20, 2014 at 19:40

2 Answers 2

10

In his answer egreg has already explained that the hyphen - has a different catcode inside the verbatim environment. Package fancyvrb saves the environment name from \begin{my-environ} in \FV@EnvironName. - has the catcode before the catcode changes of the verbatim environment, usually 12 (other). Then inside the environment fancyvrb looks for \end{...} and checks if ... matches \FV@EnvironName. But - has now catcode 13 (active) and the strings my-environ does not match because of the different catcode of - and fancyvrb fails to see the end of the environment.

The example hacks the macros of fancyvrb to define \FV@EnvironCheckName that stores my-environ with the catcodes of the verbatim environment. The hack requires e-TeX because of \scantokens, \everyeof, and \unexpanded to get the unexpanded environment name with the catcodes, which are active after the catcode settings of the verbatim environment.

\documentclass{article}

\usepackage{fancyvrb}

\DefineVerbatimEnvironment{my-environ}{Verbatim}{
  numbers=left,
  frame=lines,
  label=My-Environ,
  labelposition=topline,
}

\makeatletter
\renewcommand*{\VerbatimEnvironment}{%
  \ifx\FV@EnvironName\relax
    \xdef\FV@EnvironName{\@currenvir}%
    \begingroup
      \endlinechar=-1 %
      \everyeof{\@nil\noexpand}%
      \xdef\FV@EnvironCheckName{%
        \expandafter
        \FV@CatchUnexpanded\scantokens\expandafter{\@currenvir}%
      }%
    \endgroup
  \fi
}
\def\FV@CatchUnexpanded#1\@nil{\unexpanded{#1}}
\begingroup
\catcode`\^^M=\active
\gdef\FancyVerbGetLine#1^^M{%
  \@nil%
  \FV@CheckEnd{#1}%
  \ifx\@tempa\FV@EnvironCheckName%            % True if end is found
    \ifx\@tempb\FV@@@CheckEnd\else\FV@BadEndError\fi%
    \let\next\FV@EndScanning%
  \else%
    \def\FV@Line{#1}%
    \def\next{\FV@PreProcessLine\FV@GetLine}%
  \fi%
  \next%
}%
\endgroup
\makeatother

\begin{document}

\begin{my-environ}
Hello
\end{my-environ}

\end{document}

Result

16

The problem is quite subtle. In general, a hyphen is allowed to be in an environment name, just like any other non special character (and also some special ones, actually). However, it's not possible to use some of them in a verbatim environment, because the verbatim mode makes them active; in latex.ltx you find

\def\verbatim@nolig@list{\do\`\do\<\do\>\do\,\do\'\do\-}

and the characters in the list, that is `<,'- are made active in order (La)TeX not make the usual ligatures

?` !` << >> ,, `` '' -- ---

However, the end of your verbatim environment is delimited by a string

\end{my-verbatim}

which fancyvrb builds before setting the active characters above. A string in the sense that all characters have category code 12; fancyvrb loads a line at the time and compares it to the ending string. However, if the name of the environment contains one of the characters above, the ending string can't be found.

It's maybe possible to hack the macros so that those characters are allowed, but the best is to use only letters.

1
  • This is good to know! (I realize the question seems crazy)
    – Bart Snapp
    Apr 20, 2014 at 20:13

You must log in to answer this question.

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