6

As stated elsewhere, it is usually quite recommended to use the starred \newcommand* instead of \newcommand since this helps finding missing }s by disallowing paragraphs in its argument. Every now and then, it is however desired to let such a command, e.g. \pdfmarkupcomment, act on (parts of) multiple paragraphs+. Is there any way to define an environment (say, pdfmarkedup, or can the environment share the command's name?) such that it automatically wraps each paragraph into the desired single-paragraph command? I.e.

\documentclass{article}
\usepackage{pdfcomment}
\newenvironment{pdfmarkedup}{%
    % insert magic here
}

\begin{document}
\begin{pdfmarkedup}[markup=Highlight]{no comment}
I'm a little paragraph short and stout.
Here is my last stop.

Here is my successor.
When I get all wrapped up,
Hear me shout!

Just write me down
and pour me out.

I'm a clever environment, yes it's true.
Here's an example of what I can do.
I can wrap my paragraphs each into a command.
Just put me around them and pour me out.
\end{pdfmarkedup}

\end{document}

should be equivalent to

\documentclass{article}
\usepackage{pdfcomment}
\begin{document}

\pdfmarkupcomment[markup=Highlight]{
I'm a little paragraph short and stout.
Here is my last stop.
}{No comment}

\pdfmarkupcomment[markup=Highlight]{
Here is my successor.
When I get all wrapped up,
Hear me shout!
}{No comment}

\pdfmarkupcomment[markup=Highlight]{
Just write me down
and pour me out.
}{No comment}

\pdfmarkupcomment[markup=Highlight]{
I'm a clever environment, yes it's true.
Here's an example of what I can do.
I can wrap my paragraphs each into a command.
Just put me around them and pour me out.
}{No comment}

\end{document}

+ In my example of \pdfmarkupcomment, it would be acceptable to have the same comment repeated over each paragraph.

  • yes sorry I just deleted that comment I misread the text, but still fixing the example so it loads all the right packages to run the example would be good – David Carlisle Dec 09 '15 at 07:51
  • @DavidCarlisle The second form shouldn't need more than a \documentclass{article}\usepackage{pdfcomment}\begin{document} and \end{document} wrapped around it, the first form obviously needs the sought environment's definition in addition. Probably some iteration over the paragraphs inside...But pdfmarkupcomment is really just an example, this might as well be any other star-defined macro, e.g. \newcommand*{\red}[#1]{{\color{red}#1}} – Tobias Kienzler Dec 09 '15 at 07:55
  • Strongly related, maybe even duplicate: https://tex.stackexchange.com/a/10526/430 – Tobias Kienzler Dec 09 '15 at 08:02
  • Don't add that to the comment add it to the example!! But as I said in my original comment, in general (as for the \color example) I can think of no cases where the complexity of doing this do not outweigh the benefits of the * form so simply using \newcommand would be preferable, But if you have and existing command that only works on text runs it could be done, probably although the details would depend on the command – David Carlisle Dec 09 '15 at 08:03
  • Are you perhaps looking for the environ package? – egreg Dec 09 '15 at 08:06
  • @DavidCarlisle Ok, added. In how far would the details depend on the command? Probably on the number of (optional) arguments, but aside from that? – Tobias Kienzler Dec 09 '15 at 08:12
  • @TobiasKienzler So you want \begin{pdfmarkedup}a\par b\par c\end{pdfmarkedup} to be equivalent to \pdfmarkupcomment{a}\par\pdfmarkupcomment{b}\par\pdfmarkupcomment{c}? – egreg Dec 09 '15 at 08:20
  • @egreg Precisely, I should edit the question a bit I guess – Tobias Kienzler Dec 09 '15 at 08:21
  • 1
    you could grab the whole environment with environ as in egreg's answer then what you do next depends on the command. In some cases it would be enough to define \par as \egroup\bgroup\foo so the command stops and starts at each blank line., Other commands really need explicit {} so there you would have to scan over the text splitting at \par and adding \foo{...} which is more general but more complicated, but as egreg's shown that I'll leave him to get the tick:-) – David Carlisle Dec 09 '15 at 09:00

1 Answers1

5

Use the power of expl3 together with environ:

\documentclass{article}
\usepackage{environ,xparse}

\usepackage{pdfcomment}

\ExplSyntaxOn
\NewEnviron{pdfmarkedup}[2][]
 {
  \kienzler_pdfmarkedup:Vnn \BODY { #1 } { #2 }
 }

\seq_new:N \l_kienzler_pdfmarkedup_pars_seq
\cs_new_protected:Nn \kienzler_pdfmarkedup:nnn
 {
  \seq_set_split:Nnn \l_kienzler_pdfmarkedup_pars_seq { \par } { #1 }
  \seq_map_inline:Nn \l_kienzler_pdfmarkedup_pars_seq
   {
    \tl_if_blank:nF { ##1 }
     {
      \pdfmarkupcomment[#2]{##1}{#3} \par
     }
   }
 }
\cs_generate_variant:Nn \kienzler_pdfmarkedup:nnn { V }
\ExplSyntaxOff


\begin{document}
\begin{pdfmarkedup}[markup=Highlight]{no comment}
I'm a little paragraph short and stout.
Here is my last stop.

Here is my successor.
When I get all wrapped up,
Hear me shout!

Just write me down
and pour me out.

I'm a clever environment, yes it's true.
Here's an example of what I can do.
I can wrap my paragraphs each into a command.
Just put me around them and pour me out.
\end{pdfmarkedup}

\end{document}

We absorb the environment's content with environ, then split it in a sequence at \par tokens. Each item of the sequence is passed to \pdfmarkupcomment.

egreg
  • 1,121,712
  • I frankly don't have the faintest clue how this works (yet), but it does, so here's the checkmark. I guess this can be generalized into a \createenvironmentfromcommand somehow... – Tobias Kienzler Dec 09 '15 at 13:36
  • @TobiasKienzler The main obstacle is the syntax of the original command. – egreg Dec 09 '15 at 15:39