Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I've been following the instructions and code available at: https://zuttobenkyou.wordpress.com/2010/12/05/latex-saner-source-code-listings-no-starch-press-style/

I would like to add notes (and style) to lstlisting environments similar to those in No Starch Press publications:

Optimal output

Unfortunately it depends on XeTeX and I've added conditional support for it in my document, but this is problematic with pgf/tikx since the xetex driver isn't very complete, and I also have issues with monospace fonts such as DejaVu Sans Mono, which results in (very) weird invalid kerning.

How can I avoid the xetex dependency using a similar approach for notes and pdftex?

Update: Check my answer for tikz-based solution with support for unlimited sidenotes.

Thanks to Mike Renfro for the input!

share|improve this question

2 Answers 2

Not perfect, but it works on a subset that may be sufficient for you. Using The Comprehensive LaTeX Symbol List to scan for the circled numbers and such:

enter image description here

\documentclass{article}
\usepackage[x11names]{xcolor} % for a set of predefined color names, like LemonChiffon1
\usepackage{listings}
\usepackage{textcomp}
\newcommand{\numold}[1]{\oldstylenums{#1}}

% Allow "No Starch Press"-like custom line numbers (essentially, bulleted line
% numbers for only those lines the author will address)
\usepackage{pifont}
\usepackage{ifthen}
\newcounter{lstNoteCounter}
\newcommand{\lnnum}[1]{% Print pifont circled number for line label
\ifcase#1%
% nothing for 0
\or\ding{202}%
\or\ding{203}%
\or\ding{204}%
\or\ding{205}%
\or\ding{206}%
\or\ding{207}%
\or\ding{208}%
\or\ding{209}%
\or\ding{210}%
\or\ding{211}%
\else{NUM TOO HIGH}%
\fi%
}
\newcommand*{\lnote}{%
\stepcounter{lstNoteCounter}\vbox{\llap{{\lnnum{\thelstNoteCounter}}\hskip 1em}}%
}
\lstnewenvironment{csource2}[1][]
{
    \setcounter{lstNoteCounter}{0}
    \lstset{basicstyle=\ttfamily,language=C,numberstyle=\numold,numbers=right,
            frame=lines,framexleftmargin=0.5em,framexrightmargin=0.5em,
            backgroundcolor=\color{LemonChiffon1},showstringspaces=false,
            escapeinside={(*@}{@*)},#1}
}
{}

\begin{document}
\section{Hello, world!}
The following program \texttt{hello.c} simply prints ``Hello, world!'':

\begin{csource2}
(*@\lnote@*)#include <stdio.h>

/* This is a comment. */
(*@\lnote@*)int main()
{
(*@\lnote@*)    printf("Hello, world!\n");
(*@\lnote@*)    return 0;
}
\end{csource2}

We first include the \texttt{stdio.h} header file \lnnum{1}. We then declare
the \texttt{main} function \lnnum{2}. We then print ``Hello, world!'' to
standard output (a.k.a., \textit{STDOUT}) \lnnum{3}. Finally, we return value
0 to let the caller of this program know that we exited safely without any
errors \lnnum{4}.
\end{document}

It won't handle more than 10 circled number labels, but does work with regular pdflatex. Someone else can make TikZ code for those labels and extend it past the 20 labels in the original.

share|improve this answer
    
Let's hope someone comes up with the tikz version, but many thanks for all the effort :) (I'm actually having trouble using the original code too, seems something is wrong with my global listings lset catch-all). –  soze Apr 12 '12 at 1:54
    
Any chance for something with better resolution? (so the numbers inside the circles are a bit more "crisp" to the eye) –  soze Apr 12 '12 at 2:28
    
Please check my update. Does \oldstylenums work fine on both xetex and pdftex? –  soze Apr 12 '12 at 3:44
    
In an attempt to duplicate the shown example, you could use numbers=left,numbersep=3em to push the regular line numbers further left. –  Werner Apr 12 '12 at 5:08
    
Werner, I've detected problems with both versions (mine and yours). For instance, depending on the identation level of the annotated level, the corresponding circle is placed erroneously in the margin. So spaces affect its placement. I don't know what's causing it. –  soze Apr 13 '12 at 18:51
up vote 4 down vote accepted

I've decided to do my own tikz-based version, mostly because the actual quality of the output is better even compared to a properly scalable glyph. It has no limitations as to how many "annotated lines" you can add, and you get fine-grained support for the typography inside each circle.

%\newcommand{\mynumold}[1]{{\addfontfeature{Numbers=OldStyle}#1}}
\newcommand{\mynumold}[1]{{\oldstylenums{#1}}}

\newcounter{lstNoteCounter}

\newcommand*\lnnum[1]{\tikz[baseline=(char.base)]{
            \node[shape=circle,draw,inner sep=0.8pt,
                        fill=black, text=white] (char) { \rmfamily\bfseries\footnotesize#1};}}

\newcommand*{\lnote}{\stepcounter{lstNoteCounter}\llap{{\lnnum{\thelstNoteCounter}}\hskip 6em}}

\lstnewenvironment{annotatedcsource}[1][]
{
    \setcounter{lstNoteCounter}{0}
        \lstset{
            frame=lines,
            framexleftmargin=0.5em,
            framexrightmargin=0.5em,
            basicstyle=\ttfamily\footnotesize,
            numberstyle=\normalsize\itshape\mynumold,
            backgroundcolor=\color{LemonChiffon1},
            showstringspaces=false,
            numbers=left,
            escapeinside={(*@}{@*)},#1}
        }
{}

This is the output:

output

Currently it has some issues:

  • The size of the circle might break the way the background is displayed. This won't show up if it's white, but the spacing between the affected line and others is affected either way. One workaround is to make it larger to accommodate more space, choose a smaller font size for the circle text or some such.

Also, sorry about the garbled code block. See for yourself and adjust the hline spacing.

Update: I have posted the following question looking for answers on how to properly solve the alignment problems (so far I've solved the background display through the overlay feature): Position tikz pictures at left margin of a listing code block

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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