Bucle hasta el final de una página.

Bucle hasta el final de una página.

Quiero llenar una página con una sola palabra o frase repetida una y otra vez. Luego imprimiré esta página. Por ejemplo,

\documentclass[12pt]{article}

\usepackage[margin=0.5in]{geometry}
\usepackage{pgffor}

\begin{document}
\thispagestyle{empty}
\pagestyle{empty}
\setlength{\parindent}{0cm}
\def\Phrase{Phrase to repeat }
\def\repititions{400}%The issue is with the number 400.

\foreach \n in {0,...,\repititions}{\Phrase}
\end{document}

Sin embargo, llegué a la cifra 400mediante prueba y error. Esto no es realmente un problema, ya que imprimiré la página para poder configurar el número \repetitionpara que sea arbitrariamente grande. Más bien es una molestia.

Entonces, mi pregunta es:

¿Hay alguna manera de detener el bucle al final de una página, en lugar de obtener el valor 400mediante prueba y error?

Respuesta1

El creador de páginas es asincrónico y TeX no tiene idea de dónde termina una página al escribir un párrafo. Sólo cuando un párrafo ha finalizado se toman decisiones de salto de página.

Mi estrategia es construir el párrafo gigantesco en un cuadro que luego se compara con la altura del texto deseado. Si todavía está debajo, se prepara un nuevo cuadro con más repeticiones. Cuando tenemos suficiente material (la altura de la página más tres líneas para estar seguros), el cuadro se divide a la altura deseada y se coloca en la página actual.

\documentclass[12pt]{article}

\usepackage[
  margin=0.5in,
  heightrounded, % whole number of lines on the page
  showframe,     % just for the example
]{geometry}
\usepackage{expl3}

\ExplSyntaxOn
% faster than \pgffor
\cs_set_eq:NN \repeatphrase \prg_replicate:nn
\ExplSyntaxOff

\pagestyle{empty}
\setlength{\parindent}{0cm}

\begin{document}

\def\Phrase{Phrase to repeat }
\count255=200 % or anything that seems fit
\loop
  \typeout{Trying \the\count255\space\space repetitions}
  \setbox0=\vbox{\repeatphrase{\count255}{\Phrase}}
  \ifdim\ht0<\dimexpr\textheight+3\baselineskip\relax
  \advance\count255 by 20
\repeat

\setbox0=\vbox to \textheight{
  \vbadness=10000 % remove a spurious message
  \vsplit0 to \textheight
}
\unvbox0

\end{document}

Los mensajes en el terminal y el archivo de registro son

Trying 200 repetitions
Trying 220 repetitions
Trying 240 repetitions
Trying 260 repetitions
Trying 280 repetitions
Trying 300 repetitions
Trying 320 repetitions

El punto de partida es 200, una estimación aproximada de lo que se necesita (se podría empezar desde 1, pero no parece significativo).

ingrese la descripción de la imagen aquí

Tenga en cuenta que LaTeX no tiene una interfaz pública \vsplit, por lo que tenemos que recurrir a programación de nivel inferior.

Aquí hay una versión completa expl3que es esencialmente la misma. Acabo de agregar una pequeña flexibilidad al salto entre líneas para llenar mejor la página.

\documentclass[12pt]{article}

\usepackage[
  margin=0.5in,
  heightrounded, % whole number of lines on the page
  showframe,     % just for the example
]{geometry}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\fillpage}{O{200}m}
 {
  \clearpage
  \egreg_fillpage:nn { #1 } { #2 }
  \clearpage
 }

\int_new:N \l__egreg_fillpage_copies_int
\box_new:N \l__egreg_fillpage_box

\cs_new_protected:Npn \egreg_fillpage:nn #1 #2
 {
  \int_set:Nn \l__egreg_fillpage_copies_int { #1 }
  \bool_do_until:nn
   {
    \dim_compare_p:nNn { \box_ht:N \l__egreg_fillpage_box } > { \textheight + 3\baselineskip }
   }
   {
    \typeout{Trying~\int_eval:n { \l__egreg_fillpage_copies_int }~repetitions}
    \vbox_set:Nn \l__egreg_fillpage_box
     {
      \skip_set:Nn \baselineskip { 1\baselineskip plus 0.1pt }
      \prg_replicate:nn { \l__egreg_fillpage_copies_int } { #2 }
     }
    \int_add:Nn \l__egreg_fillpage_copies_int { 20 }
   }
  \vbox_set_split_to_ht:NNn \l__egreg_fillpage_box \l__egreg_fillpage_box { \textheight }
  \box_use_drop:N \l__egreg_fillpage_box
 }
\ExplSyntaxOff

\pagestyle{empty}
\setlength{\parindent}{0cm}

\begin{document}

\fillpage{Phrase to repeat }

\end{document}

El comando \fillpagetiene un argumento opcional para establecer el número inicial de repeticiones (200 por defecto), por lo que

\fillpage[300]{Phrase to repeat }

Empezaría desde 300.

Respuesta2

Mi solución solo imprime una vez el texto repetido en el cuadro temporal0. Entonces este box0 está \vspliten la página actual.

Se proporciona la macro \toendpage{repeated text}. Esta macro llena la página actual desde el punto actual (es irrelevante si está al principio de la página o en el medio de la página) hasta el final de la página.

La macro \toendpagenecesita hacer un cálculo de cuántas repeticiones del texto necesitamos. Este número debe ser suficientemente grande, por lo que se calcula como

(1.3 * \hsize/ ancho_del_texto + 1) * líneas_en_el_\pagegoal

La macro sigue:

\newcount\tmpnum
\def\toendpage#1{\par \bgroup
   \setbox0=\hbox{#1}
   \null \nobreak \vskip-\baselineskip % we need to set \pagegoal and set zero \prevdepth
   \dimen0=\pagegoal
   \divide\dimen0 by\baselineskip
   \tmpnum=\dimen0                % \tmpnum= number of lines in \pagegoal
   \dimen0=1.3\hsize   
   \divide\dimen0 by\wd0          % \dimen0= number of text in 1.3\hsize     
   \advance\dimen0 by1sp          % increased by one
   \multiply\dimen0 by\tmpnum     % \dimen0= number of repeats of the text
   \tmpnum=0
   \setbox0=\vbox{\null \loop #1\advance\tmpnum by1 \ifnum\tmpnum<\dimen0 \repeat}
   \vbadness=10000
   \dimen0=\pagegoal \advance\dimen0 by-\pagetotal
   \setbox0=\vsplit0 to\dimen0    % \vsplit to the end of the current page
   \unvbox0
   \vfil\break \egroup
}

Usage:        
\toendpage{This is repeated text. }

información relacionada