如何(!)在同一个段落内(!)设置允许线条太宽的地方和不允许线条太宽的地方?

如何(!)在同一个段落内(!)设置允许线条太宽的地方和不允许线条太宽的地方?

假设您有\macroA一种方法,可以产生一定数量的字符。 假设您有一种方法,可以 产生一定数量的字符。\macroA{⟨TeX number-quantity denoting amount⟩}A
\macroB\macroB{⟨TeX number-quantity denoting amount⟩}B

可能看起来像这样:

%\overfullrule=0pt
\long\def\firstoftwo#1#2{#1}%
\long\def\secondoftwo#1#2{#2}%
\def\macroA#1{%
  \expandafter\Aloop\expandafter{\romannumeral\number\number#1 000}{}%
}%
\def\Aloop#1#2{%
  \ifx\relax#1\relax\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
  {\leavevmode#2}{%
    \expandafter\ifx\expandafter\relax\firstoftwo{}#1\relax\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
    {%
      % Don't use \discretionary with the last A to avoid
      % \baselineskip after the last line in case that line being
      % too long:
      \expandafter\Aloop\expandafter{\firstoftwo{}#1}{#2A}%
    }{%
      % use \discretionary to allow linebreaks
      \expandafter\Aloop\expandafter{\firstoftwo{}#1}{#2A\discretionary{}{}{}}%
    }%
  }%
}%
\def\macroB#1{%
  \expandafter\Bloop\expandafter{\romannumeral\number\number#1 000}{}%
}%
\def\Bloop#1#2{%
  \ifx\relax#1\relax\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
  {\leavevmode#2}{%
    \expandafter\ifx\expandafter\relax\firstoftwo{}#1\relax\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
    {%
      % Don't use \discretionary with the last B to avoid
      % \baselineskip after the last line in case that line being
      % too long:
      \expandafter\Bloop\expandafter{\firstoftwo{}#1}{#2B}%
    }{%
      % use \discretionary to allow linebreaks
      \expandafter\Bloop\expandafter{\firstoftwo{}#1}{#2B\discretionary{}{}{}}%
    }%
  }%
}%

\hrule\kern\dp\strutbox

\macroA{240}

\macroB{240}

\kern\dp\strutbox\hrule

\bye

正如你在图片上看到的,

在此处输入图片描述

,在终端上,

This is pdfTeX, Version 3.14159265-2.6-1.40.19 (TeX Live 2019/dev/Debian) (preloaded format=pdftex)
 restricted \write18 enabled.
entering extended mode
(./test.tex
Overfull \hbox (0.24593pt too wide) in paragraph at lines 26--27
[]\tenrm AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|

Overfull \hbox (2.74597pt too wide) in paragraph at lines 26--27
\tenrm AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|

Overfull \hbox (2.74597pt too wide) in paragraph at lines 26--27
\tenrm AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|

Overfull \hbox (3.57997pt too wide) in paragraph at lines 28--29
[]\tenrm BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB|

Overfull \hbox (4.83005pt too wide) in paragraph at lines 28--29
\tenrm BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB|

Overfull \hbox (4.83005pt too wide) in paragraph at lines 28--29
\tenrm BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB|
[1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] )
(see the transcript file for additional information)</usr/share/texlive/texmf-d
ist/fonts/type1/public/amsfonts/cm/cmr10.pfb>
Output written on test.pdf (1 page, 9746 bytes).
Transcript written on test.log.

,这会产生大量的过满\hboxes,即很多文本行太宽,因此突出到右边距。

假设你申请\macroA并且\macroB 在同一段落内,即你这样做:

\macroA{240}\macroB{240}\bye 。

您将得到一个段落,由一个字母序列A和一个字母序列组成B- 行可能仍然有点太宽:

在此处输入图片描述

问题:

B如何才能在同一个段落中实现这样的效果:以“来自”结尾的行\macroB不会太宽但可能会太短,因此不会突出到右边距;而以“A来自”结尾的行\macroA可能会太宽,因此可能会突出到右边距?

\macroA即如何修改and/or的定义\macroB以实现以下输出,

在此处输入图片描述

,不“手动”进行换行,而是将换行留给 TeX 自己的(非限制)水平模式算法?

如何让用户选择如何处理在即将断线的地方一个B来自后面\macroB跟着一个A来自的\macroA情况,这样如果紧接着断线的话线就会太短一点,B如果紧接着断线的话线就会太宽一点A ;-)



我现在想到的解决方案是生成与字母宽度相同的水平空格,B后跟\hskip相同宽度的可丢弃“负片”,后跟字母B- 这样你仍然会收到\hbox带有Bs 的过满警告,但这样它们是由于行末的空格触发了换行符,而不是由于可见材料突出到右侧边缘:

%\overfullrule=0pt
\long\def\firstoftwo#1#2{#1}%
\long\def\secondoftwo#1#2{#2}%
\def\macroA#1{%
  \expandafter\Aloop\expandafter{\romannumeral\number\number#1 000}{}%
}%
\def\Aloop#1#2{%
  \ifx\relax#1\relax\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
  {\leavevmode#2}{%
    \expandafter\ifx\expandafter\relax\firstoftwo{}#1\relax\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
    {%
      % Don't use \discretionary with the last A to avoid
      % \baselineskip after the last line in case that line being
      % too long:
      \expandafter\Aloop\expandafter{\firstoftwo{}#1}{#2A}%
    }{%
      % use \discretionary to allow linebreaks
      \expandafter\Aloop\expandafter{\firstoftwo{}#1}{#2A\discretionary{}{}{}}%
    }%
  }%
}%
\def\macroB#1{%
  \expandafter\Bloop\expandafter{\romannumeral\number\number#1 000}{}%
}%
\def\Bloop#1#2{%
  \ifx\relax#1\relax\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
  {\leavevmode#2}{%
    \expandafter\Bloop\expandafter{\firstoftwo{}#1}{#2\phantom{B}\hbox{B}{\setbox1=\lastbox\hskip-\wd1 \box1}}%
  }%
}%

\hrule\kern\dp\strutbox

\macroA{240}\macroB{240}

\macroA{240}

\macroB{240}

\kern\dp\strutbox\hrule

\bigskip

About the edge case:

\bigskip

\hrule\kern\dp\strutbox

The case of the 64$^{\hbox{th}}$ B not fitting in the line any more:

\macroB{64}

The edge-case of 63 B being followed by an A:

\macroB{63}\macroA{1}

\kern\dp\strutbox\hrule

\bye

在此处输入图片描述

我不认为这个解决方案很优雅。

我认为还有更好的方法。

答案1

首先:我必须简化您的仅扩展循环,因为它在其参数中一次又一次地重复 256 m、 255 m、 254 。更有效的方法是仅将这 256 放入输入队列一次。mm

第二:我建议对 A 插入负跳过、惩罚 0、正跳过,对 B 则反之。

第三:我建议做成\rightskip可拉伸的,以避免盒子过满。

\def\expandrepeat #1{\expandafter\expandrepeatA\romannumeral #1000\relax}
\def\expandrepeatA #1\relax#2{\expandrepeatB{#2}#1\relax}
\def\expandrepeatB #1#2{\ifx#2\relax \else #1\afterfi \expandrepeatB{#1}\fi}
\def\afterfi#1\fi{\fi#1}

\rightskip=0em minus1em

\expandrepeat{250}{A\hskip-1em\penalty0\hskip1em}%
\expandrepeat{250}{B\hskip1em\penalty0\hskip-1em}

% for testing, where is the margin?
\vskip-4cm \hfill \vrule height4cm

\end

答案2

你是什​​么意思

将换行留给 TeX 自己的(非限制)水平模式算法?

你能修改该算法的参数吗?比如\leftskip\rightskip\tolerance\hfuzz

如果是:

  • 为了允许 TeX 制作由于太短而不好的行,您可以将其设置\tolerance为 10000。
  • 要抑制警告和超长规则,请增加\hfuzz。这不会阻止行变得太长。这只会阻止被告知。这就是我对特定段落所做的。

A或的序列B不包含粘合。诸如此类的事情\emergencystretch似乎并不有趣。它们还适用于整个段落,而不仅仅是段落中的几行。

重复 A 或重复 B 之间的重复惩罚始终相同,并且不会改变哪个 A 或 B 靠近线末端以利于突破线。

宏是否也必须在乳胶\centering(与 TeX 的不同\centering)或center-environment?

任何。

您需要在A或之间设置断点B。您可以穿插一些形成断点的内容:\penalty0\hskip0pt\discretionary{}{}{}。(或者您可以暂时将A或设为B字体的连字符,但不能用于最后的AB。)

该问题隐藏了复制令牌的问题。

通用宏\replicatethis很有用,您可以在其中指定要重复的内容以及要使用的内容进行散布。

使用散布时您需要查看最后一步,因为最后一步不需要散布。

所以我用通用宏如同Wipet 的但有一些修改:

  1. 附加两个\relax以便您可以检测最后一步。
  2. \afterfi,但是\firstotwo/\secondoftwo因为方法将无法产生具有不匹配或的\afterfi事物序列。\if..\fi
  3. \romannumeral0\number\number#1 000使用字母常量时也会`\a失败。\count24\romannumeral#1000
  4. 复制的内容在参数中收集,并在循环结束时一次性交付所有内容。如果通用的 \replicatethis\if必须用不匹配的/保存\fi,必须这样做,以便最后所有不匹配的\if/都会立即出现。缺点:这比较慢,并且重复次数受到参数中适合的标记数量的限制。\fi

 

%\overfullrule=0pt
% / prevent nagging:
{\setbox1=\hbox{A}\expandafter}\expandafter\hfuzz\expandafter=\the\wd1
%\tolerance=10000

\long\def\permutetwoarguments#1#2{#2#1}%
\long\def\firstoftwo#1#2{#1}%
\long\def\secondoftwo#1#2{#2}%
% /
% / Generic macro \repeatthis{<<number> denoting repetitions>}{<what to repeat>}{<interspersing>}
% /
\long\def\replicatethis#1#2#3{%
  % / #1 repetitions
  % / #2 what to repeat
  % / #3 interspersing
  \romannumeral0% / <-- I *think* you may like this.  ;-)
  \expandafter\permutetwoarguments
  \expandafter{\romannumeral\number\number#1 000}%
              {\replicatethisloop{#2}{#3}{}}%
  \relax\relax
}%
\long\def\replicatethisloop#1#2#3#4#5%
  {%
    % / #1 what to repeat
    % / #2 interspersing
    % / #3 what you got so far.
    % / #4 other-m or \relax. If \relax done.
    % / #5 other-m or \relax. If \relax last step or done.
    \ifx#4\relax\expandafter\secondoftwo\else\expandafter\firstoftwo\fi
    {%
      \ifx#5\relax\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
      {\replicatethisloop{#1}{#2}{#3#1}}%
      {\replicatethisloop{#1}{#2}{#3#1#2}}%
      #5%
    }{ #3}%
  }%
% /
% / \macroA and \macroB
% /
\def\macroA#1%
  % / Intersperse with zero-\hskip breakpoint
  {%
    \leavevmode
    \replicatethis{#1}{A}{\hskip0pt}%
  }%
\def\macroB#1%
  % / If the \phantom causes line to be too long, then the \hskip 
  % / as breakpoint is used for breaking line and discarded.
  {%
    \leavevmode
    \replicatethis{#1}{\phantom{B}\hbox{B}{\setbox1=\lastbox\hskip-\wd1}B}{}%
  }%

% / Play game with unbalanced \if \fi.
\expandafter\expandafter\expandafter
\permutetwoarguments
\expandafter\expandafter\expandafter
{\replicatethis{12}{\fi}{}}
{\replicatethis{12}{\iffalse}{\else}}

% / That is the margins:%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\noindent\vrule\vbox to\vsize{\advance\hsize-.8pt\leavevmode\hrule\vfill\hrule}\vrule
\par \kern-\vsize \nobreak\vskip-\baselineskip\nobreak\vskip\topskip\par 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\macroA{240}\macroB{240}

\macroA{240}

\macroB{240}

\kern\dp\strutbox\hrule

\bigskip

About the edge case:

\bigskip

\hrule\kern\dp\strutbox

The case of the 64$^{\hbox{th}}$ B not fitting in the line any more:

\macroB{64}

\smallskip

The edge-case of 63 B being followed by an A:

\macroB{63}\macroA{1}

\smallskip

The edge-case of 60A being followed by a B:

\macroA{60}\macroB{1}

\smallskip

The edge-case of an 1pt-kern and 59A being followed by a B:

\leavevmode\kern1pt\macroA{59}\macroB{1}

\smallskip

The edge-case of 59A being followed by a B:

\macroA{59}\macroB{1}

\kern\dp\strutbox\hrule

\vfill \break

\bye

在此处输入图片描述

答案3

我没有看到被删除的答案,但它可能是这样的。\Aloop改为\discretionary{}{}{}

\nobreak\hskip0ptminus9pt\penalty1000\hskip0ptminus-9pt\relax

\Bloop变成\discretionary{}{}{}

\nobreak\hskip0ptplus9pt\penalty1000\hskip0ptplus-9pt\relax

\nobreak当首字母非常适合整行时,可以省略首字母,以允许普通的齐平换行。

相关内容