I just found another way - using the delimiter option of lstlisting, to insert tikz nodes at the quote characters. The nuisance is that you have to decide and specify amount of nesting levels (and their colors) apriori; but the good thing is that you can hide the processed quote characters altogether - while the other such characters pass untouched (and so no escaping or interventions are required in the raw text source); and also you can draw lines with decorations if you want (oh yeah, and you have to tex twice, because of tikz overlays):

The code is not really straightforward, some overloading of listings.sty stuff is required - see comments in the code below:
\documentclass{article}
\usepackage{listings}%
\usepackage{xcolor}%
% \usepackage{unravel}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}
% \usepackage{trace}
% \pagecolor{yellow!15}
\begin{document}
\newcounter{testa} % just to see how newcounter works with resetting:
% \unravel{
\newcounter{testb}[testa]
% \@cons \cl@testa {{testb}} -> \xdef \cl@testa {\@elt {testb}}
% }
\makeatletter
\def\lnm{\the\lst@lineno}
\def\lnc{\the\lst@column}
\def\lnp{\the\lst@pos} % character column, but as -1, -34..
% \lst@lineno is newcount; "let" it to
% a macro named accordingly so can link to it in newcounter
\let\c@lst@lineno\lst@lineno
\let\cl@lst@lineno\relax
\newcounter{unm}[lst@lineno]
% \@cons\cl@lst@lineno{{unm}} % ! TeX capacity exceeded, sorry
% \xdef\cl@lst@lineno{\@elt{unm}} %cannot: unm needs to be added to list of lst@lineno, which is reset upon addtocounter, which lst@lineno doesn't use
% hack in lst@MProcessListing (listings.sty), to call \extralstlinecall before change of line number
\gdef\extralstlinecall{\typeout{EXTRA LINE \lnm}}
\def\lst@MProcessListing{%
\lst@XPrintToken \lst@EOLUpdate \lsthk@InitVarsBOL
\extralstlinecall
\global\advance\lst@lineno\@ne
\ifnum \lst@lineno>\lst@lastline
\lst@ifdropinput \lst@LeaveMode \fi
\ifx\lst@linerange\@empty
\expandafter\expandafter\expandafter\lst@EndProcessListing
\else
\lst@interrange
\lst@GetLineInterval
\expandafter\expandafter\expandafter\lst@SkipToFirst
\fi
\else
\expandafter\lst@BOLGobble
\fi}
\makeatother
\tikzstyle{every picture}+=[remember picture] % must have
\tikzstyle{nn} = [inner sep=0pt, outer sep=0pt, minimum size=0pt]
\tikzstyle{qln} = [line width=2pt]
% quote colors:
\colorlet{qcol0}{blue!50}
\colorlet{qcol1}{orange!50}
\colorlet{qcol2}{cyan!50}
\gdef\lastqcol{2} % declare how many levels/colors we expect (last index)
\colorlet{defaultcol}{.} % current color
% percolumn node lists - same ammount as qcols
\gdef\setpcol#1#2{%
\global\expandafter\edef\csname pcoll-#1\endcsname{#2}%
}
\gdef\addpcol#1#2{%
\expandafter\ifx\csname pcoll-#1\endcsname\empty%
\global\expandafter\edef\csname pcoll-#1\endcsname{#2}%
\else%
\global\expandafter\edef\csname pcoll-#1\endcsname{\csname pcoll-#1\endcsname,#2}%
\fi%
}
\setpcol{0}{}
\setpcol{1}{}
\setpcol{2}{}
% we know nodes are NXX-YY here, so
\global\let\e\relax
\gdef\getnameXY N#1-#2\e#3#4{%
%\typeout{getname \string#1, \string#2, \string#3, \string#4}%
\xdef#3{#1}%
\xdef#4{#2}%
}
% \getnameXY NXX-YY\e\tmpa\tmpb
% \typeout{tmpa \tmpa, tmpb \tmpb}
% {\uccode`A=10
% \uppercase{\xdef\lf{A}}}
\xdef\qnodelist{}
\xdef\qnodelistx{}
\xdef\qnodelisty{}
\xdef\lastlnm{0}
\def\repl{%
\tikzstyle{every picture}+=[remember picture] % must have
\pgfmathtruncatemacro{\clnp}{-1*\lnp}%
\ifnum\lnm=\lastlnm%
\stepcounter{unm}%
\else%
\setcounter{unm}{0}%
\fi%
\xdef\lastlnm{\lnm}%
\ifnum\clnp>\lastqcol%
\setcounter{unm}{\lastqcol}%
> % output verbatim character; cannot insert LF (\n): ^^J; also give space betw. char and % sign!
\else%
\edef\tnnd{N\lnm-\theunm}%
\tikz[baseline=(\tnnd.base)]{%
\node[nn] (\tnnd) {\phantom{>}};%
\draw[qln,draw=qcol\theunm] (current bounding box.north) -- (\tnnd.south);%
}%
\ifx\qnodelist\empty%
\xdef\qnodelist{\tnnd}%
\xdef\qnodelistx{\lnm}%
\xdef\qnodelisty{\clnp}%
\else%
\xdef\qnodelist{\qnodelist,\tnnd}%
\xdef\qnodelistx{\qnodelistx,\lnm}%
\xdef\qnodelisty{\qnodelisty,\clnp}%
\fi%
\addpcol{\clnp}{\tnnd}
\color{qcol\theunm}% this spills color; to stop it, use a reset in \extralstlinecall!
\fi%
%\typeout{ln \lnm, col \lnc, pos \clnp, unm \theunm}%
}
\gdef\extralstlinecall{%
\color{defaultcol}%
\typeout{EXTRA LINE \lnm}%
}
\lstset{
basicstyle=\ttfamily\small,
% {\^^M}{{\^^M}}1 % matches, but cannot insert, end of line (actually, para!)
literate={>}{{\repl}}1 ,% kills the >,>> morecomments!
morecomment=[l][\color{red!50}]{>>\ },
morecomment=[l][\color{green!80}]{>\ },
%morecomment=[f][\color{green!80}][0]{\^^M}, % locks
}
\begin{lstlisting}
At 10.01am Wednesday, Danny wrote:
> At 9.40am Wednesday, Jim wrote: >>check here<<
>> I'm going to suspend the mail service for approx. thirty
>> minutes tonight, starting at 5pm, to install some updates
>> and important fixes.
>
> Whoa! Hold on. I have a job scheduled at 5:30 which mails out
> a report to key tech staff. Could you push it back an hour?
>
>> I'm going to suspend the mail service for approx. thirty
>> minutes tonight, starting at 5pm, to install some updates
>> and important fixes.
>
> By the way, which systems will be updated? I had some network
> problems after last week's update. Will I have to reboot?
No problems. 6pm it is then.
Basically, I will update our WWW server and firewall.
No, you won't have to reboot.
> By the way, which systems will be updated? I had some network
> problems after last week's update. Will I have to reboot?
> Will I have to reboot?
No, you won't have to reboot.
\end{lstlisting}
\qnodelist
\tikzstyle{bnl} = [line width=1pt,decoration=snake,decorate]
% \begin{tikzpicture}[overlay]
\foreach \ix in {0,...,\lastqcol}{
\xdef\strt{}\xdef\endr{}
\expandafter\edef\expandafter\ptmp{\csname pcoll-\ix\endcsname}
\typeout{ptmp: '\ptmp'}
% will not loop if \ptmp empty; that's why all pcoll-\ix must be initialized to empty
\ifx\ptmp\empty\else
\foreach \inn in \ptmp {
\expandafter\getnameXY\inn\e\trow\tcol % get
\typeout{\inn, \trow, \tcol, '\strt', '\endr'}
\ifx\strt\empty
\xdef\strt{\trow}
\xdef\endr{\trow}
\else
\pgfmathtruncatemacro{\isNeighbor}{\trow-\endr == 1}
\typeout{isNeigh \isNeighbor: \trow, \strt, \endr}
\ifnum\isNeighbor=1{}\else
\tikz[overlay]\draw[bnl,qcol\tcol!60] (N\strt-\tcol) -- (N\endr-\tcol);
\xdef\strt{\trow}
\fi
\xdef\endr{\trow}
\fi
} % foreach
\tikz[overlay]\draw[bnl,qcol\tcol!60] (N\strt-\tcol) -- (N\endr-\tcol);
\fi
}
% \end{tikzpicture}
\end{document}
\tikzmarksolution of @PeterGrill :-) – percusse Mar 27 '12 at 06:07\tikzmarkwould be useful but that would require editing the email text. So if it was to be used just a few times that would work. But, if you want to simply incorporate an existing email from an external file and not have to edit it, then listings is probably the way to go. – Peter Grill Mar 27 '12 at 14:52\tikzmarkhave a look at How to draw arrows between parts of an equation to show the Math Distributive Property (Multiplication)?, or Draw a line through one column of a matrix – Peter Grill Mar 27 '12 at 14:53listings. However, many thanks for the\tikzmarklinks - those certainly point to a way of how a graphical solution (with vertical lines) would work. Cheers! – sdaau Mar 28 '12 at 04:40