18

In the paper "Beautiful Code Compelling Evidence", by J.R. Heard -- Code is formated in a particular way which includes margin comments. I am looking for a way to do this as I think it is a very clear way to comment comment code in a literate programming style.

20

As mentioned already in the comments you can use escapeinside option of lstlisting (listings package) to execute own code inside a code listing. There are also executebegin and executeend to insert code automatically before and after such markers.

My idea: * Use minipages to restrain the listing to less than the text width and move it to the right using some horizontal space. * A separation line like in the linked paper can be added using the frame=l option. * Use the above commands to add comments at the beginning of code lines. * The automatic added code places the comments to the left using \llap{<content>\hspace{<distance>}} without taking up any official space. * To allow multi-line comments an extra minipage with correct alignment is added around the comments.

The code would look like this: (first listing only supports single line comments while the second supports multi-line comments!)

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage{lmodern} % better tt fonts!

\usepackage{xcolor}
\usepackage{listings}

\usepackage{lipsum}% dummy text

\makeatletter
\def\comsep{\dimexpr\lst@numbersep+\lst@frametextsep\relax}% most likely not correct!
\makeatother
\begin{document}

\lipsum

\begin{minipage}{\linewidth}
\hspace*{.3\linewidth}%
\begin{minipage}{.7\linewidth}
\begin{lstlisting}[frame=l,basicstyle=\ttfamily,language=C,
    escapeinside={(*@}{@*)},
    escapebegin={\begin{lrbox}{0}\normalfont\itshape\small\color{black!70}},
    escapeend={\end{lrbox}\llap{\box0\hspace{\comsep}}}
    ]
(*@ Declare it   @*) int i = 0;
(*@ useless!     @*) i + i;
(*@ increment    @*) i++:

(*@ now print it @*) print i;
\end{lstlisting}
\end{minipage}
\end{minipage}


\begin{minipage}{\linewidth}
\hspace*{.3\linewidth}%
\lstset{% set here because `\linewidth` has still its old value
    escapeinside={(*@}{@*)},
    escapebegin={\begin{lrbox}{0}\minipage[t]{.3\linewidth}\raggedleft\normalfont\itshape\small\leavevmode\color{black!70}\ignorespaces},
    escapeend={\endminipage\end{lrbox}\llap{\raisebox{0pt}[0pt][0pt]{\box0}\hspace{\comsep}}}
}%
\begin{minipage}{.7\linewidth}
\begin{lstlisting}[frame=l,basicstyle=\ttfamily,language=C]
(*@ Declare it   @*) int i = 0;
(*@ useless!     @*) i + i;
(*@ increment; more text more    @*) i++:

(*@ now print it @*) print i;
\end{lstlisting}
\end{minipage}
\end{minipage}



\end{document}

This looks as follows:

Result

If this is used more often a new environment could be defined (\newlstenvironment) or the settings can be set globally.

Note: In theory this could be hacked deeper into the listings code to allow the comment to be added at the end instead of the start. This would simplify the adding of comments but would be much more difficult to code.

  • (+1) I was about to ask a similar question! In ConTeXt, I used to rely on custom paragraphs (usually defined as \defineparagraphs[ecode][n=2,rule=on]) to create such side-by-side layout but I guess the above code could be translated to ConTeXt without too much difficulty. It has the merit of having the code and associated comments on the same line. – chl Dec 7 '11 at 10:38

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.