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.

  • Well the problem is that lstlisting contains verbatim content. Do you really need syntax highlighting? – TeXnician May 27 '17 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. – tillyboy May 27 '17 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 '17 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. – David Carlisle May 27 '17 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? – tillyboy May 27 '17 at 16:14
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}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.