[Tex/LaTex] How to define a parshape command with LaTeX

indentationloopsmacrosparagraphs

I want to typeset a book with some \parshape command, for example:

\documentclass{article}
\usepackage{lipsum}

\begin{document}
\parshape=4
0.2\textwidth 0.8\textwidth
0.2\textwidth 0.8\textwidth
0.2\textwidth 0.8\textwidth
0pt \textwidth
\lipsum
\end{document}

But since the lines and width may changes frequently, so I want to define a command like this

\newcounter{foo}
\setcounter{foo}{0}
\newcommand{\MyParShape}[3]
{
\parshape=#1
\loop
#2\textwidth #3\textwidth 
\addtocounter{foo}{1}
\if\thefoo<#1-1\repeat
0pt \textwidth
}

So I can call it like

\MyParShape{5}{0.5}{0.5}

or

\MyParShape{10}{0.8}{0.2}

But this does not work, I'm not an expert of TeX primitives, can somebody help?

Best Answer

As Harald says, the key here is that you need everything expanded. You can do that in a temporary variable, as he shows. Alternatively, you can use something like an expandable 'repeat n times' approach. Here, I'm assuming e-TeX is available

\documentclass{article}
\usepackage{lipsum}
\makeatletter
\newcommand*\replicate[1]{%
  \expandafter\replicate@aux\romannumeral\number\numexpr #1\relax000Q{}
}
\newcommand*\replicate@aux[1]{\csname replicate@aux@#1\endcsname}
\newcommand\replicate@aux@m{}
\long\def\replicate@aux@m#1Q#2#3{\replicate@aux#1Q{#2#3}{#3}}
\newcommand\replicate@aux@Q[2]{#1}
\DeclareRobustCommand*\MyParShape[3]{%
    \parshape = #1
      \replicate{#1 -1}{#2\textwidth #3\textwidth}%
      0pt\textwidth
}
\newcommand*\my@parshape{}
\makeatother
\begin{document}
\MyParShape{3}{0.6}{0.4}
\lipsum
\end{document}
Related Question