8

I'm looking for an environment similar to Verbatim which will allow me to say something like the following code (which uses indentation instead of spaces):

\documentclass{article}

\usepackage{fancyvrb}
\usepackage[margin=1in]{geometry}

\begin{document}
    \begin{enumerate}
        \item We first set \texttt{x} to infinity if it is positive:
            \begin{Verbatim}
                if x > 0:
                    x = \infty
            \end{Verbatim}
    \end{enumerate}
\end{document}

and get back exactly the following, in terms of the indentation, the escaping of all symbols (like \infty), etc.

Screenshot

The problem with Verbatim is that it requires me to un-indent the body with respect to the rest of the code, which makes my source code ugly. (I also can't use verbatim because it forces me to use spaces.) Furthermore, I can't figure out how to embed special symbols in it, either.

Is there some environment that fixes these problems with a not-too-difficult syntax for inserting special symbols and math into the code? (Ideally, I would want \ and $ to be the escape characters, but anything that isn't too difficult to type will do.)

4
  • The indentation is done with tabs, I guess. But you can also indent with spaces (in the fancyvrb documentation you can BTW find this remark: “using tabs is in fact a rather old-fashioned style of coding”). In fancyvrb there’s an option gobble, with that you can suppress a certain amount of spaces or even tabs (max. 9 chars). Note also the options obeytabsand tabsize. I am surprised, too, that you didn’t get an error message while compiling your MWE. Normally you should have to define commandchars first.
    – Speravir
    Mar 21, 2012 at 3:27
  • Actually the shown image can not be produced with the code of the MWE!
    – Speravir
    Mar 21, 2012 at 17:59
  • I added an answer, where I show you something of that, what I’ve wriiten in my first comment.
    – Speravir
    Mar 21, 2012 at 23:03
  • @Mehrad: please see my updated answer with a new solution solving the tabs issue. Mar 21, 2012 at 23:35

5 Answers 5

18

UPDATE

Martin Scharrer's lstautogobble package takes care of the tabs issue using the listings package; for the other issues, you can and the mathescape=true, and escapeinside options; a little example:

\documentclass{article}
\usepackage{listings}
\usepackage{lstautogobble}

\lstset{basicstyle=\ttfamily,
  mathescape=true,
  escapeinside=||,
  autogobble}

\begin{document}

    \begin{enumerate}
        \item We first set \texttt{x} to infinity if it is positive:
            \begin{lstlisting}
                if $x > 0$:
                     $x = \infty$
                if x > 0:
                     x = $\infty$
            \end{lstlisting}
    \end{enumerate}

\end{document}

enter image description here

The file lstautogobble.sty can be found in this answer to How to automatically skip leading white spaces in listings

5
  • Is there any way to make it look like TTY text, the way verbatim and Verbatim do?
    – user541686
    Mar 21, 2012 at 3:12
  • @Mehrdad: sure; see my updated answer. Mar 21, 2012 at 11:26
  • Gonzalo, that's bad: I already had upvoted your answer and then your edit is so much better, but I can’t upvote twice :-) …
    – Speravir
    Mar 22, 2012 at 0:18
  • @Speravir: no problem and thank you. Most of the credit, if not all, goes to Martin and his package ;-) Mar 22, 2012 at 0:23
  • This is freaking amazing. Thanks so much to both you and Martin!! :)
    – user541686
    Mar 22, 2012 at 0:45
4

In order to allow indenting the code as pleases to you, TeX generally ignore spaces at the beginning of a line.

This poses a "chicken and egg" problem: when \begin{Verbatim} is sensed, the spaces that precede it have already been thrown out and TeX can't know how many it should discard at the beginning of verbatim lines unless you tell it (there's a gobble option to the Verbatim environment provided by fancyvrb). Only inside the Verbatim environment spaces at the beginning of a line are not ignored, because they are significant.

I'm not saying that the general problem is not solvable, but a solution requires a different reading of the input (for example maintaining a count of how many spaces are thrown out at the beginning of the line), which is simply not possible in TeX, but might be realized in LuaTeX.

I don't think that indenting code as you do is "nice": to the contrary, I never do that in normal text, but only in macro definitions. It's a matter of opinion, of course. Unfortunately, you have to live with "ugly" code when you need verbatim material, or pass explicitly the indentation level with the gobble option.

3
  • Whoa, so you never indent your code like that? How do you match opening/closing tags then? (Isn't it painful?)
    – user541686
    Mar 21, 2012 at 11:00
  • @Mehrdad Is balancing environments painful? No. :)
    – egreg
    Mar 21, 2012 at 12:18
  • Side note – there's still an option of counting how many spaces there are before the \end environment; however that disables typesetting the content line-by-line thus likely lose synctex information without some special handling. Another option would be to re-read the file at line \inputlineno to determine how many spaces there are, although that's costly (re-read the whole file for each verbatim environment).
    – user202729
    Jul 7, 2022 at 4:29
3

Let me show the opportunities in an answer (it’s obviously too long for a another comment):

As I pointed out in my comment, you can indent also with spaces, which is in my opinion the better variant, because it’s much better predictable. But, see my example code:

\documentclass{article}

\usepackage{fancyvrb}
% Let us first define a custom Verbatim environment, that saves us a lot of writing
  \DefineVerbatimEnvironment{VerbatimTest}{Verbatim}%
    {showspaces,showtabs,commandchars=\\\{\}}% showspaces and showtabs only for visualizing

\begin{document}

Remember, options ``showspaces'' and ``showtabs'' are active.

\begin{enumerate}
  \item First, no change, indenting with spaces (using the \$ sign would
        require an additional definition, see fancyvrb manual, section
        "Catcode characters").

        \begin{VerbatimTest}
          if x > 0:
            x = \(\infty\)
        \end{VerbatimTest}

  \item Second, gobbling 8 space chars (up to nine are possible).

        \begin{VerbatimTest}[gobble=8]
          if x > 0:
            x = \(\infty\)
        \end{VerbatimTest}

  \item From now on indenting with tabs, first line for comparising indented
        with spaces, note that by default one tab stands for 8 (!) characters.

        \begin{VerbatimTest}
          First line indented with spaces
        if x > 0:
            x = \(\infty\)
        \end{VerbatimTest}

  \item Now gobbling one character (here one space or one tab).

        \begin{VerbatimTest}[gobble=1]
          First line indented with spaces
        if x > 0:
            x = \(\infty\)
        \end{VerbatimTest}

  \item You can define with ``tabsize'', how many spaces are represented by
        one tab (here 1 tab = 4 spaces).

        \begin{VerbatimTest}[tabsize=4]
          First line indented with spaces
        if x > 0:
            x = \(\infty\)
        \end{VerbatimTest}

  \item Last in combination: ``tabsize=4'' and ``gobble=1''.

        \begin{VerbatimTest}[tabsize=4,gobble=1]
          First line indented with spaces
        if x > 0:
            x = \(\infty\)
        \end{VerbatimTest}
\end{enumerate}

\end{document}

The output looks as follows:

output of example code

2
  • Yeah I was looking for something automatic (I don't want to change the gobble values every time I indent/unindent), but +1 anyway I guess.
    – user541686
    Mar 21, 2012 at 23:25
  • @Mehrdad: You can of course give the option gobble with a global value in the preamble definition, too. If somewhere in the document you need a different gobble, you can add it there, and this overwrites the global definition then.
    – Speravir
    Mar 21, 2012 at 23:40
2

enter image description here

This counts the spaces used to indent the first line and removes that many spaces from all lines.

\documentclass{article}

\usepackage{fancyvrb}
\usepackage[margin=1in]{geometry}
\makeatletter
\def\zzz{\FV@Space}
\def\hmm#1{%
\let\zz=#1%
\ifx\zz\zzz
\toks@\expandafter{\the\toks@#1}%
\expandafter\hmm
\else
\expandafter\hmmb
\fi}
\def\hmmb#1\relax{%
\expandafter\gdef\expandafter\hmmc\the\toks@{}}

\def\FancyVerbFormatLine#1{%
\gdef\FancyVerbFormatLine##1{\hmmc##1}%
\toks@{}%
\hmm#1\relax\relax
\hmmc#1}

\begin{document}
    \begin{enumerate}
        \item We first set \texttt{x} to infinity if it is positive:
            \begin{Verbatim}[commandchars=\\\{\}]
                if x > 0:
                    x = \(\infty\)
            \end{Verbatim}
    \end{enumerate}
\end{document}
1

Use alltt.sty file and then use \begin{alltt} for math use \(

Example:

\documentclass{article}
\usepackage{fancyvrb}
\usepackage[margin=1in]{geometry}
\usepackage{alltt}

\begin{document}
\begin{enumerate}
    \item We first set \texttt{x} to infinity if it is positive:
        \begin{alltt}
            if \(x > 0\):
                \(x = \infty\)
        \end{alltt}
\end{enumerate}

\end{document}

and also use:

\begin{enumerate}
    \item We first set \texttt{x} to infinity if it is positive:
    \begin{Verbatim}[commandchars=\\\{\}, codes={\catcode`$=3\catcode`^=7}]
                if $x>0$:
                   $x=\infty$
    \end{Verbatim}
\end{enumerate}
1
  • Thanks but that doesn't fix the space issue.
    – user541686
    Mar 21, 2012 at 5:19

You must log in to answer this question.

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