Прикрепите короткие или длинные последние строки к идеально прямоугольным абзацам

Прикрепите короткие или длинные последние строки к идеально прямоугольным абзацам

При наборе абзацев я хочу убедиться, что их последняя строка не слишком короткая.нислишком длинный.Для этого я ищу настройки, которые производят либо:

  • полностью выровненный, идеально прямоугольный абзац;
  • выровненный абзац, последняя строка которого заполнена более чем на 20%, но менее чем на 80%.

Другими словами, ни один абзац не должен иметь последнюю строку, заполненную менее чем на 20% или более чем на 80% — вместо этого они должны стать полностью выровненными. Эффекта можно достичь, вручную добавляя \parfillskip 0pt(только) эти абзацы, но это именно то, что я хочу автоматизировать вместо этого.

В этом документе приведены два хороших примера и два плохих примера:

\documentclass[a4paper]{article}
\usepackage[utf8]{inputenc}

% Page setup
\usepackage[a4paper,margin=3cm]{geometry}

% Typography
\usepackage{newtxtext,newtxmath}
\usepackage{microtype}
\parindent 0pt
\parskip\baselineskip

\begin{document}

\textbf{I'm looking for settings
        that produce either a)~a~perfect rectangle
        or b)~a paragraph whose last line
        is filled more than 20\% and less than 80\%.}

\section*{Good examples}

\textbf{My perfect paragraph is a~rectangle:}

{
\parfillskip 0pt
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed rhoncus lorem eget ultricies bibendum. Duis luctus felis arcu, sit amet dapibus orci imperdiet id. Duis ullamcorper tortor eget leo fringilla, a lacinia nisl pulvinar. Etiam id facilisis augue. Sed convallis tempus ex, sed accumsan justo pulvinar vitae. Sed id sapien leo. Aliquam posuere ex lacus, ut posuere metus ullamcorper eu. Duis a imperdiet nibh. Donec tincidunt hendrerit nulla, et convallis metus imperdiet nec. Pellentesque massa enim, pharetra in pulvinar a, efficitur nec lorem. Cras mattis ex lorem, et euismod ligula rhoncus. Aenean ultricies quis velit non faucibus.

}

\textbf{However, this is not always achievable (and that's fine):}

{
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed rhoncus lorem eget ultricies bibendum. Duis luctus felis arcu, sit amet dapibus orci imperdiet id. Duis ullamcorper tortor eget leo fringilla, a lacinia nisl pulvinar. Etiam id facilisis augue. Sed convallis tempus ex, sed accumsan justo pulvinar vitae. Sed id sapien leo. Aliquam posuere ex lacus, ut posuere metus ullamcorper eu. Duis a imperdiet nibh. Donec tincidunt hendrerit nulla, et convallis metus imperdiet nec. Pellentesque massa enim, pharetra in pulvinar a, efficitur nec lorem. Cras mattis ex lorem, et euismod ligula rhoncus.

}

\section*{Bad examples}

\textbf{This last line is too short:}

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed rhoncus lorem eget ultricies bibendum. Duis luctus felis arcu, sit amet dapibus orci imperdiet id. Duis ullamcorper tortor eget leo fringilla, a lacinia nisl pulvinar. Etiam id facilisis augue. Sed convallis tempus ex, sed accumsan justo pulvinar vitae. Sed id sapien leo. Aliquam posuere ex lacus, ut posuere metus ullamcorper eu. Duis a imperdiet nibh. Donec tincidunt hendrerit nulla, et convallis metus imperdiet nec. Pellentesque massa enim, pharetra in pulvinar a, efficitur nec lorem.

\textbf{The above can be fixed with}
\verb!\parfillskip 0pt plus 0.80\textwidth!
\textbf{but that doesn't help for the case below.}

\textbf{This last line should have been justified (note the small gap at the end):}

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed rhoncus lorem eget ultricies bibendum. Duis luctus felis arcu, sit amet dapibus orci imperdiet id. Duis ullamcorper tortor eget leo fringilla, a lacinia nisl pulvinar. Etiam id facilisis augue. Sed convallis tempus ex, sed accumsan justo pulvinar vitae. Sed id sapien leo. Aliquam posuere ex lacus, ut posuere metus ullamcorper eu. Duis a imperdiet nibh. Donec tincidunt hendrerit nulla, et convallis metus imperdiet nec. Pellentesque massa enim, pharetra in pulvinar a, efficitur nec lorem. Cras mattis ex lorem, et euismod ligula rhoncus. Aenean ultricies quis velit non ut faucibus.

\textbf{The above can be fixed with}
\verb!\parfillskip 0pt!
\textbf{but that doesn't help for the case below.}

\end{document}

Решение должно состоять изкорректировки только в преамбуле. Никаких специальных команд не должно требоваться в начале или конце любого абзаца. Я надеюсь, что, как и в нескольких связанных случаях, это можно решить с помощью специального клея в \parfillskip, но я не уверен, возможно ли это.


Похожие вопросы, решения которых я пробовал, но они не дают желаемого результата:

решение1

Этот подходполу-автоматически, поскольку абзац все равно необходимо заключить в \fixitмакрос.

ПЕРЕСМОТРЕННЫЙ ПОДХОД

Вместо того чтобы разбирать абзац пословно, как в ОРИГИНАЛЬНОМ ПОДХОДЕ ниже, здесь я просто измеряю длину содержащего \hboxабзац материала и на основе длины решаю, следует ли использовать завершающий тег \hspace{}\mboxи/или расширение \parfillskip0pt.

Макрос предоставляет необязательный аргумент, если требуется настройка. Он представляет собой наибольшее дробное превышение строки, которое будет сжато, в настоящее время установлено на .05(5%). Вы поймете, что требуется настройка, если строка, которая, как вы думали, будет сжата, будет расширена в совершенно новую широко разнесенную строку. Установка значения по умолчанию на .0устранит любые проблемы, но за счет того, что некоторые строки, которые в противном случае могли бы быть сжаты для устранения конечных вдов, вместо этого расширяются так, что вдова занимает 20% последующей строки.

\documentclass{article}
\usepackage[margin=1.5in,top=0cm,bottom=0cm]{geometry}
\newcommand\fixit[2][.05]{%
  \setbox0=\hbox{\hspace{\parindent}#2}\fixithelp{#1}{#2}}
\newcommand\fixithelp[2]{%
  \wd0=\dimexpr\wd0-\linewidth\relax%
  \ifdim\wd0>0pt\relax%
    \fixithelp{#1}{#2}%
  \else%
    \wd0=\dimexpr\wd0+\linewidth\relax
    \ifdim\wd0>.9\linewidth\relax%
      {\parfillskip0pt\relax#2\par}%
    \else%
      \ifdim\wd0>.8\linewidth\relax%
        {\parfillskip0pt\relax#2\hspace{.2\linewidth}\par}%
      \else%
        \ifdim\wd0<#1\linewidth\relax%
          {\parfillskip0pt\relax#2\par}%
        \else%
          \ifdim\wd0<.2\linewidth\relax%
            {\parfillskip0pt\relax#2\hspace{.8\linewidth}\mbox{}\par}%
          \else%
            #2%
          \fi
        \fi
      \fi
    \fi
  \fi%
}
\sloppy
\parskip1ex
\begin{document}
\noindent\rule{.2\linewidth}{2pt}\hfill\rule{.2\linewidth}{2pt}

\fixit{%
yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yack, yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yackity yack, yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yack, yackity yack, yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yackity yack, yackity yack, yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yack, yackity yack, yackity yack, yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yackity yack, yackity yack, yackity yack, yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yack, yackity yack, yackity yack, yackity yack, yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yackity yack, yackity yack, yackity yack, yackity yack, yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yack, yackity yack, yackity yack, yackity yack, yackity yack, yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yackity yack, yackity yack, yackity yack, yackity yack, yackity yack, yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yack, yackity yack, yackity yack, yackity yack, yackity yack, yackity yack, yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
yackity yack, yackity yack, yackity yack, yackity yack, yackity yack, yackity yack, yackity yack, yakity yack, yakity yack, paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\end{document}

Поля=1,5 дюйма

введите описание изображения здесь

Поля = 1,7 дюйма

введите описание изображения здесь

Поля = 1,9 дюйма

введите описание изображения здесь

ОРИГИНАЛЬНЫЙ ПОДХОД

Но макрос пережевывает абзац слово за словом, пока не останется 4 последних слова. Затем он определяет, сколько из этих последних слов требуется для превышения, .2\linewidthи объединяет их вместе \mboxс \hspace{.2\linewidth}. Если последние 3 слова не превышают .2\linewidth, то он использует все 4 в \mbox.

Ибо то, что просит ОП, \sloppyпочти наверняка потребуется, поскольку мы говорим об изменении длины текста .4\linewidthодним махом (что почти всегда нежелательно). Поэтому я это добавил.

Одна вещь, которая сломает подход, это если ранее открытая группа заканчивается в пределах последних 4 слов абзаца. Это применимо, например, при закрытии длинного текста \textitближе к концу абзаца.

Еще следует отметить, что идеально прямоугольный абзац будетникогдабыть создано с помощью этого подхода, из-за добавленного \hspaceв конце абзаца.

\documentclass{article}
\newcommand\fixit[1]{\fixithelp#1 \cr\relax}
\def\fixithelp#1 #2 #3 #4 #5\relax{\ifx \cr#5\finishup#1 #2 #3 #4\relax%
  \else#1 \fixithelp#2 #3 #4 #5\relax\fi}
\def\finishup#1 #2 #3 #4\relax{ %
  \setbox0=\hbox{#4}%
  \ifdim\wd0>.2\linewidth\relax #1 #2 #3 \mbox{#4\hspace{.2\linewidth}}\else%
    \setbox0=\hbox{#3 #4}%
    \ifdim\wd0>.2\linewidth\relax #1 #2 \mbox{#3 #4\hspace{.2\linewidth}}\else%
      \setbox0=\hbox{#2 #3 #4}%
      \ifdim\wd0>.2\linewidth\relax #1 \mbox{#2 #3 #4\hspace{.2\linewidth}}\else%
        \mbox{#1 #2 #3 #4\hspace{.2\linewidth}}%
      \fi%
    \fi%
  \fi%
}
\sloppy
\parskip1em
\begin{document}
\fixit{typesetting 
paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce either:}

\fixit{%
paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce overlylongwords:}

\fixit{%
I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce overlylongwords:}

\fixit{%
typesetting paragraphs, I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce I I I I:}

\fixit{%
typesetting I want to \textit{ensure their last line} is neither 
overly short nor overly long. To that end, I'm looking for settings that 
produce I I I I:}
\end{document}

введите описание изображения здесь

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