5

How can I define a column of a table to contain lstlistings?

The background is that I want to write my own cheat sheet for Haskell, in which I have mainly tabular environments that contain the keywords and a short explanation.

A first very naive attempt, which compiles just fine, looks like this:

\documentclass{article}
\usepackage{xcolor}
  \definecolor{greencyan}{rgb}{0.5, 1.0, 0.83}
  \definecolor{marine}{rgb}{0.0, 0.5, 1.0}
  \definecolor{firebrick}{rgb}{0.7, 0.13, 0.13}
\usepackage{listings}
  \lstset{
    language=haskell,
    basicstyle=\ttfamily,
    commentstyle=\color{gray}\textit,
    keywordstyle=\color{firebrick},
    numberstyle=\color{marine},
    stringstyle=\color{greencyan},
    breaklines=true
  }
\usepackage{array}

\begin{document}
  \begin{tabular}{ll}
    \lstinline$[]       $ & empty list initiation            \\
    \lstinline$++       $ & list concatenation               \\
    \lstinline$x:list   $ & prepend x to list                \\
    \lstinline$head list$ & first element of a list          \\
    \lstinline$tail list$ & all but first element of a list  \\
    \lstinline$init list$ & last element of a list           \\
    \lstinline$last list$ & all but last element of a list   \\
  \end{tabular}

\end{document}

It his however quite tedious to always make a \lstinline$<code>$ in every second cell of the whole document, and since the array package allows me to use the math environment in tables via \newcolumntype{m}{>{$}l<{$}} I thought it might be useful to define myself a columntype for source code like so:

\documentclass{article}
...    % same as above, not necessary for the problem
\usepackage{array}
  \newcolumntype{f}{>{\begin{lstlisting}}l<{\end{lstlisting}}}

\begin{document}
  \begin{tabular}{fl}
    []        & empty list initiation           \\
    ++        & list concatenation              \\
    head list & first element of a list         \\
    tail list & all but first element of a list \\
    init list & last element of a list          \\
    last list & all but last element of a list  \\
  \end{tabular}

\end{document}

Which throws a whopping 103 errors at me, starting with Missing \endcsname inserted. [ [] Wanting to use the lstlistings environment and not lstinline, for the upcoming multiline function definitions on the cheatsheet I tried to bring that environment inside a tabular cell like I did with the lstinline:

\documentclass{article}
...
\usepackage{array}

\begin{document}
  \begin{tabular}{ll}
    \begin{lstlisting} []        \end{lstlisting}& empty list initiation           \\
    \begin{lstlisting} ++        \end{lstlisting}& list concatenation              \\
    \begin{lstlisting} head list \end{lstlisting}& first element of a list         \\
    \begin{lstlisting} tail list \end{lstlisting}& all but first element of a list \\
    \begin{lstlisting} init list \end{lstlisting}& last element of a list          \\
    \begin{lstlisting} last list \end{lstlisting}& all but last element of a list  \\
  \end{tabular}

\end{document}

This gets me down to one error:

: TeX STOPPED: fatal errors occured. Check the TeX log file for details []

Checking the log file, I guess the relevant lines are the following, although I do not know how to fix that error.

! TeX capacity exceeded, sorry [input stack size=5000].
\end #1->\csname end#1
                      \endcsname \@checkend {#1}\expandafter \endgroup \if@e...
l.44     \begin{lstlisting} []        \end
                                    {lstlisting}  & empty list initiatio...
If you really absolutely need more capacity,
you can ask a wizard to enlarge me.

Please note that the line numbers do not match with the MWE since I have one file in which I have all versions and can comment and uncomment them for testing purposes.

Which brought me to the point that maybe, although that would be a huge shame, the lstlistings environment does not work inside the tabular environment. So I tried to define a column to be a lstinline column:

\documentclass{article}
...    % same as above, not necessary for the problem
\usepackage{array}
  \newcolumntype{f}{>{\lstinline$}l<{$}}

\begin{document}
  \begin{tabular}{fl}
    []        & empty list initiation           \\
    ++        & list concatenation              \\
    head list & first element of a list         \\
    tail list & all but first element of a list \\
    init list & last element of a list          \\
    last list & all but last element of a list  \\
  \end{tabular}

\end{document}

One one hand, this would be a pain in the rear for multiline function definitions, while on the other hand I still get two errors from this:

Improper alphabetic consonant. [ []
mwe.tex: TeX STOPPED: File ended while scanning use of \lst@tem\ETC.[]

If you got this far, thanks for your kind attention. In addition to my question asked above and a fix for the cheat sheet, can anybody explain the behaviour that leads to all of these errors?

I guess it has something to do with the lstlistings environment and that it ignores most of the normal LaTeX commands, but I still don't get why only one option works while all others will fail.

6
  • Well the problem is that lstlisting contains verbatim content. Do you really need syntax highlighting?
    – TeXnician
    May 27, 2017 at 11:03
  • Depends on your definition of "really needing" something. At least I'd highly appreciate having Syntax highlighting for this as in my experience it often brings a huge amount of structure into the code, especially in a confusing language like Haskell.
    – tifrel
    May 27, 2017 at 11:14
  • 2
    Yeah well there's at least tex.stackexchange.com/questions/297210/…, tex.stackexchange.com/questions/207973/…, stackoverflow.com/questions/3220121/…. Especially the last is interesting.
    – TeXnician
    May 27, 2017 at 11:18
  • 2
    as with any verbatim environment it turns off all standard processing so & does not end the table cell (imagine if your code had been C it would need & all over) so & is a normal character within the listing. verbatim environments just have special code to look for the end string which must be literally there, <{\end{lstlisting} relies on & meaning end of table cell and inserting that code but that is never going to happen here. May 27, 2017 at 15:40
  • @DavidCarlisle thanks for your answer, which at least clarified why I can't have easy-going code-columns (at least not without major trickery aka rewriting a lot of code that already exists). Do you also know why the \begin{} \end{} syntax fails inside a tabular cell?
    – tifrel
    May 27, 2017 at 16:14

2 Answers 2

5

I can't judge how robust this solution is but using the collcell package and defining a new column

\newcolumntype{H}{>{\collectcell\lstinline}l<{\endcollectcell}}

seems to work at least for your MWE.

\documentclass{article}
\usepackage{xcolor}
  \definecolor{greencyan}{rgb}{0.5, 1.0, 0.83}
  \definecolor{marine}{rgb}{0.0, 0.5, 1.0}
  \definecolor{firebrick}{rgb}{0.7, 0.13, 0.13}
\usepackage{listings}
  \lstset{
    language=haskell,
    basicstyle=\ttfamily,
    commentstyle=\color{gray}\textit,
    keywordstyle=\color{firebrick},
    numberstyle=\color{marine},
    stringstyle=\color{greencyan},
    breaklines=true
  }
\usepackage{array}
\usepackage{collcell}

\newcolumntype{H}{>{\collectcell\lstinline}l<{\endcollectcell}}

\begin{document}

\begin{tabular}{Ll}
  []        & empty list initiation            \\
  ++        & list concatenation               \\
  x:list    & prepend x to list                \\
  head list & first element of a list          \\
  tail list & all but first element of a list  \\
  init list & last element of a list           \\
  last list & all but last element of a list
\end{tabular}

\end{document}

enter image description here

1

If structure is all you're after, you can just set the descriptions as \comments within an lstlisting environment:

enter image description here

\documentclass{article}

\usepackage{xcolor}
\definecolor{greencyan}{rgb}{0.5, 1.0, 0.83}
\definecolor{marine}{rgb}{0.0, 0.5, 1.0}
\definecolor{firebrick}{rgb}{0.7, 0.13, 0.13}
\usepackage{listings}
\lstset{
  language=haskell,
  basicstyle=\ttfamily,
  commentstyle=\color{gray}\textit,
  keywordstyle=\color{firebrick},
  numberstyle=\color{marine},
  stringstyle=\color{greencyan},
  breaklines=true,
  mathescape
}
\newcommand{\comment}{\textrm}

\begin{document}

\begin{lstlisting}
[]         $\comment{empty list initiation}$
++         $\comment{list concatenation}$
x:list     $\comment{prepend x to list}$
head list  $\comment{first element of a list}$
tail list  $\comment{all but first element of a list}$
init list  $\comment{last element of a list}$
last list  $\comment{all but last element of a list}$
\end{lstlisting}

\end{document}

Even line-breaking is not an issue:

enter image description here

% ...
\usepackage{makecell}
\newcommand{\comment}[1]{\textrm{\makecell[tl]{#1}}}

\begin{document}

\begin{lstlisting}
[]         $\comment{empty list initiation}$
++         $\comment{list concatenation}$
x:list     $\comment{prepend x to list}$
head list  $\comment{first element of a list}$
tail list  $\comment{all but first element of a list}$
init list  $\comment{last element of a list \\ and something below that}$
last list  $\comment{all but last element of a list}$
\end{lstlisting}

\end{document}

You must log in to answer this question.

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