4

In order to reduce copy-pasting, I want to create an environment that will produce a two-column table with headers and two listings in different languages, like below:

\begin{tabular}{l l}
Python & Haskell \\
\hline \\
\lstset{language=Python}
\begin{lstlisting}
A
\end{lstlisting}
&
\lstset{language=Haskell}
\begin{lstlisting}
B
\end{lstlisting}
\end{tabular}

I want to use it like below, hiding everything but code:

\begin{comparison}
A
\vs
B
\end{comparison}

So far I tried making two new environments (instead of a \vs command inside) with \lstnewenvironment, where first environment had \tabularx command and second \endtabularx. I also tried creating normal \newenvironment for this tabular, & for \vs command and manually inserting \begin{lstlistings} and \end{lstlistings} with code, but it stopped compiling when I put lstlistings inside.

How can I create such an environment?

EDIT: The most compact version I've came up with until now is

\newenvironment{comparison}
{\begin{parcolumns}[nofirstindent,distance=0pt,colwidths={1=0.35\textwidth}]{2}}
{\end{parcolumns}}

\lstnewenvironment{python}
{Python
\lstset{language=Python,frame=t}}
{}

\lstnewenvironment{haskell}
{Haskell
\lstset{language=Haskell,frame=t}}
{}

which is used like that:

\begin{comparison}
\colchunk{
\begin{python}
A
\end{python}
}
\colchunk{
\begin{haskell}
B
\end{haskell}
}
\end{comparison}

I'm still unable to hide \colchunk{} within python or haskell environments.

Troy
  • 13,741
Xilexio
  • 143
  • How can I create such an environment? With difficulty :) You cannot simply use \newenvironment because precautions have to be taken to define a new environment that is supposed to have some verbatim content. The listings package provides the \lstnewenvironment macro to create new environments for listings, but those environments can only contain one listing. You may have to define a new macro based on \lstnewenvironment to achieve what you want. – jub0bs Dec 03 '13 at 17:20
  • If your document is meant to be two-sided (like a book), an easier, though perhaps not as satisfactory, alternative would be to have two associated listings at the top or bottom of consecutive even and odd pages; the reader would then be able to compare them easily. – jub0bs Dec 03 '13 at 17:30
  • @Jubobs: This is an article paper, so it won't work. Also, I think it's impossible to do this environment for two listings, since there is no "command" sort of lstlisting, like \tabularx instead of \begin{tabularx}. Also, tabularx doesn't work well with verbatim-like environments inside, so I'm thinking of multicols/tabular and adding lstlistings environments manually (with options and headers hidden in my command). – Xilexio Dec 03 '13 at 17:50

1 Answers1

1

What you want to do is impossible with lstlisting environments, because their contents is verbatim. However, you can use \lstinputlisting.

The following approach uses a macro rather than an environment and requires using/writing to external files, but it might be useful.

  1. Type the Python and Haskell source files (outside the .tex file, or inside, using filecontents).
  2. Call the \comparison macro, which takes two arguments; the first being the relative path to the Python source file, and the second being that to the Haskell source file.

enter image description here

\documentclass{article}

\usepackage[margin=2cm]{geometry} % the listings won't fit on the page otherwise
\usepackage{listings,xcolor}
\usepackage{filecontents}

\newcommand\comparison[2]%
{%
    \begin{minipage}[t]{.45\textwidth}
        \centering \textbf{Python}\\
        \lstinputlisting[frame=single,language=Python]{#1}
    \end{minipage}
    \hfill
    \begin{minipage}[t]{.45\textwidth}
        \centering \textbf{Haskell}\\
        \lstinputlisting[frame=single,language=Haskell]{#2}
    \end{minipage}
}

% Source file for Hello World in Python
\begin{filecontents*}{HelloWorldPython.py}
print "Hello, World!"
\end{filecontents*}

% Source file for Hello World in Haskell
\begin{filecontents*}{HelloWorldHaskell.hs}
module Main where
main :: IO ()
main = putStrLn "Hello, World!""
\end{filecontents*}

\begin{document}

\comparison{HelloWorldPython.py}{HelloWorldHaskell.hs}

\end{document}
jub0bs
  • 58,916
  • I like this solution. I'll use that with additional showstringspaces=false (without underbar-like spaces in strings) to make it look more like original code and it's perfect. – Xilexio Jan 16 '14 at 14:41
  • It's still possible by collecting the content verbatim and scantokens it (or before that, write to file then input) – user202729 Dec 28 '21 at 14:43