Получить следующий фрагмент текста (указанного размера), содержащийся в макросе

Получить следующий фрагмент текста (указанного размера), содержащийся в макросе

Допустим, у нас есть большой объем текста, который нужно набрать, содержащийся в одном макросе, назовем его\myverylongtext

\newcommand{\myverylongtext}{
    This is some really long text: \blindtext[4].

    And it continues even more: \blindtext[1].
}

Для простоты предположим, что в нет команды sectioning/newpage \myverylongtext, но в нем могут быть команды переноса строк и несколько абзацев (команды переноса абзацев?). Также предположим, что размер шрифта и интерлиньяж остаются неизменными, хотя все остальные команды набора LaTeX (\textbf и т. д.) разрешены в тексте и должны вступить в силу.

Можно ли определить эффективный* макрос, который (при обнаружении) получает следующий фрагмент текста указанного размера? Например:

\newcommand{\getnextchunk}[4]{
    % #1 is name of macro (in our case \myverylongtext) 
    % #2 width of text box
    % #3 height of text box in lines
    % #4 draftmode: optional boolean argument that, when set, instead of typesetting contents returns the actual height (in lines), and width (in length units) of the chunk. (useful in making dynamic layout decisions)
    % returns/typesets a box of shape width * height
}

Новые вызовы этого макроса \getnextchunkдолжны получать следующий фрагмент текста, как если бы текст, содержащийся в нем, \myverylongtextбыл перенесен из предыдущего фрагмента в этот фрагмент.

* Это \myverylongtextможет быть очень длинным, и таких фрагментов может быть много, поэтому нужна эффективность. Вы не можете набирать оставшуюся часть \myverylongtextнесколько раз. Одно из моих видений решения такой проблемы заключается в том, что блок размером 0 заполняется итеративно, пока не вырастет до указанной метрики: ширина (в измерении длины), высота (в строках) и требуемое выравнивание; хотя мне не хватает понимания низкоуровневого tex/luatex/expl3, чтобы написать его самому.

Кроме того, либо команды выравнивания, такие как raggedright/raggedleft/full-justified, указанные в , \myverylongtextдолжны волшебным образом вступить в силу, либо мы можем установить ограничение, что у нас не будет таких команд в \myverylongtext&, вместо этого передав их в качестве четвертого аргумента \getnextchunk(я думаю, последний вариант предпочтительнее и сделает код/использование проще и/или чище).

Другой способ визуализировать проблему — представить, что у нас есть несколько прямоугольных текстовых полей (разной ширины и высоты), которые последовательно перетекают друг в друга по мере того, как мы сталкиваемся с ними в нашем документе (не беспокойтесь о размещении этих текстовых полей, *tex уже имеет несколько элегантных решений для этого). Кроме того, мы не знаем, когда и сколько таких текстовых полей будет встречаться в документе заранее. По моему мнению, за годы использования *tex решение только этой одной проблемы откроет массу возможностей и сделает tex непобедимым (по сравнению с InDesign и т. д.) по ценности как типографский инструмент для макетов, ориентированных на дизайн. Такие инструменты, как InDesign и Affinity Publisher, позволяют связывать текстовые поля, которые в конечном итоге перетекают друг в друга как поток, и являются чем-то незаменимым для типографской системы, которая предполагает обслуживать современную выразительную типографику и множество дизайнов. Это может открыть *tex как наборщика для гораздо более широкого сообщества наборщиков/дизайнеров.

решение1

Мое решение не совсем то, что вам нужно, но вся информация управляется в одном месте. Надеюсь, что не составит проблемы принять три прохода по параметрам.

Данные должны выглядеть так:

%          lines  width
\declchunk    5     10cm ;
\declchunk    6     12cm ;
\declchunk   12     13cm ;
\declchunk    9     10cm ;
\declchunk    9     10cm ;
\declchunk    9     10cm ;
\declchunk    7      8cm ;
\declchunk    5     10cm ;

\formatchunks \myverylongtext

\setbox101 = \getnextchunk
\setbox102 = \getnextchunk  \rebox 102:{\raggedright}
\setbox103 = \getnextchunk
\setbox104 = \getnextchunk  \rebox 104:{\raggedleft} 
\setbox105 = \getnextchunk

% you can place these boxes everywhere. the following code is only for testing:

box 101: \par \box101 \bigskip
box 102: \par \box102 \bigskip
box 103: \par \box103 \bigskip
box 104: \par \box104 \bigskip
box 105: \par \box105 \bigskip

\bye

Во-первых, мы dcelare размеры всех блоков (по количеству строк для высоты и по размерам для ширины). Во-вторых, мы форматируем заданный текст. Наконец, мы можем получить фрагменты данных и сохранить их, например, в блоках. Они выравниваются по блокам по умолчанию. Если нам нужно сделать другую настройку, то мы можем повторно скомпоновать эти блоки. Наш пример показывает, что второй блок имеет рваные края справа, а четвертый блок имеет рваные края слева. Более того, вы можете сделать

\vbox to<dimension>{\unvbox103} \vtop to12mm{\unvbox105} etc. 

например, потому что между линиями существует растяжимость и сжимаемость.

Реализация: мы получаем все \parshapeпараметры по списку \declchunks, затем форматируем текст, используя эти параметры (только один раз) в \vbox\allchunksи затем делаем \vsplitкогда \getnextcunkвызывается. Наконец, мы можем сделать небольшую переупаковку, если пользователю нужно несколько иное выравнивание блока формы.

Моя реализация работает только с простым TeX и классическим TeX. Нам не нужно никаких расширений TeX и (конечно) нам не нужен LaTeX:).

\newcount\tmpnum
\newcount\shapenum
\newcount\globpar
\newbox\allchunks
\newif\ifrepeat

\splittopskip=\baselineskip

\def\formatchunks#1{\setbox\allchunks=\vbox{%
   \def\par{\ifhmode\shapepar\fi}
   \def\shapepar{\prevgraf=\globpar 
      \parshape\shapenum\shapelist \endgraf
      \globpar=\prevgraf
      \ifnum\prevgraf>\shapenum \let\par=\endgraf \fi}
   \dimen0=\baselineskip \baselineskip=\dimen0 plus2pt minus2pt
   \widowpenalty=0 \clubpenalty=0 \brokenpenalty=0
   \penalty0 #1\vfil}
   \setbox0=\vsplit\allchunks to0pt % \splittopskip added
   \expandafter \renewsize \sizelist \relax
}

\def\shapelist{} \def\sizelist{}
\splittopskip=\baselineskip

\def\shapelist{} \def\sizelist{}

\def\declchunk #1 #2;{\edef\sizelist{\sizelist#1\space}
   \tmpnum=0
   \loop  \advance\tmpnum by1 \advance\shapenum by1
          \edef\shapelist{\shapelist 0pt#2}%
          \ifnum\tmpnum<#1 \repeat
}
\def\getnextchunk{\vsplit\allchunks to\size
   \ifx\sizelist\empty \def\size{\baselineskip}%
   \else \expandafter \renewsize \sizelist \relax \fi 
}
\def\renewsize #1 #2\relax{%
   \def\size{#1\baselineskip}\def\sizelist{#2}%
}

\def\rebox#1:#2{\setbox#1=\vbox{%
   \setbox0=\hbox{}%
   \repeattrue
   \def\raggedright{\rightskip=0pt plus1fill minus1em \relax}%
   \def\raggedleft{\leftskip=0pt plus1fill minus1em \relax}%
   \hsize=\wd#1 
   \unvbox#1
   \loop
      \setbox2=\lastbox
      \ifvoid2 \repeatfalse
      \else \setbox0=\hbox{\hbox{\unhbox2}\penalty-10000 \unhbox0 }
            \unskip\unskip\unpenalty
      \fi
      \ifrepeat \repeat
   \null
   #2\noindent \hfil \unhbox0 \par
}}

\def\myverylongtext{%
  Lorem ipsum dolor sit amet, consectetuer
  ...
  purus eget enim. Nunc vitae tortor. Proin tempus nibh sit amet nisl.
  Vivamus quis tortor vitae risus porta vehicula.
}

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