# Wrapping code (listings, verbatim, or other method) inside a newcommand

For some teaching I've been doing, I'd like to have code from two different languages side-by-side. To do so, I hacked together a newcommand which uses a tabular environment to arrange two verb environments, but the problems are myriad:

• Indentation can only be accomplished by changing spaces to ~'s

• Any math symbols have to be escaped with \, which requires knowing which ones to escape and which ones not to (can't escape the <'s for instance, otherwise it complains)

• The <- assignment operator gets changed into an upside down !- when compiled.

The listings environment doesn't work either. Error message is:

Runaway argument?
! Forbidden control sequence found while scanning use of \lst@next.
<inserted text>
\par
l.23 \codeListing{x <- y}{f(g(x))}


Here's some code to reproduce the problem:

\documentclass[english]{article}
\usepackage[latin9]{inputenc}
\usepackage{geometry}
\begin{document}

\newcommand{\codeListing}[2]{
\begin{tabular}{p{8cm} p{8cm}}
\begin{lstlisting}
#1
\end{lstlisting}
&
#2\tabularnewline
\end{tabular}
}

\section{verbatim test}
\begin{verbatim}
logLik <- function(x) {
y <<- x^2+2
return(sum(sqrt(y+7)))
}
\end{verbatim}

\section{codeListing test}
\codeListing{}{
logLik <- function(x) \{

~~y <<- x\^2+2

~~return(sum(sqrt(y+7)))

\}

}

\end{document}


Is there any way to make a newcommand wrap parameter-passed code? It doesn't have to be keyword-highlighted or do any of the other tricks that the fancier packages do; it just has to preserve whitespace and no interpret code as latex commands.

• You might want to use a minipage or parallel environment. Note also that listings and minted (and a few others) are specialized in printing computer code (which is closer to your need than verbatim). – ℝaphink Aug 13 '11 at 6:33
• @Raphink I think I tried listings a few months ago but it didn't handle R code well? Can't remember precisely. I'll take a look at the others. Thanks. – Ari B. Friedman Aug 13 '11 at 6:43
• You can define unsupported language when using listings package. Read its manual by typing texdoc listings in your DOS prompt. – xport Aug 13 '11 at 7:48
• @xport Thanks for pointing that out. It's been a few months since I tried making listings work but perhaps I'll give it another go. Is there any reason to prefer listings over minted or any of the others? – Ari B. Friedman Aug 13 '11 at 7:52

We recently considered adding some support for verbatim arguments to xparse. Starting from roughly 15/08/2011 (on the svn, not yet on CTAN), you can define a command with any combination of optional, mandatory and verbatim arguments. Each command defined with xparse has an argument signature which indicates what kind of argument it expects (the most common are m for normal mandatory argument, o for optional, s, for an optional star). With the new argument type, for instance, \verb would have a signature {sv}: an optional star followed by a verbatim argument.

For your case, I think a good idea is to give the signature { O{} +v O{} +v } to \codeListing:

• #1, optional argument = options given to the first listing (default empty);
• #2, verbatim argument = contents of the first listing;
• #3, optional argument = options given to the second listing (default empty);
• #4, verbatim argument = contents of the second listing;

The + mean that the next argument is "long". For non-verbatim arguments, this means that they may contain more than one paragraph. For verbatim arguments, it currently means that they may contain line-breaks, contrarily to the normal \verb command.

[Apart from the use of xparse, I based the example on Mike Renfro's answer.]

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand {\codeListing} { O{} +v O{} +v }
{
\begin{table}[h]\centering
\begin{tabular}[width=\textwidth]{ll}
\newlinechar=\endlinechar
\exp_args:Nx \scantokens
{
\string\begin{lstlisting}[\unexpanded{#1}]
#2
\string\end{lstlisting}
&
\string\begin{lstlisting}[\unexpanded{#3}]
#4
\string\end{lstlisting}
}
\end{tabular}
\end{table}
}
\ExplSyntaxOff
\usepackage[a4paper,margin=2cm]{geometry}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{lipsum}
\begin{document}
\lipsum[1]

\codeListing[language=C,backgroundcolor=\color{yellow!30}]$#include <stdio.h> int main(void) { printf("Hello world\n"); return 0; }$[language=C++,backgroundcolor=\color{red!20}]$#include <iostream> using namespace std; int main() { cout << "Hello World!" << endl; return 0; }$

\lipsum[2]

\end{document}

• This will break if one of the verbatim arguments includes a } won't it? Is there any plan to allow abritrary argument delimiters? – Seamus Aug 15 '11 at 15:44
• No wait, your example uses $ as a delimiter. How? – Seamus Aug 15 '11 at 15:46 • @Seamus: it can use (almost) anything as a delimiter, like \verb. And the two verbatim arguments can use different delimiters. More precisely, in this case, xparse looks for an optional argument, tokenizing whichever token is next. Then the delimiter for the verbatim argument is that first token. Thus, the delimiter for the verbatim argument cannot be %, \ , space, #, {, nor }, but anything else (that doesn't appear in the argument you want) works. – Bruno Le Floch Aug 15 '11 at 18:37 • Unknown argument type 'v' replaced by 'm'. Fingers crossed ... That is what I get... – Karel Bílek Aug 26 '12 at 15:04 • @KarelBilek Your installation of the l3package bundle (and probably l3kernel too is too old. The verbatim argument type was added roughly a year ago. – Bruno Le Floch Aug 26 '12 at 21:22 Starting from @xport's example, and minimizing it as much as possible, this is as close as I can get to the brevity of a two-argument command. Maybe someone else can take it the rest of the way. \documentclass{article} \usepackage[a4paper,margin=2cm]{geometry} \usepackage{listings} \lstnewenvironment{K}{\lstset{language=C}}{} \lstnewenvironment{M}{\lstset{language=C++}}{} \newenvironment{T}{\begin{table}[h]\centering\begin{tabular}[width=\textwidth]{ll}}{\end{tabular}\end{table}} \usepackage{lipsum} \begin{document} \lipsum[1] \begin{T} \begin{K} #include <stdio.h> int main(void) { printf("Hello world\n"); return 0; } \end{K} & \begin{M} #include <iostream> using namespace std; int main() { cout << "Hello World!" << endl; return 0; } \end{M} \end{T} \lipsum[2] \end{document}  Think about what things like verbatim and listings are doing. They are suspending LaTeX's normal reading of symbols and printing those symbols out directly. So \verb~$~ says to LaTeX "Don't interpret anything up to the next "~"". That is, LaTeX reads \verb and then it says "OK, the next symbol signals the start of the verbatim text: I should search for the next instance of that symbol and ignore everything in between them". It then sees a "~", so it searches for the next matching symbol and doesn't interpret anything between them. That's why \verb~\end{document}~ doesn't end the document: LaTeX isn't interpreting those symbols that would normally signal the end of the document.

What you want to do with a \newcommand is going to be tricky. Things are being read in the wrong order. Look at the following:

\codeListing{$e^i$}{}


This becomes ei: not $e^i$ as you want. The text isn't being ignored. That's why you're getting a lot of weird things going on.

Also, compare:

\codeListing{%}{}
\codeListing{}}{}


which both break, and:

\verb~%~
\verb~}~


which should work fine.

I think the "multiple environment" method of xport and Mike Renfro is as good as it gets here. You simply can't "hide" the verbatim commands inside new commands: LaTeX doesn't know what to do with them. Listings has to provide a new way of making new listings evnironments \lstnewenvironment because trying to put a listings inside a \newenvironment breaks...

## External SourceCode.cs file

using System;
public class Foo
{
public static void Main()
{
Console.WriteLine("I Love LaTeX");//This is a comment.
}
/*This is a comment too.*/
}


## TeX input file

\documentclass{article}
\usepackage[a4paper,margin=2cm]{geometry}
\usepackage[table,cmyk,dvipsnames]{xcolor}
\usepackage{array,longtable}

\arrayrulewidth=\fboxrule
\tabcolsep=2\fboxsep
\arrayrulecolor{white}

\newcolumntype{A}[2]{%
>{\begin{minipage}{%
\dimexpr#2\linewidth-2\tabcolsep-#1\arrayrulewidth\relax}%
\vspace\tabcolsep}c<{\vspace\tabcolsep
\end{minipage}}}

\usepackage{listings}
\lstset
{
language=[Sharp]C,
breaklines=true,
breakindent=0pt,
tabsize=3,
aboveskip=0\dimexpr\fboxsep+\fboxrule\relax,
belowskip=-\dimexpr\fboxsep+\fboxrule\relax,
frame=single,
framesep=\fboxsep,
framerule=\fboxrule,
rulecolor=\color{Yellow!30},
xleftmargin=0\dimexpr\fboxsep+\fboxrule\relax,
xrightmargin=\dimexpr\fboxsep+\fboxrule\relax,
showstringspaces=false,
basicstyle=\color{Maroon}\scriptsize\tt,
keywordstyle=\color{Blue}\sf\bf,
stringstyle=\color{Green},
backgroundcolor=\color{Yellow!30}
}

\usepackage{lipsum}
\begin{document}
\lipsum[1]
\begin{longtable}{*2{|A{1.5}{0.45}}|}\hline
\lstinputlisting{SourceCode.cs}&\lstinputlisting{SourceCode.cs}\tabularnewline\hline
\lstinputlisting{SourceCode.cs}&\lstinputlisting{SourceCode.cs}\tabularnewline\hline
\end{longtable}
\lipsum[2]
\end{document}

• This works but the key part of my question is that I need it inside a \newcommand (and the code needs to be inline since I have dozens of 1-5 line snippets rather than a few large code files). – Ari B. Friedman Aug 13 '11 at 12:49
• From section 5.1 of the listings documentation, it might not be worth it to even try to put the code into arguments. You'd have to modify your line breaks, spaces and tabs, special characters, etc. – Mike Renfro Aug 13 '11 at 14:21

One possible work around is to use a temporary file.

First you need a macro to write to the file (\jobname.tmp was used here) and read it twice using the regular and the listing input commands:

\usepackage{listings}
\newwrite\tempfile
\newcommand{\example}[1]{
\immediate\openout\tempfile=\jobname.tmp
\immediate\write\tempfile{#1}
\immediate\closeout\tempfile
\input{\jobname.tmp}
\lstinputlisting{\jobname.tmp}
}


Then use previous commands where you want to place the content. Notice that we have to use the \unexpanded macro.

\example{\unexpanded{\lipsum[1]}}


As shown in the following image that uses a method simular to the above one:

Note: lipsum package must be used for the given example.