1

I have been using the following trick to obtain the contents of a paragraph. It works most of the time, but not on macros like \lipsum or \end{document} or \end{minipage} which expand the \par internally. Is there a way to fix this?

\documentclass{article}
\usepackage{lipsum}

\newcounter{count}

\def\mypar#1\par{\stepcounter{count}\thecount(#1)\addtocounter{count}{-1}\par}


\begin{document}
\everypar{\mypar}
This is a test.

\lipsum[1]
This is a new paragraph.

\end{document}

results

This also demonstrats that another \mypar is executed when \lipsum expands inside \mypar (recursively).


If I convert my application to a macro instead of an environment, the inability to detect the end of the environment is no longer an issue. In other words, I could just live with it.

I believe I can detect the presence of a \par inside a macro by expanding it in a \savebox and using \everypar to increment a counter. If I store the input data as a token list, one can add tokens without expanding them. So it is just a matter of adding tokens one at a time until one expands a \par.

Of course, this only works if the macro has a single \par at the end. Macros like \item which have a \par at the beginning cannot be used with \parshape (unless modified).

6
  • Perhaps \lipsum*[1]? – egreg Feb 29 '16 at 17:29
  • Is this question specific to lipsum? Or just a general question about some areas where your \mypar doesn't work as expected? – Werner Feb 29 '16 at 17:36
  • @Werner - It also doesn't work on \end{document}, so it's about \mypar. – John Kormylo Feb 29 '16 at 18:03
  • @JohnKormylo: For that you might get away with \AtEndDocument{\par}. – Werner Feb 29 '16 at 18:40
  • Perhaps you're interested in the shapepar package. – egreg Mar 1 '16 at 0:00
2

You want to use \lipsum* that does not issue \par.

\documentclass{article}
\usepackage{lipsum}

\newcounter{count}

\def\mypar#1\par{\stepcounter{count}\thecount(#1\unskip\unskip)\addtocounter{count}{-1}\par}


\begin{document}
\everypar{\mypar}

This is a test.

\lipsum*[1]

This is a new paragraph.

\end{document}

enter image description here

If you were hoping to make \mypar into seeing the final \par in \lipsum, you're out of luck.

0

Instead of trying to parse the source, I decided to put each paragraph into a separate box. Also, instead of the whole document I reduced the problem to the contents of an environment (\BODY}.

By putting a \pagebreak at the end of each paragraph I can force \vsplit to pull off 1 paragraph each time and store the heights. I repeat the process using normal penalties and these heights.

\documentclass{article}
\usepackage{environ}
\usepackage{lipsum}

\newsavebox{\mybox}
\newcounter{total}
\newcounter{count}
\renewcommand{\thecount}{\Roman{count}}

\NewEnviron{test}{%
  \let\oldpar=\par
  \def\par{\oldpar\pagebreak}%
  \everypar{\stepcounter{total}}%
  \setbox\mybox=\vbox{\BODY}%
  \let\par=\oldpar
  \everypar{\relax}
  \loop\ifnum\value{count}<\value{total}\relax
    \stepcounter{count}%
    \dimen0=\ht\mybox
    \setbox0=\vsplit\mybox to \dimen0
    \advance\dimen0 by -\ht\mybox
    \expandafter\xdef\csname testht\thecount\endcsname{\the\dimen0}%
  \repeat
  \global\setbox\mybox=\vbox{\BODY}%
}

\begin{document}
\parindent=0pt
\begin{test}
This is a test.

\lipsum[1]
This is a new paragraph.
\end{test}
\setcounter{count}{0}%
\loop\ifnum\value{count}<\value{total}\relax
  \stepcounter{count}%
  \arabic{count}\par
  \dimen0=\csname testht\thecount\endcsname\relax
  \setbox0=\vsplit\mybox to \dimen0
  \usebox0
\repeat
\end{document}

demo

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.