Повторять до конца страницы

Повторять до конца страницы

Я хочу заполнить страницу одним словом или фразой, повторяющейся снова и снова и снова. Затем я распечатаю эту страницу. Например,

\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}

Однако я пришел к этому числу 400методом проб и ошибок. Это не проблема, так как я распечатаю страницу, поэтому могу просто задать \repetitionпроизвольно большое число. Скорее, это раздражает.

Итак, мой вопрос:

Есть ли способ остановить цикл в конце страницы, вместо того чтобы придумывать значение 400методом проб и ошибок?

решение1

Конструктор страниц асинхронный, и TeX не имеет ни малейшего понятия, где заканчивается страница при наборе абзаца. Только когда абзац заканчивается, принимаются решения о разрыве страницы.

Моя стратегия заключается в том, чтобы построить гигантский абзац в блоке, который затем сравнивается с желаемой высотой текста. Если он все еще ниже, готовится новый блок с большим количеством повторений. Когда у нас достаточно материала (высота страницы плюс три строки, просто для уверенности), блок разделяется на желаемой высоте и помещается на текущую страницу.

\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}

Сообщения на терминале и в файле журнала

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

Начальная точка — 200, грубая оценка того, что необходимо (можно было бы начать с 1, но это не имеет смысла).

введите описание изображения здесь

Обратите внимание, что LaTeX не имеет открытого интерфейса \vsplit, поэтому нам придется прибегнуть к программированию более низкого уровня.

Вот полная expl3версия, которая по сути та же самая. Я просто добавил небольшую гибкость в пропуск между строками для лучшего заполнения страницы.

\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}

Команда \fillpageимеет необязательный аргумент для установки начального количества повторений (по умолчанию 200), поэтому

\fillpage[300]{Phrase to repeat }

начнется с 300.

решение2

Мое решение делает только одну печать повторяющегося текста во временном box0. Затем этот box0 переходит \vsplitна текущую страницу.

Макрос \toendpage{repeated text}предоставляется. Этот макрос заполняет текущую страницу от текущей точки (неважно, находится ли она в начале страницы или в середине страницы) до конца страницы.

Макрос \toendpageдолжен сделать расчет, сколько повторений текста нам нужно. Это число должно быть достаточно большим, поэтому оно вычисляется как

(1,3 * \hsize/ ширина_текста + 1) * строк_в_\pagegoal

Макрос следующий:

\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. }

Связанный контент