\documentclass{article}
\usepackage[a5paper,landscape]{geometry}
\usepackage{url}
\usepackage{listings}
\usepackage{tikz}
\usepackage{eso-pic}
\usepackage[calc]{picture}
\usetikzlibrary{decorations.pathreplacing,arrows,tikzmark,calc}
\usetikzmarklibrary{listings}
\newcommand{\addstufftoforegroundall}[1]{%
\AddToShipoutPictureFG{% Add <stuff> to all following pages' foreground
\put(0,\paperheight){\vtop{{\null}\makebox[0pt][l]{#1}}}%
}%
}%
\newcommand{\addstufftoforegroundthis}[1]{%
\AddToShipoutPictureFG*{% Add <stuff> to the current page foreground
\put(0,\paperheight){\vtop{{\null}\makebox[0pt][l]{#1}}}%
}%
}%
\makeatletter
\def\getpicturepage#1{%
@nameuse{save@pg@@nameuse{save@pt@#1}}%
}
\lst@AddToHook{EOL}{%
\begingroup
\ifcsname listings-deferline-\lst@name-\the\c@lstnumber\endcsname
\iftikzmarkcurrentpage{line-\lst@name-\the\c@lstnumber-end}{%
\let\addstufftoforeground\addstufftoforegroundthis
}{%
\let\addstufftoforeground\addstufftoforegroundall
}%
\edef\pagehookstuff{%
\noexpand\addstufftoforeground{%
\noexpand\iftikzmarkcurrentpage{line-\lst@name-\the\c@lstnumber-end}{%
@nameuse{listings-deferline-\lst@name-\the\c@lstnumber}%
}{}%
}%
}%
\global\expandafter\let\csname listings-deferline-\lst@name-\the\c@lstnumber\endcsname@undefined
\pagehookstuff
\fi
\ifcsname listings-eol-execute-\lst@name-\the\c@lstnumber\endcsname
@nameuse{listings-eol-execute-\lst@name-\the\c@lstnumber}%
\fi
\endgroup
}
\newcommand{\iftikzmarkcurrentpage}[3]{%
\iftikzmark{#1}{%
\ifcsname save@pg@@nameuse{save@pt@#1}\endcsname
\expandafter\ifnum\getpicturepage{#1}=\the\c@page\relax
#2%
\else
#3%
\fi
\else
#3%
\fi
}{%
#3
}%
}
\newcommand{\appendhookorcreatenew}[2]{%#1<- hook csname, #2<- code to add
% note: code in #2 is not expanded at this stage!
\ifcsname #1\endcsname
\expandafter\g@addto@macro\csname #1\endcsname{\unexpanded{#2}}%
\else
@namedef{#1}{\unexpanded{#2}}%
\fi
}
\newcommand*{\deferlinecode}[3]{% #1<-listing name, #2<-line number, #3<-code
\appendhookorcreatenew{listings-deferline-#1-#2}{#3}%
}
\colorlet{annotationColor}{red}
\newlength\annotationLinewidth
\setlength\annotationLinewidth{0.6pt}
\tikzset{%
note/.style={annotationColor,
font=\sffamily\scriptsize,%\bfseries
align=center,
text width=2.5cm
},
every round node/.style={
draw,
shape=rounded rectangle,
rounded rectangle arc length=180,
inner sep=+.333em,
text depth=+.1ex}
}
% utility function
\makeatletter
\def\ifPositive#1{%
@ifnextchar{-}%
{\expandafter@secondoftwo\remove@to@nnil}%
{\expandafter@firstoftwo\remove@to@nnil}%
#1@nnil
}
\makeatother
%\AddNoteVBrace{listing}{line-start}{line-end}{x-pos}{text}
\newcommand{\AddNoteVBrace}[5]{%
\deferlinecode{#1}{#2}{\tikz[overlay, remember picture]
\draw [decoration={brace,amplitude=0.5em},decorate,annotationColor,line width=\annotationLinewidth]
($([xshift=#4]pic cs:line-#1-#2-start)!([yshift=1ex]pic cs:line-#1-#2-start)!($([xshift=#4]pic cs:line-#1-#2-start)-(0,1)$)$) --
($([xshift=#4]pic cs:line-#1-#3-start)!([yshift=-.25ex]pic cs:line-#1-#3-start)!($([xshift=#4]pic cs:line-#1-#3-start)-(0,1)$)$)
node [note, pos=0.5,anchor=west] {#5};}%
}%
%\AddNoteVLine{listing}{line-start}{line-end}{x-pos}{text}
\newcommand{\AddNoteVLine}[5]{%
\deferlinecode{#1}{#2}{\tikz[overlay, remember picture]
\draw [annotationColor,line width=\annotationLinewidth]
($([xshift=#4]pic cs:line-#1-#2-start)!([yshift=1ex]pic cs:line-#1-#2-start)!($([xshift=#4]pic cs:line-#1-#2-start)-(0,1)$)$) --
($([xshift=#4]pic cs:line-#1-#3-start)!([yshift=-.25ex]pic cs:line-#1-#3-start)!($([xshift=#4]pic cs:line-#1-#2-start)-(0,1)$)$)
node [note, align=left, pos=0.5, anchor=west] {#5};}%
}%
%\AddNoteRight{listing}{line}{label-x-offset}{label-y-offset}{text}
\newcommand{\AddNoteRight}[5]{%
\deferlinecode{#1}{#2}{\tikz[overlay, remember picture]
\def\anchor{south}\ifx&\else \ifPositive{#4}{}{\def\anchor{north}}\fi
\draw[<-,>=stealth,annotationColor,line width=\annotationLinewidth] (pic cs:line-#1-#2-end) +(0.25,.5ex) -| +(\ifx&1\else#3\fi,\ifx&2.5ex\else#4\fi) node[note,anchor=\anchor] {#5};}%
}%
%\AddNoteTop{listing}{line}{x-pos}{label-x-offset}{label-y-offset}{text}
\newcommand{\AddNoteTop}[6]{%
\deferlinecode{#1}{#2}{\tikz[overlay, remember picture]
\def\anchor{west}\def\align{left}
\ifx&\else \ifPositive{#4}{}{\def\anchor{east}\def\align{right}}\fi
\draw[<-,>=stealth,annotationColor,line width=\annotationLinewidth] ($([xshift=#3]pic cs:line-#1-#2-start) +(0,2.5ex)$) |- +(\ifx&1\else#4\fi,\ifx&2.5ex\else#5\fi)
node[note,align=\align,anchor=\anchor] {#6};}%
}%
%\AddNoteBottom{listing}{line}{x-pos}{label-x-offset}{label-y-offset}{text}
\newcommand{\AddNoteBottom}[6]{%
\deferlinecode{#1}{#2}{\tikz[overlay, remember picture]
\def\anchor{west}\def\align{left}
\ifx&\else \ifPositive{#4}{}{\def\anchor{east}\def\align{right}}\fi
\draw[<-,>=stealth,annotationColor,line width=\annotationLinewidth] ($([xshift=#3]pic cs:line-#1-#2-start) +(0,-1.5ex)$) |- +(\ifx&1\else#4\fi,\ifx&-2.5ex\else-#5\fi)
node[note,align=\align,anchor=\anchor] {#6};}%
}%
%\AddBox{listing}{line}{x-start}{x-end}
\newcommand{\AddBox}[4]{%
\deferlinecode{#1}{#2}{\tikz[overlay, remember picture]
\draw[annotationColor,line width=\annotationLinewidth] ($([xshift=#3]pic cs:line-#1-#2-start) +(-.25ex,-.25ex)$) rectangle ($([xshift=#4]pic cs:line-#1-#2-start) +(.5ex,2.0ex)$);}%
}%
%\AddUnderline{listing}{line}{x-start}{x-end}
\newcommand*{\AddUnderline}[4]{%
\deferlinecode{#1}{#2}{\tikz[overlay, remember picture]
\draw[annotationColor,line width=\annotationLinewidth] ($([xshift=#3]pic cs:line-#1-#2-start) +(0,-.25ex)$) -- ($([xshift=#4]pic cs:line-#1-#2-start) +(0,-.25ex)$);}%
}%
\AddNoteVBrace{texcode}{1}{3}{4cm}{Note VBrace}
\AddNoteVLine{texcode}{5}{7}{4cm}{Note VLine}
\AddUnderline{texcode}{9}{0cm}{3cm}
\AddBox{texcode}{11}{1cm}{3cm}
\AddNoteTop{texcode}{15}{0cm}{5cm}{}{Note Top}
\AddNoteRight{texcode}{15}{3cm}{-2cm}{Note Right}
\AddNoteBottom{texcode}{15}{1cm}{}{}{Note Bottom}
\lstset{
language={[LaTeX]TeX},
numbers=left,
breaklines=true,
basicstyle=\small\ttfamily,
columns=flexible,
}
\begin{document}
\title{Example output of code annotation}
\author{\url{http://tex.stackexchange.com/questions/86309/macros-for-code-annotations}}
\maketitle
This is only to illustrate how one might go about adding annotations to code that spans across more than one page.
The annotations to be added have to specified before the listing appears.
It is not very robust to lost notes, eg if attempting to add an annotation to a blank line where there may not be an end marker.
\begin{lstlisting}[name=texcode]
\documentclass{article}
\usepackage{listings}
\title{Sample Document}
\author{John Smith}
\date{\today}
\begin{document}
\maketitle
Hello World!
% This is a comment.
\end{document}
\end{lstlisting}
\end{document}
\documentclassand the appropriate packages that sets up the problem. While solving problems is fun, setting them up is not. Then those trying to help can simply cut and paste your MWE and get started on solving problem. – Peter Grill Dec 10 '12 at 04:37\begin{tikzpicture}and one after\end{tikzpicture}. Put percent signs after the opening brace of the\newcommandand after\end{tikzpicture}and that should stop things shifting. – Andrew Stacey Dec 10 '12 at 22:16