[Tex/LaTex] Source Code Margin Comments

commentslistingsmarginpar

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.

Best Answer

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.