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'm not a fan of Microsoft Word, but I have missed the ability to comment on papers that I'm working on with friends using comments that appear as little bubbles in the margins. I've managed to create something that's pretty close to what I'm looking for, but there are some bugs that I haven't been able to resolve.

Here's a (hopefully) minimal working example document using the code that I've created:

\documentclass[draft]{article}

% For conditional control flow in draft mode
\usepackage{ifdraft}

% For larger margins when in draft mode
\ifdraft{\usepackage[rmargin=3in,marginparwidth=2.75in]{geometry}}{}

% For todo notes in the margins
\usepackage{todonotes}

% For highlighting in MS Word-like comments
\usepackage{soul,color}

% This is needed to ensure the line spacing of the margin notes is correct.
\usepackage{setspace}

% For conditional use of the \comment command based on the options provided.
\usepackage{ifthen}

% BEGIN HIGHLIGHTING: The following code provides a highlighting command, which is 
% used in my custom commenting system below.  If you want more information about 
% this code, see the following URL:
%   http://tex.stackexchange.com/questions/5959/cool-text-highlighting-in-latex
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.pathmorphing}

\makeatletter

\newcommand{\defhighlighter}[3][]{%
  \tikzset{every highlighter/.style={color=#2, fill opacity=#3, #1}}%
}

\defhighlighter{yellow}{.5}

\newcommand{\highlight@DoHighlight}{
  \fill [ decoration = {random steps, amplitude=1pt, segment length=15pt}
        , outer sep = -15pt, inner sep = 0pt, decorate
        , every highlighter, this highlighter ]
        ($(begin highlight)+(0,8pt)$) rectangle ($(end highlight)+(0,-3pt)$) ;
}

\newcommand{\highlight@BeginHighlight}{
  \coordinate (begin highlight) at (0,0) ;
}

\newcommand{\highlight@EndHighlight}{
  \coordinate (end highlight) at (0,0) ;
}

\newdimen\highlight@previous
\newdimen\highlight@current

\DeclareRobustCommand*\highlight[1][]{%
  \tikzset{this highlighter/.style={#1}}%
  \SOUL@setup
  %
  \def\SOUL@preamble{%
    \begin{tikzpicture}[overlay, remember picture]
      \highlight@BeginHighlight
      \highlight@EndHighlight
    \end{tikzpicture}%
  }%
  %
  \def\SOUL@postamble{%
    \begin{tikzpicture}[overlay, remember picture]
      \highlight@EndHighlight
      \highlight@DoHighlight
    \end{tikzpicture}%
  }%
  %
  \def\SOUL@everyhyphen{%
    \discretionary{%
      \SOUL@setkern\SOUL@hyphkern
      \SOUL@sethyphenchar
      \tikz[overlay, remember picture] \highlight@EndHighlight ;%
    }{%
    }{%
      \SOUL@setkern\SOUL@charkern
    }%
  }%
  %
  \def\SOUL@everyexhyphen##1{%
    \SOUL@setkern\SOUL@hyphkern
    \hbox{##1}%
    \discretionary{%
      \tikz[overlay, remember picture] \highlight@EndHighlight ;%
    }{%
    }{%
      \SOUL@setkern\SOUL@charkern
    }%
  }%
  %
  \def\SOUL@everysyllable{%
    \begin{tikzpicture}[overlay, remember picture]
      \path let \p0 = (begin highlight), \p1 = (0,0) in \pgfextra
        \global\highlight@previous=\y0
        \global\highlight@current =\y1
      \endpgfextra (0,0) ;
      \ifdim\highlight@current < \highlight@previous
        \highlight@DoHighlight
        \highlight@BeginHighlight
      \fi
    \end{tikzpicture}%
    \the\SOUL@syllable
    \tikz[overlay, remember picture] \highlight@EndHighlight ;%
  }%
  \SOUL@
}
\makeatother
% END HIGHLIGHTING

% BEGIN MS WORD-STYLE COMMENTS
% This is the main function for providing MS Word-style comments.  There are two 
% ways to use it.  First, you can do the following: 
% 
%     \comment[akm]{This is comment text that will appear in the margin.}{This is 
%         body text that will appear in the main output.}
%
% Second, you can do the following, which will appear only as a note in the margin:
%
%     \comment[akm]{Here's a comment that won't highlight any text.  However, it 
%         should still point to the place in the text where it appears.}
% 
% Third, if you're Aaron, then you can leave out the initials.  Obviously, anyone 
% else reading this should consider altering the command for their own default 
% initials.
%
%     \comment{Here's a margin note using the default initials.}
\newcounter{akmctr}
\newcommand{\comment}[3][akm]{%
    % initials of the author (optional) + note in the margin
    \ifdraft{\refstepcounter{akmctr}%
    {%
        \setstretch{1.0}% line spacing
        \todo[color={red!100!green!33},size=\small,fancyline]{%
            \textbf{Comment [\uppercase{#1} \arabic{akmctr}]:}~#2}
        \ifthenelse{\equal{#3}{}}{}{\highlight[red!100!green!33]{#3}}%
        }%
    }{}%
}
% END MS WORD-STYLE COMMENTS

\begin{document}

\section{Introduction} % (fold)
\label{sec:introduction}
Let's start testing the comments.  Here's a comment with the default initials and no highlighted text.

Alice was beginning to get very \comment{These sample paragraphs are from the first chapter of Lewis Carroll's \emph{Alice in Wonderland}.  Please note that the original text shouldn't have weird spacing at the place where the comment was inserted, but it does.}tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, `and what is the use of a book,' thought Alice `without pictures or conversation?'

here's a comment that uses non-default initials and still doesn't highlight text.

So she was \comment[pno]{This comment should have a different counter.  Is it possible to setup counters based on the initials passed?}considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.

Here's a comment that uses the default initials and highlights some text.

There was nothing so VERY remarkable in that; nor did Alice think it so VERY much out of the way to hear the Rabbit say to itself, `Oh dear! Oh dear! I shall be late!' (when she thought it over afterwards, \comment{This should also have no strange artifacts at the place where it was inserted.  It should also have a fancyline pointing to the highlighted portion of the text.}{it occurred to her that she ought to have wondered at this}, but at the time it all seemed quite natural); but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT-POCKET, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fortunately was just in time to see it pop down a large rabbit-hole under the hedge.

In another moment down went Alice after it, \comment[pno]{Basically, this is the same as before, but it should be for a different author, preferably with a different counter and a different color text.}{never once considering how in the world she was to get out again}.

It's probably also a good idea to test these things in lists.  Let's try making a few comments in a list environment.

\begin{enumerate}
    \item This is the first item in the list.
    \item This is the second item in the list.
    \item This is the \comment{This should be the third item in the list!}{fourth} item in the list.
    \item This is the fourth item in the list.
    \item This is the \comment{Here's a comment in a list with no highlighting.}final item in the list.
\end{enumerate}
% section introduction (end)

Obviously, there are many other environments that we should test these things in, but this is already going to be a huge post.  I'll stop here.

\end{document}

In particular, the section of code that creates the new command for commenting is this one:

% BEGIN MS WORD-STYLE COMMENTS
% This is the main function for providing MS Word-style comments.  There are two 
% ways to use it.  First, you can do the following: 
% 
%     \comment[akm]{This is comment text that will appear in the margin.}{This is 
%         body text that will appear in the main output.}
%
% Second, you can do the following, which will appear only as a note in the margin:
%
%     \comment[akm]{Here's a comment that won't highlight any text.  However, it 
%         should still point to the place in the text where it appears.}
% 
% Third, if you're Aaron, then you can leave out the initials.  Obviously, anyone 
% else reading this should consider altering the command for their own default 
% initials.
%
%     \comment{Here's a margin note using the default initials.}
\newcounter{akmctr}
\newcommand{\comment}[3][akm]{%
    % initials of the author (optional) + note in the margin
    \ifdraft{\refstepcounter{akmctr}%
    {%
        \setstretch{1.0}% line spacing
        \todo[color={red!100!green!33},size=\small,fancyline]{%
            \textbf{Comment [\uppercase{#1} \arabic{akmctr}]:}~#2}
        \ifthenelse{\equal{#3}{}}{}{\highlight[red!100!green!33]{#3}}%
        }%
    }{}%
}
% END MS WORD-STYLE COMMENTS

There are a couple of big issues and a couple of minor issues. Here's a list of things I haven't been able to figure out:

  1. [ANSWERED - See Yiannis's answer] Why are there extraneous spaces added to the body text when a comment is added?
  2. Why do some comments that aren't using text highlighting creating a little triangle of highlighting?
  3. Is there any way to get a separate counter for each author?
  4. Is there any way to get a separate color for both the comment bubbles and the highlighting for each author?

The first two problems are much more important to me than the other two.

I should also add that I don't really need the other change tracking features in MS Word. I use a source code control system (git) that meets all my needs for that. Also, I have read some other, very helpful posts on collaborating with non-LaTeX users, including What is a good strategy for obtaining comments on a LaTeX document from non-LaTeX using collaborators? and Workflow for reviewing PDFs Generated from TeX. Both are great, but I need comment bubbles to appear in PDFs because my research group regularly reading early drafts on paper that need some additional explanations.

share|improve this question
2  
Why on earth don't you use the todonotes-package? Have a look at the docu: texdoc todonotes on the commandline. –  Keks Dose Feb 8 '12 at 16:03
    
I suppose @aaron-massey wants to design his own style. –  azetina Feb 8 '12 at 16:33
    
If you look carefully at my initial post, you'll see that I'm actually already using that as a part of my solution. Unfortunately, it doesn't do some things that I really need. For example, it doesn't highlight excerpts from the body text when inserting the comment. It also doesn't have the ability to create per-author comment colors and counting. –  Aaron Massey Feb 8 '12 at 19:01
add comment

2 Answers

up vote 5 down vote accepted

I think it would have been better to focus your MWE and your questions in separate questions to enable both you and the persons answering to provide focus comments.

The answer to your first question is that you need to add the (%) to ensure that no redundant empty spaces occur.

This corrects the first problem.

\newcommand{\comment}[3][akm]{%
    % initials of the author (optional) + note in the margin
    \ifdraft{\refstepcounter{akmctr}%
    {%
        \setstretch{1.0}% line spacing
        \todo[color={red!100!green!33},size=\small,fancyline]{%
            \textbf{Comment [\uppercase{#1} \arabic{akmctr}]:}~#2}
        \ifthenelse{\equal{#3}{}}{}{\highlight[red!100!green!33]{#3}}%
        }%
    }{}%
}

See also this http://tex.stackexchange.com/a/19927/963.

I must also congratulate you on what looks like a very nicely set of to-do notes. I will come back and add the rest of the answers unless you want to split them as per my suggestion and please reduce your minimal by 80%.

How do we add counters for more users? Firstly, we need to define a method to add a user, as well as decide on the type of datastructure to hold the user names.

A comma delimited list would be a suitable data structure and one which we can manipulate via LaTeX kernel commands or the etoolbox package or even write our own commands to do so. This list is simply defined in a macro:

  \def\users{yiannis,egreg,martin}

To add more users, we can just manually enter another name or create another command for it, opting for the latter we use the LaTeX kernel \g@addto@macro command to do so.

 \def\adduser#1{\g@addto@macro{\users}{,#1}}

To add a user use \adduser{Mary} and if you want to print the list of users, just expand the list by typing \users.

The next step is to create the counters automatically, since we have a list we will use a for-loop, within a macro we call \counterfactory.

\def\counterfactory#1{\@for\next:=#1\do{%
\ifcsname c@\next\endcsname%
 \else
   \newcounter{\next}%
   \setcounter\next{0}
\fi
}}
\AtBeginDocument{\counterfactory\users}

When LaTeX allocates a counter for example foo the counter it creates is c@counter. The \ifcsname part of the code in the for-loop just checks if the counter was created earlier and if not then goes on and creates the counter and sets it to zero.

Including the above code fragments in your preamble and adjusting the relevant parts of your \comment, macro such as \ifdraft{\refstepcounter{akmctr} to \ifdraft{\refstepcounter{#1} etc would do the trick. Here is a minimal to see the counter part operating on its own.

\documentclass{article}
\makeatletter
\def\users{egreg,martin}
\def\adduser#1{\g@addto@macro{\users}{,#1}}
\def\counterfactory#1{\@for\next:=#1\do{%
\ifcsname c@\next\endcsname%
 \else
   \newcounter{\next}%
   \setcounter\next{0}
\fi
}}
% activate at beginning of document
\AtBeginDocument{\counterfactory\users}
% add a few users   
\adduser{aaron}
\adduser{yiannis}
\adduser{george}
\begin{document}
This documented commented by \users. \\
\stepcounter{yiannis}
\theyiannis\\% 1
\theaaron\\ %0
\setcounter{aaron}{100}\\ %100
\theaaron\\
\end{document}

One could use a similar technique to add a specific user color. We can modify the \adduser macro to take two parameters, the first would be the user name and the second to be the color.

 \def\adduser#1#2{%
   \g@addto@macro{\users}{,#1}%
   \expandafter\def\csname #1@color\endcsname{#2}
  }

Here is another MWE to test the changes.

\documentclass{article}
\usepackage{xcolor}
\makeatletter
\def\users{egreg,martin}
\def\adduser#1#2{%
   \g@addto@macro{\users}{,#1}%adds user to list
   \expandafter\def\csname #1@color\endcsname{#2} %holds the color name in `\name@color`
  }
\def\counterfactory#1{\@for\next:=#1\do{%
\ifcsname c@\next\endcsname%
 \else
   \newcounter\next%
   \setcounter\next{0}
\fi
}}
\AtBeginDocument{\counterfactory\users}

\adduser{aaron}{red}
\adduser{yiannis}{blue}
\adduser{george}{orange}
\begin{document}
This documented commented by \users. \\
\stepcounter{yiannis}
\theyiannis\\% 1
\theaaron\\ %0
\setcounter{aaron}{100}\\ %100
\theaaron\\

\color{\yiannis@color} This text is printed in blue, 
 whereas Aaron's color is printed in \color{\aaron@color} red.
\end{document}

So where you say \highlight[red!100!green!33], you can replace with the user's color command. This would hopefully help you iterate your code and get what you want, as well as understand a bit better what went wrong.

share|improve this answer
    
Thanks very much for the help! That's a great solution to one of the biggest problems I've been having. I have a couple of potentially idiotic follow up questions: (1) What do you mean by "focus on your MWE"? (2) What do you mean by "reduce your minimal by 80%"? and (3) Do you think I should turn question #2 from my original post and questions #3 and #4 from my original post into separate questions? Thanks again! –  Aaron Massey Feb 8 '12 at 19:20
    
@AaronMassey The counter part of your question is not too long an answer and will post one in the morning is a bit late here:) (2) & (4) are related and you should post separately. A MWE is a Minimal Working Example, you should remove any code not related to the problem, such as minitoc, date, author etc and some comments etc. It makes it easier to work, if one focuses on the problem areas. –  Yiannis Lazarides Feb 8 '12 at 19:59
    
Ok, I've updated the question to minimize some of the example. I've also added a code section to focus on the new command I've created that is the source of the problem. Please let me know if there's anything else I can do to ask this question more clearly. (If nothing else, I hope it will improve my ability to ask reasonable questions about LaTeX in the future.) –  Aaron Massey Feb 8 '12 at 20:56
    
@YiannisLazarides You have \makeatletter in your code, but no \makeatother. I thought the two went together. Am I missing something? –  zun Feb 9 '12 at 9:49
    
@zun Sometimes in MWE I leave them out. They don't really go in pairs. The \makeother is only necessary if you want to revert its catcode. It is good practice though to pair them. I am very lazy when it comes to programming:) –  Yiannis Lazarides Feb 9 '12 at 10:33
show 1 more comment

The todonotes package sounds like it does what you want.

\usepackage{todonotes}
This is some text.\todo{This is a margin note with a line} 
Here's more text.\todo[noline]{Here's a note in the margin without a line pointing to the text}
share|improve this answer
    
If you look carefully at my initial post, you'll see that I'm actually already using that as a part of my solution. Unfortunately, it doesn't do some things that I really need. For example, it doesn't highlight excerpts from the body text when inserting the comment. –  Aaron Massey Feb 8 '12 at 18:58
add comment

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.