マクロに含まれる次のテキストチャンク(指定されたサイズ)を取得します。

マクロに含まれる次のテキストチャンク(指定されたサイズ)を取得します。

1つのマクロにたくさんのテキストをタイプセットするとします。これをマクロと呼びます。\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複数回タイプセットすることはできません。このような問題の解決策として私が思いついた 1 つのアイデアは、サイズ 0 のボックスが、指定されたメトリック (幅 (長さの次元)、高さ (行数)、必要な位置揃え) に達するまで繰り返し入力されるというものです。ただし、低レベルの tex/luatex/expl3 を理解していないため、自分で記述することはできません。

また、 で指定された raggedright/raggedleft/full-justified などの位置揃えコマンドが\myverylongtext自動的に有効になるか、 にそのようなコマンドが含まれないように制限を設定し\myverylongtext、代わりに の 4 番目の引数として渡すことができます\getnextchunk(後者の方が望ましいと思います。コーディングや使用がより簡単かつクリーンになります)。

この問題を視覚化する別の方法は、複数の長方形のテキスト ボックス (幅と高さが異なる) があり、ドキュメント内で遭遇すると、それらが順番に互いに流れ込んでいくことを想像することです (これらのテキスト ボックスの配置については心配する必要はありません。*tex には、そのための複数の優れたソリューションが既に用意されています)。また、ドキュメント内でそのようなテキスト ボックスがいつ、いくつ出現するかは事前にはわかりません。長年 *tex を使用してきた私の意見では、この問題を 1 つ解決するだけで、多くの可能性が開かれ、デザイン指向のレイアウト用のタイポグラフィ ツールとしての価値において、tex は (InDesign などに対して) 無敵になります。InDesign や Affinity Publisher などのツールでは、最終的にストリームとして互いに流れ込むテキスト ボックスをリンクできます。これは、現代の表現力豊かなタイポグラフィや多様なデザインに対応することを想定したタイポグラフィ システムには欠かせないものです。これにより、*tex はタイプセッターとして、より広範なタイプセッティング/デザイン コミュニティに開放されます。

答え1

私の解決策はまさにあなたが望んでいるものではありませんが、すべての情報が 1 か所で管理されます。パラメータを 3 回渡すことが問題にならないことを願っています。

データは次のようになります。

%          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

まず、すべてのチャンクの寸法を揃えます (高さは行数、幅は寸法)。次に、指定されたテキストをフォーマットします。最後に、データの一部を取得して、たとえばボックスに保存します。デフォルトでは、ブロックに揃えられます。別の設定が必要な場合は、これらのボックスを再度ボックス化できます。この例では、2 番目のボックスは右に不揃いで、4 番目のボックスは左に不揃いです。さらに、次のようにすることもできます。

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

例えば、線の間には伸縮性があるためです。

実装: s\parshapeのリストによってすべてのパラメータを取得し\declchunk、これらのパラメータを使用してテキストをフォーマットし (1 回のみ) 、 が呼び出されたとき\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.
}

関連情報