添加可能被 tex 调用的可选文本,以避免出现坏框

添加可能被 tex 调用的可选文本,以避免出现坏框

我目前正在写一篇很长的文档,每当我切换样式时(我知道,我不应该经常这样做),我都会收到大量错误的框,主要是因为段落中的长而牢不可破的数学部分换行方式不同。例如:

We should consider the function $alongfunctiondefinitionthat
cannotbesplitintwolinesandIdon'twanttohaveinitsownenvironment$.

通常,当我需要修复这些糟糕的框时,我最终不得不添加或删除前面句子中的文本,以使此函数定义出现在行首。但如果我再次更改样式,我可能不得不稍后恢复此努力(有时这需要大量工作)。

我的问题如下:是否可以添加一段可选的文本,仅在有助于避免出现坏框的情况下插入?例如:

We should consider the \opt{following continuous} function $alongfunctiondefinitionthat
cannotbesplitintwolinesandIdon'twanttohaveinitsownenvironment$.

然后 TeX 可以following continuous根据包装算法决定是否应该插入。

或者更好的是,有两个可选的文本可供选择

We \opt{define the}{would like to introduce the following continuous} function...

我不知道是否有办法将其融入 TeX 的包装算法,但如果能做到那就太棒了!

答案1

我的解决方案引入了一个宏\testbadnesspar{paragraph text},它计算段落中行的最大不良程度,并将结果设置为\badnesspar寄存器。\choosepar{par1}{par2}{par3}...{par-n}{}提供了。它根据从段落列表中选择最佳段落\badnesspar。并且

\chooseoptpar {paragraph text with the \opt{one}{two} macro}` 

提供。它从两个\opt扩展变体生成的两个变体中选出更好的段落。

\newif\ifboxrepeat   \boxrepeattrue
\newcount\badnesspar
\newcount\tmpnum

\def\testbadnesspar#1{\par
   \setbox0=\vbox{#1\par
   \global\badnesspar=0
   \loop
      \setbox0=\lastbox
      \ifvoid0 \boxrepeatfalse \else
         \unskip \unpenalty \setbox0=\hbox to\hsize{\unhbox0}
         \ifnum\badness > \badnesspar \global\badnesspar=\badness \fi
      \fi
      \ifboxrepeat \repeat
   }
}
\def\choosepar{\par\def\tmp{}\tmpnum=2000000 \chooseparA}
\def\chooseparA#1{\ifx^#1^\tmp \else
   \testbadnesspar{#1}
   \ifnum\tmpnum>\badnesspar \tmpnum=\badnesspar \def\tmp{#1}\fi
   \expandafter\chooseparA \fi
}
\def\chooseoptpar#1{%
   \def\opt##1##2{##1}
   \testbadnesspar{#1}\tmpnum=\badnesspar
   \def\opt##1##2{##2}
       \testbadnesspar{#1}
   \ifnum\badnesspar>\tmpnum \def\opt##1##2{##1}\fi
   #1\par
}   

%%% test
\hsize=8cm

\chooseoptpar{
   We \opt{define}{would like to introduce the following continuous}
   function $alongfunctiondefinitionthat$.
}

\bye

答案2

您可以通过环境\sloppy\sloppypar环境来减少/消除过满的盒子(尽管\sloppy仍然会产生未满的盒子)。当然,它可能会通过引入过多的空间来消除过满的问题。

已编辑以引入\optOP 所要求的语法,但宏\optpar仍必须对整个段落进行操作。\opt在 的参数中允许 的多个实例\optpar。 使用可选参数 会\optpar产生一个诊断结果,该结果显示了在没有草率更正的情况下这两个选项会是什么样子。

\optpar使用辅助宏\choosepar{}{},该宏将两个完整的段落选项作为输入。它将它们都设置\sloppy为临时文本\parbox,并将文本的总长度(模数\textwidth)与简单临时框(不会进行空间拉伸)中设置的相同文本进行比较。

它选取空间拉伸最小的段落,并将其设置在一个位置sloppypar以消除过满的框,同时选择最不糟糕的框。

此 MWE 采用诊断选项(如图所示red!90)来显示当前的选择。

\documentclass{article}
\usepackage{tabto,ifthen,xcolor}
\def\compressbias{0pt}

\newcommand\savemypos[1]{%
  \tabto*{0in}\xdef#1{\TabPrevPos}\tabto{\TabPrevPos}{}%
}
\newcommand\testpar[1]{%
  \xdef\myparskip{\the\parindent}%
  \setbox2=\hbox{\parbox{\textwidth}{\sloppy%
    \hspace*{\myparskip}#1\savemypos{\finalparloc}}}
  \setbox4=\hbox{#1}%
  \wd4=\dimexpr\wd4-\compressbias\relax%
  \def\continuecheck{T}%
  \whiledo{\equal{T}{\continuecheck}}{%
    \wd4=\dimexpr\wd4-\textwidth\relax%
    \ifdim\wd4<\finalparloc\def\continuecheck{F}\fi%
  }%
  \def\thedelta{\the\dimexpr\finalparloc-\wd4\relax}%
}
\newcommand\choosepar[2]{%
  \begin{sloppypar}%
  \testpar{#1}\edef\deltaA{\thedelta}%
  \testpar{#2}\edef\deltaB{\thedelta}%
  \ifdim\deltaA>\deltaB\relax#2\else#1\fi%
  \end{sloppypar}%
}
\newcommand\optpar[2][\relax]{\choosepar{%
  \def\opt##1##2{##1}#2}{\def\opt##1##2{##2}#2}%
% THE FOLLOWING CODE USES THE OPTIONAL ARGUMENT FOR DIAGNOSTICS
  {\color{red!90}\ifx\relax#1\else%
  The options had been:\par
  \def\opt##1##2{##1}#2\par versus\par
  \def\opt##1##2{##2}#2\par
  \fi}%
}
\parskip 1ex
\begin{document}
\noindent\hrulefill

\optpar[d]{This \opt{particular}{\ignorespaces} sentence is being 
  tested, because it has a long box, 
  \mbox{$\int_0^x A + b\xi + C\xi^2 \,d\xi$} 
  in the middle of it.}

\noindent\hrulefill

\optpar[d]{This \opt{particular}{small} sentence is
  tested with \opt{several}{two} opt calls because it
  has a box, 
  \mbox{$\int_0^x A + b\xi + C\xi^2 \,d\xi$} 
  in the middle of it.}

\noindent\hrulefill

\optpar[d]{This \opt{particular}{small} sentence is being 
  tested, because it has a long box, 
  \mbox{$\int_0^x A + b\xi + C\xi^2 \,d\xi$} 
  in the middle of it.}

Both choices were bad.  But the first option was chosen 
because the second choice,
when addressed with sloppy, would introduce more space.

\end{document}

在此处输入图片描述

原始(预\optpar)解决方案显示解决方案元素:

在 MWE 中,我定义了两个段落,并分别展示了它们的排版效果和外观(我这样做是为了说明……这不是该方法所必需的)。然后我使用它\choosepar来选择最好的一个。然后我执行第二个示例,该示例仅包含一大块被正常文本包围的方框材料。

编辑以允许用户选择我所说的特定长度\compressbias,以便我使用的模数数学不会将小空间压缩(这是可以接受的)视为大空间扩展(具有很大的坏处)

\documentclass{article}
\usepackage{tabto,ifthen}
\def\compressbias{0pt}

\newcommand\savemypos[1]{%
  \tabto*{0in}\xdef#1{\TabPrevPos}\tabto{\TabPrevPos}{}%
}
\newcommand\testpar[1]{%
  \xdef\myparskip{\the\parindent}%
  \setbox2=\hbox{\parbox{\textwidth}{\sloppy%
    \hspace*{\myparskip}#1\savemypos{\finalparloc}}}
  \setbox4=\hbox{#1}%
  \wd4=\dimexpr\wd4-\compressbias\relax%
  \def\continuecheck{T}%
  \whiledo{\equal{T}{\continuecheck}}{%
    \wd4=\dimexpr\wd4-\textwidth\relax%
    \ifdim\wd4<\finalparloc\def\continuecheck{F}\fi%
  }%
  \def\thedelta{\the\dimexpr\finalparloc-\wd4\relax}%
}
\newcommand\choosepar[2]{%
  \begin{sloppypar}%
  \testpar{#1}\edef\deltaA{\thedelta}%
  \testpar{#2}\edef\deltaB{\thedelta}%
  \ifdim\deltaA>\deltaB\relax#2\else#1\fi%
  \end{sloppypar}%
}
\parskip 1ex
\begin{document}

\def\tmpA{%
verylongwordthathasnospace 
verylongwordthathasnospace
verylongwordthathasnospace
verylongwordthathasnospace
verylongwordthathasnospace
verylongwordthathasnospace
verylongwordthathasnospace.}%

\testpar{\tmpA}
added space = \thedelta

\begin{sloppypar}
\tmpA
\end{sloppypar}

\def\tmpB{%
very longword that has no space 
very longword that has no space
very longword that has no space
very longword that has no space
very longword that has no space
very longword that has no space
very longword that has no space.}%
\testpar{\tmpB}

added space = \thedelta
\begin{sloppypar}
\tmpB
\end{sloppypar}

Now let choosepar pick:

\choosepar{\tmpA}{\tmpB}

EXAMPLE 2:

\choosepar{%
I want to check the quality of this algorithm on a 
\mbox{verylongwordthathasnospace} 
to see if it will work.}{%
I want to check whether 
\mbox{verylongwordthathasnospace} 
will fit nicely in this space.}

This was the one rejected:

\begin{sloppypar}
I want to check the quality of this algorithm on a 
\mbox{verylongwordthathasnospace} 
to see if it will work.
\end{sloppypar}

\end{document}

在此处输入图片描述

相关内容