Obtenha o próximo pedaço de texto (de tamanho especificado) contido em uma macro

Obtenha o próximo pedaço de texto (de tamanho especificado) contido em uma macro

Digamos que temos muito texto para ser digitado contido em uma única macro, vamos chamá-lo\myverylongtext

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

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

Para simplificar, digamos que não haja comando de seção/newpage em \myverylongtext, mas ele pode ter comandos de quebra de linha e vários parágrafos (comandos de quebra de parágrafo?). Além disso, suponha que o tamanho da fonte e o início permaneçam constantes, embora todos os outros comandos de composição LaTeX (\textbf, etc) sejam permitidos no texto e devam entrar em vigor.

É possível definir uma macro eficiente* que (quando encontrada) obtenha o próximo pedaço de texto da dimensão especificada? Por exemplo:

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

Novas chamadas para esta macro \getnextchunkdevem obter o próximo pedaço de texto, como se o texto contido em \myverylongtextrefluísse do pedaço anterior para este pedaço.

* Isso \myverylongtextpode ser muito longo e pode haver vários desses pedaços, portanto, é necessária eficiência. Você não pode digitar a parte restante \myverylongtextvárias vezes. Uma visão que tenho de solução para tal problema é que uma caixa de tamanho 0 seja preenchida iterativamente até atingir a métrica especificada: largura (em dimensão de comprimento), altura (em linhas) e justificativa necessária; embora eu não tenha compreensão de tex/luatex/expl3 de baixo nível para escrevê-lo sozinho.

Além disso, comandos de justificação como raggedright/raggedleft/full-justified especificados em \myverylongtextdevem entrar em vigor magicamente, ou podemos definir uma restrição de que não teremos tais comandos no \myverylongtext&, em vez disso, passá-los como um quarto argumento para \getnextchunk(acho que o último é preferível e tornaria mais fácil e/ou mais limpo codificar/usar).

Outra forma de visualizar o problema é imaginar que temos múltiplas caixas de texto retangulares (de diferentes larguras e alturas) que fluem umas para as outras sequencialmente à medida que as encontramos em nosso documento (não se preocupe com o posicionamento dessas caixas de texto, *tex já tem várias soluções elegantes para isso). Além disso, não sabemos quando e quantas dessas caixas de texto serão encontradas antecipadamente no documento. Na minha opinião, após anos de uso do *tex, resolver apenas esse problema abrirá inúmeras possibilidades e tornará o tex imbatível (contra o InDesign, etc.) em valor como ferramenta tipográfica para layouts orientados ao design. Ferramentas como InDesign e Affinity Publisher permitem vincular caixas de texto que eventualmente fluem entre si como um fluxo, e é algo indispensável para um sistema tipográfico que pretende atender à tipografia expressiva moderna e à pluralidade de designs. Isso pode abrir o *tex como compositor para uma comunidade de composição/design muito mais ampla.

Responder1

Minha solução não é exatamente o que você deseja, mas todas as informações são gerenciadas em um só lugar. Espero que não seja problema aceitar três passagens de parâmetros.

Os dados devem ficar assim:

%          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

Primeiro, determinamos as dimensões de todos os pedaços (por número de linhas para alturas e por dimensões para larguras). Em segundo lugar, formatamos o texto fornecido. Finalmente, podemos obter alguns dados e salvá-los em caixas, por exemplo. Eles são justificados para blocos por padrão. Se precisarmos fazer outra configuração, podemos reencaixar essas caixas. Nosso exemplo mostra que a segunda caixa está irregular para a direita e a quarta caixa está irregular para a esquerda. Além disso, você pode fazer

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

por exemplo, porque existe elasticidade e encolhimento entre as linhas.

Implementação: obtemos todos \parshapeos parâmetros pela lista de \declchunks, depois formatamos o texto usando esses parâmetros (apenas uma vez) \vbox\allchunkse então fazemos \vsplitquando \getnextcunké chamado. Finalmente, podemos fazer um pequeno re-boxing se o usuário precisar de uma justificativa de bloco de formulário diferente.

Minha implementação funciona apenas com TeX simples e TeX clássico. Não precisamos de nenhuma extensão TeX e (é claro) não precisamos de 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.
}

informação relacionada