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, 2016 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, 2016 at 17:36
  • @Werner - It also doesn't work on \end{document}, so it's about \mypar. Feb 29, 2016 at 18:03
  • @JohnKormylo: For that you might get away with \AtEndDocument{\par}.
    – Werner
    Feb 29, 2016 at 18:40
  • Perhaps you're interested in the shapepar package.
    – egreg
    Mar 1, 2016 at 0:00

2 Answers 2

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .