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.

This question led to a new package:
nowidow

I'm trying to define a dynamic \begingroup command to get rid of widows:

\usepackage{pgffor}
\newcommand{\nowidow}[1][2]{%
 \begingroup\widowpenalties #1 \foreach \n in {2,...,#1}{10000 } 0 
 \par\endgroup
}

This fails complaining that \begingroup requires a number and I'm guessing this has to do with expansion.

Here is a MWE:

\documentclass{scrbook}

\usepackage{lipsum}

\usepackage{pgffor}
\newcommand{\nowidow}[1][2]{%
 \begingroup\widowpenalties #1 \foreach \n in {2,...,#1}{10000 } 0
 \par\endgroup
}

\begin{document}

\lipsum
\nowidow

\end{document}

How can I get this to work? Would it be easier (although less portable) to do it in Lua?

share|improve this question

2 Answers 2

up vote 7 down vote accepted

\begingroup doesn't require a number. It is \widowpenalties which looks for one and \foreach isn't expandable, so it doesn't produce a number directly and therefore you get an error. Most likely \begingroup is just shown somewhere in the error message because it was the last correctly read token before the error.

In order to fix this you need to use an expandable loop, e.g. using e-TeX's \numexpr:

\documentclass{scrbook}

\usepackage{lipsum}

\def\nowidowX#1{%
    \ifnum#1<\nowidowmax
        10000
        \expandafter\nowidowX\expandafter{\the\numexpr(#1)+1\expandafter\relax\expandafter}%
    \fi
}

\newcommand{\nowidow}[1][2]{%
    \begingroup
    \mathchardef\nowidowmax#1\relax
    \widowpenalties #1 \nowidowX{1} 0\par
    \endgroup
}

\begin{document}

\lipsum
\nowidow

\end{document}
share|improve this answer
    
How can I use an expandable loop? –  ℝaphink Aug 22 '11 at 11:43
    
I added some code now. –  Martin Scharrer Aug 22 '11 at 11:51
    
Thanks, I'll test :-) –  ℝaphink Aug 22 '11 at 11:52
    
Thank you very much. –  ℝaphink Aug 22 '11 at 11:56
    
@Martin: you save a few \expandafter if you make the argument of \nowidowX delimited (e.g., \def\nowidowX#1;{\ifnum#1<\nowidowmax10000 \expandafter\nowidowX\the\numexpr#1+1\expandafter;\fi}). –  Bruno Le Floch Aug 22 '11 at 16:23

Martin has already pointed out that \foreach is non-expandable. I'd add that the expl3 bundle provides such expandable tools. For instance,

\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand {\nowidow} { O{2} }
  {
     \begingroup
     \widowpenalties #1~ \prg_replicate:nn {#1-1} {10000~} 0~
     \par\endgroup
  }
\ExplSyntaxOff

(I'm just using xparse for \NewDocumentCommand. You could simply stick with \newcommand if you prefer.)

share|improve this answer
    
This is latex3, right? –  ℝaphink Aug 22 '11 at 16:56
1  
@Raphink, yes. I should add that spaces are ignored between \ExplSyntaxOn and Off and the odd-looking ~ are spaces. Basically, I replicate 10000~ a given number of times. Also, it seems that the last 0 penalty is not really needed, is it? You could put \widowpenalties \int_eval:n{#1-1}~ \prg_replicate:nn... and remove that 0~. –  Bruno Le Floch Aug 22 '11 at 18:03

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.