使用 LaTeX 排版具有互联网风格引用的电子邮件?

使用 LaTeX 排版具有互联网风格引用的电子邮件?

我想知道是否存在一个包,可以接受所谓的互联网风格引用电子邮件的纯文本,并根据 PDF 输出对其进行相应的格式化。互联网风格的引用在维基百科页面中进行了讨论发帖风格;因此假设我从那里取一个例子,并且我有以下内容作为email.eml文件的内容:

At 10.01am Wednesday, Danny wrote:
> At 9.40am Wednesday, Jim wrote:
>> 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?
>
> 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.

然后,我想象可以准备类似的东西email.tex,我可以使用它来获取格式化的 PDF:

\documentclass{article}
\usepackage{???}

\begin{document}

\begin{QUOTEDEMAIL}
\input{email.eml}
\end{QUOTEDEMAIL}

\end{document}

我希望至少能够控制选择不同级别引用回复(以 ' >' 为前缀的行)的颜色(灰度)...但是,如果我还可以控制字体 - 或者渲染行而不是 ' >'(就像 Thunderbird 所做的那样),那就太棒了!:)

那么,存在类似的事情吗?

答案1

这只是一个部分解决方案,但它将是可行的方法 - 使用listings

在此处输入图片描述

\documentclass{article}
\usepackage{listings}% http://ctan.org/pkg/listings
\usepackage{xcolor}% http://ctan.org/pkg/xcolor
\begin{document}
Here is the message:

\lstset{
  basicstyle=\ttfamily\small,
  morecomment=[l][\color{red!50}]{>>\ },
  morecomment=[l][\color{green!80}]{>\ },
}

\lstinputlisting{email.eml}
\end{document}

各个回复级别的格式化是通过 完成的morecomments,实际上指定该行“代码”为“注释”。listings无法在上述示例中拾取空行,但如果您不介意使用特定级别的格式,则可以正确解释

\lstset{
  basicstyle=\ttfamily\small,
  morecomment=[l][\color{red!50}]{>},
}

说。请注意,>在电子邮件的其他地方使用可能会导致问题。

答案2

我刚刚找到了另一种方法 - 使用delimiterlstlisting 选项,tikz在引号字符处插入节点。麻烦的是,您必须先决定并指定嵌套级别的数量(及其颜色);但好处是您可以完全隐藏已处理的引号字符 - 而其他此类字符则不受影响(因此原始文本源中不需要转义或干预);并且您还可以根据需要绘制带有装饰的线条(哦,是的,由于 tikz 覆盖,您必须使用 tex 两次):

测试02a.png

代码并不是很简单,需要对 listings.sty 内容进行一些重载 - 请参阅以下代码中的注释:

\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}

相关内容