11

Edit: I am not happy with the 3 answers my first, smaller bounty got me. So I rewrote the question to set clear rules and a proper bounty.


The solution should create two environments, originalemail and response with the following effects:

  • The originalemail-environment can be wrapped around normal LaTeX code, which might include lists, sections, etc, and that is then typeset normally, but in a way that slightly (4pt) indents all text and adds a vertical line on the left.
  • The response environment can be used inside the originalemail environment and results in the vertical line being broken and the contained text/code being aligned on the left without the originalemails indentation. The response has to be aligned to the left margin, irrespective of where in the originalemail it is placed (e.g., within a (nested) itemize or enumerate).

Summary

  • leave the layout of the original email in-tact (it should be possible to use sections, lists, paragraphs, floats, etc. as if it as was a plain TeX document and there were no responses and the numbering should be the same with and without respones)
  • using these environments should require no editing of the code after \begin{document}, outside the response environment. In particular any suspension or resume of enumerate or itemize environments---if required by the solution---should be automatic.
  • The only way in which the original layout should change is that it show vertical line (2pt) on the left margin and ideally a slight indentation (4pt).
  • responses and the fragments of the original email have to break pages as normal. (if you use parbox for the responses they wont)
  • allow to insert \replys anywhere in the the original text
  • bonus if the solution is nesteable (i.e. the outer originalemail contains an older originalemail and responses)

Rules: for the bounty, you're free to build on the existing answers, i.e. @marmot's/Gonzalo Medina's TikZ approach to draw the line in the left margin, @Vinccool96's tcolorbox or my own rudimentary approach to automatically suspending and resuming lists.

Screenshot from Gmail that roughly summarizes what I need: enter image description here

Input example This is a simple example of the document I am starting with. It is a standard LaTeX document, which I wrap into \begin{originalemail}...\end{originalemail}. Next I need to add my responses to it, but this should work context-independent (i.e. without manually tracking which other environments are currently open, which is why the answer by @Vinccool96 was not accepted)

Of course you may edit the preamble in order to define the new environments.

\documentclass{article}
%you may add code here
\begin{document}
%you may add code here
    \begin{originalemail}
     %inside this, the only change I can make to the code may be within
     % \begin{response}...\end{response}
        Text text text text text text
        \section{Text text text}
            Text text
            \begin{enumerate}
                \item text 
                \begin{itemize}
                    \item text 
                    \item text 
                \end{itemize}
                \item text 
                \item text 
            \end{enumerate}
    \end{originalemail}
\end{document}

The new enviroments should allow me to use \begin{response}my response\end{response} anywhere inside the orininalemail and achieve the desired layout break.

As pointed out by @Vinccool96, in order to break out out nested originalemails it might be neccessary to pass an argument \begin{response}[2] to indicate the number of levels it should break out of. But nesting is only a bonus.

sheß
  • 3,622
  • 1
    Maybe related: https://tex.stackexchange.com/questions/68251/how-to-format-an-email-conversation – Steven B. Segletes Mar 20 '19 at 16:26
  • 2
    Not a solution, but if you are looking into this I would try to use tcolorbox instead of mdframed. tcolorbox is actively maintained and has an awesome manual while mdframed development seems to have stalled a while ago. – moewe Mar 20 '19 at 16:31
  • 2
    @sheß Could you clarify? One can indeed put enumerations inside the \embed. So are you looking to suspend the embed to provide a response and then continue the enumeration where it left off? – Steven B. Segletes Mar 20 '19 at 16:37
  • That is exactly what I want to do. – sheß Mar 21 '19 at 00:10
  • 1
    What if you just draw a line on the left margin (using a suitably prepared background image perhaps), and use your defined \response environment to draw a box with a white border on the left to cover up the pre-drawn line? – Willie Wong Mar 21 '19 at 13:31
  • That could work. I just think it's maybe not the most elegant solution of all. I will consider it if there's no other solution suggested – sheß Mar 21 '19 at 20:26
  • 3
    Isn't this an instance of a XY problem, where your actual ultimate objective is to nicely add your comment on a document submitted to you? If so, you might want to have a look at the todonotes package. (I.e. this package doesn't do the "bar in the left margin" thing, but might be of greater help for what you ultimately want to do. See notably inline notes.) See also changes package. – ebosi Mar 28 '19 at 11:13
  • 2
    Actually, I think that what you are looking for is the changebar package. – ebosi Mar 28 '19 at 11:19
  • Thanks for those useful suggestions. The actual purpose is to typeset responses to referees in a 20 page referee report. Indeed the changes and changebar and tonotes packages are useful, but they all do not fully achieve what I am trying to achieve (e.g. the change(bar|s) package does not keep the orignal numberin in the enumerates, which is important for me) – sheß Mar 28 '19 at 12:11
  • @sheß, I don't think it's possible. How could the environment response know how many email depth it should get out of? You would need an entire package. – Vinccool96 Mar 31 '19 at 16:44
  • That's a valid point. Though this could be solved by passing the depth as an argument. Either way. The nesting would only be a bonus – sheß Mar 31 '19 at 16:51
  • Even then, how would it know the depth in itemize and enumerate. It could even be in an itemize, which is in an enumerate, which is an itemize, which is in an enumerate, which is an itemize. How would it know? – Vinccool96 Mar 31 '19 at 16:58
  • There are ways. See my own answer here and for example \@currenvir (https://tex.stackexchange.com/questions/18652/how-can-i-check-if-the-current-code-is-inside-a-certain-environment). – sheß Mar 31 '19 at 17:17
  • An alternative would be to break out of the environment only visually. Like what @Wollie Wong suggested. – sheß Mar 31 '19 at 17:24
  • 1
    You should add an example of the intended input. Currently I do find it quite unclear where it is allowed to add tex code and where not. – Ulrike Fischer Apr 02 '19 at 12:29
  • Once in a while I have to put an email correspondency into a LaTeX document. So the »input« are the usual parts of emails: text, bulletpoint lists, numbered lists and most importantly, quotes of what was said earlier in the correspondency.\ It would help a lot if you described what you would like to do. In my case I intended to display an email conversations, which I took from the email software (kmail, outlook, thunderbird, whatever) and »translate« it into my LaTeX file. There is no way to render HTML inside a *.tex file and taking the screenshot wasn't possible as well, because too long. – Keks Dose Apr 02 '19 at 13:05
  • Thanks for pointing out this shortcoming, Ulrike, I hope if fixed it. @KeksDose, I will clarify in my post that what I call "orignal email" is already in TeX. This question is in no way about how to put an email from an email sorftware/HTML into TeX – sheß Apr 02 '19 at 13:12

3 Answers3

7
\documentclass{article}

\usepackage[most]{tcolorbox}
\tcbuselibrary{breakable}
\tcbuselibrary{skins}

\newtcolorbox{emailstart}[3][]{%
    standard jigsaw,
    opacityframe=0,
    opacityback=0,
    colback=transparent,
    grow to left by=-1.5em,
    boxrule=0pt,
    boxsep=0pt,
    breakable,
    enhanced jigsaw,
    title={On #2, #3 wrote\par},
    coltitle={black},
    attach title to upper={},
    borderline west={4pt}{0pt}{black},
    overlay unbroken and first={\draw[shorten >=1.4pt, shorten <=1.4pt] ([yshift=-1.5em]frame.north west) -- ([yshift=-1.5em]frame.north east);},
    #1,
}

\newtcolorbox{emailresume}[1][]{%
    standard jigsaw,
    opacityframe=0,
    opacityback=0,
    colback=transparent,
    grow to left by=-1.5em,
    boxrule=0pt,
    boxsep=0pt,
    breakable,
    enhanced jigsaw,
    borderline west={4pt}{0pt}{black},
    #1,
}

\newcounter{enumicounter} %counter that will save the enumeration counter

\begin{document}
    \begin{emailstart}{2019}{Einstein}
        \begin{emailstart}{2018}{Sheß}
            Text Text Text Text

            Text Text Text Text Text Text Text
        \end{emailstart}
        Here I am putting my answer text 
    \end{emailstart}
    Oh, now I see your point


    \begin{emailresume}
        \begin{emailresume}
            \section{A section}
            Some content a list
            \begin{enumerate}
                \item One
                \setcounter{enumicounter}{\value{enumi}} % save the enumeration counter
            \end{enumerate}
        \end{emailresume}
        Here even more, there's no indentation, because you closed the enumaration and the email
    \end{emailresume}
    This is an answer to your answer
    \begin{emailresume}
        \begin{emailresume}
            \begin{enumerate}
                \setcounter{enumi}{\value{enumicounter}} % continue the enumeration
                \item Two
                \setcounter{enumicounter}{\value{enumi}} %save the enumeration counter
            \end{enumerate}
        \end{emailresume}
        Answer
        \begin{emailresume}
            \begin{enumerate}
                \setcounter{enumi}{\value{enumicounter}} % continue the enumeration
                \item Three
                \item Four
                \setcounter{enumicounter}{\value{enumi}} %save the enumeration counter
            \end{enumerate}
            \section{another section}
            More Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
            \subsection{a subsection}
            More Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
        \end{emailresume}
        More
        \begin{emailresume}
            \subsection{another subsection}
            More Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
        \end{emailresume}
        More
        \begin{emailresume}
            Bye,

            Sheß
        \end{emailresume}
        Bye,

        Einstein
    \end{emailresume}
    Bye
\end{document}

sheß
  • 3,622
4

All I did here is to slightly modify Gonzalo Medina's nice answer. One can of course tune it a bit more. (I also understand that there is nothing squiggly here, I was too lazy to rename the macros.)

\documentclass{article}
\usepackage{refcount}
\usepackage{tikz}
\usetikzlibrary{calc,tikzmark}
\usepackage{lipsum}

\newcounter{tmp}
% \newcommand\tikzmark[1]{%
%   \tikz[overlay,remember picture] \node (#1) {};}

\newcommand\Startsquiggly{%
  \stepcounter{tmp}%
  \tikzmarknode{a}{\strut}\label{a\thetmp}%
  \ifnum\getpagerefnumber{a\thetmp}=\getpagerefnumber{b\thetmp} \else
  \begin{tikzpicture}[overlay, remember picture]
    \draw [ultra thick,gray]
      let \p1 = (a.south), \p2 = (b), \p3 = (current page.center) in
      ( $ (\x3,\y1) + (-.55\textwidth,0) $ ) --  ( $ (\x3,\y3) + (-0.55\textwidth,-0.5\textheight) $ );
  \end{tikzpicture}%
  \fi%
}

\newcommand\Endsquiggly{%
\tikzmarknode{b}{\strut}\label{b\thetmp}
  \ifnum\getpagerefnumber{a\thetmp}=\getpagerefnumber{b\thetmp}
  \begin{tikzpicture}[overlay, remember picture]
    \draw [ultra thick,gray]
      let \p1 = (a.south), \p2 = (b), \p3 = (current page.center) in
      ( $ (\x3,\y1) + (-.55\textwidth,1em) $ ) --  ( $ (\x3,\y2) + (-.55\textwidth,1em) $ );
  \end{tikzpicture}%
  \else
  \begin{tikzpicture}[overlay, remember picture]
    \draw [ultra thick,gray]
      let \p1 = (a.south), \p2 = (b), \p3 = (current page.center) in
      ( $ (\x3,\y3) + (-.55\textwidth,.5\textheight) $ ) -- ( $ (\x3,\y2) + (-.55\textwidth,1em) $ );
  \end{tikzpicture}%
  \fi
}

\newcommand\Squ[1]{\Startsquiggly#1\Endsquiggly}
\AtBeginDocument{\Startsquiggly}
\AtEndDocument{\par\Endsquiggly}
\newcommand{\response}[1]{\par\Endsquiggly#1\par\Startsquiggly}
\begin{document}
Some text, with pictures, lists, sections
\begin{enumerate}
\item Some text, with pictures, lists, sections
\response{answer1}
\item Some text, with pictures, lists, sections
\response{answer2}
\end{enumerate}
Some text, with pictures, lists, sections
\response{this is my answer}
Some text, with pictures, lists, sections
\section{section}
\subsection{subsection1}
Some text, with pictures, lists, sections
\subsection{subsection2}
Some text, with pictures, lists, sections
\subsection{subsection3}
Some text, with pictures, lists, sections
\response{I also have an answer here}
More text
\end{document}

enter image description here

  • 1
    @sheß Absolutely. Please note that there are also many posts linked to Gonzalo's nice answer, some of which may become relevant if you have something like \raggedbottom and so on. (I really just very quickly wrote that before I went cycling, there are many things one may want to add/consider/improve.) –  Mar 23 '19 at 23:14
  • @sheß This point I do not understand. There are two things: (1) Draw the interrupted line on the margin and (2) add indentation. I didn't know you want to have (2) (which is clearer after the edit). So you wish to indent sections and so on? (In this case the question is very different from what I originally thought it is.) Or only texts as in the email conversation? –  Mar 28 '19 at 17:30
  • 1
    Whoever downvoted this answer may want to take into account that this was an attempt to answer the question before the edit(s). –  Mar 30 '19 at 18:29
  • Sorry, I missed the grace period and the bounty was out awarded – sheß Mar 31 '19 at 10:03
3

A solution I came up with, but I'm still fairly unhappy with the amount of things that are hard-coded. E.g.

  • it requires that I change all \begin{enumerate}[some arguments] to \begin{enumerate}{some arguments}
  • works only for up to a fixed number of nested enumerates and
  • probably fails if the original document uses an itemize or something else.
  • it cannot be nested

So, eventhough I'm posting this as an aswer to my own post, I do not consider this complete and would be happy for anyone who adapts it to be more general

\documentclass{article}

\newcounter{breakdepth}
\usepackage{enumitem}
\usepackage{letltxmacro}

%redefine enumerates so that they are automatically resumable
\LetLtxMacro\ooenumerate\enumerate
\LetLtxMacro\endooenumerate\endenumerate
\makeatletter
    \renewenvironment{enumerate}[2][0]{%
        \ifx0#1%i.e. this is not a resume, but a new list, so start naming it.
            \ooenumerate[series=level\the\@enumdepth,#2]%
        \else
            \ooenumerate[#2]%
        \fi
    }{
         \endooenumerate%
    }
%define the command that breaks the \report environment, closes all enumerates, but resumes them afterwards
\newcommand{\response}[1]{%
\setcounter{breakdepth}{\the\@enumdepth}%
\ifnum\value{breakdepth}>3  \end{enumerate} \fi%
\ifnum\value{breakdepth}>2  \end{enumerate} \fi%
\ifnum\value{breakdepth}>1  \end{enumerate} \fi%
\ifnum\value{breakdepth}>0  \end{enumerate} \fi%
\end{report}%
#1%
\begin{report}%
\ifnum\value{breakdepth}>0  \begin{enumerate}[]{resume*=level\the\@enumdepth}\item[]\fi%
\ifnum\value{breakdepth}>1  \begin{enumerate}[]{resume*=level\the\@enumdepth}\item[]\fi%
\ifnum\value{breakdepth}>2  \begin{enumerate}[]{resume*=level\the\@enumdepth}\item[]\fi%
\ifnum\value{breakdepth}>3  \begin{enumerate}[]{resume*=level\the\@enumdepth}\item[]\fi%
}
\makeatother
%define the environment that has a slight indentation and a vertical line for the original text
\usepackage{mdframed}
\newenvironment{report}{\begin{mdframed}[linewidth=1pt,topline=false,rightline=false,bottomline=false,linecolor=black,innerleftmargin =0cm, leftmargin=2pt,innerrightmargin=1pt]}{\end{mdframed}}

\begin{document}
    \begin{report}
    \section{first section}
    \begin{enumerate}{label=\roman*.}
    \item ione 
    \begin{enumerate}{}
    \item aone
    %%%%%%%%%
    \response{test} 
    %%%%%%%%%
    \item atwo
    \end{enumerate}
    \item itwo
    \response{test} 
    \end{enumerate}
    \section{a section}
    Some text that is not inside a list
    \response{test} 
    more text
    \end{report}
\end{document}

enter image description here

sheß
  • 3,622