Ajusta las últimas líneas cortas o largas a párrafos perfectamente rectangulares

Ajusta las últimas líneas cortas o largas a párrafos perfectamente rectangulares

Al componer párrafos, quiero asegurarme de que la última línea no sea demasiado corta.nidemasiado largo.Con ese fin, estoy buscando configuraciones que produzcan:

  • un párrafo totalmente justificado y perfectamente rectangular;
  • un párrafo justificado cuya última línea esté rellenada en más del 20% y menos del 80%.

En otras palabras, ningún párrafo debe tener una última línea que esté llena en menos del 20 % o más del 80 %; en su lugar, deben estar completamente justificadas. El efecto podría lograrse agregando manualmente \parfillskip 0pt(solo) esos párrafos, pero esto es exactamente lo que quiero automatizar.

Este documento muestra dos buenos ejemplos y dos malos ejemplos:

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

Una solución debe consistir enajustes solo en el preámbulo. No se deben requerir comandos especiales al principio o al final de ningún párrafo. Espero que, como en varios casos relacionados, se pueda solucionar con un poco de pegamento especial \parfillskip, pero no estoy seguro de que sea posible.


Preguntas relacionadas, cuyas soluciones he probado pero no producen el resultado deseado:

Respuesta1

Este enfoque essemi-automático, en el sentido de que aún hay que encerrar el párrafo en una \fixitmacro.

ENFOQUE REVISADO

En lugar de diseccionar el párrafo palabra por palabra, como en el ENFOQUE ORIGINAL a continuación, aquí simplemente mido la longitud del \hboxmaterial que contiene el párrafo y decido, en función de la longitud, si empleo un final \hspace{}\mboxy/o un \parfillskip0pt.

La macro proporciona un argumento opcional si es necesario realizar ajustes. Representa el mayor desbordamiento de línea fraccional que se comprimirá, actualmente establecido en .05(5%). Sabrá que es necesario modificarlo si una línea que pensaba que se comprimiría se expande a una línea completamente nueva y ampliamente espaciada. Establecer el valor predeterminado en .0eliminará cualquier problema, pero a costa de que algunas líneas que de otro modo podrían comprimirse para eliminar las viudas finales se expanden para que la viuda ocupe el 20% de la línea siguiente.

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

Márgenes = 1,5 pulgadas

ingrese la descripción de la imagen aquí

Márgenes = 1,7 pulgadas

ingrese la descripción de la imagen aquí

Márgenes = 1,9 pulgadas

ingrese la descripción de la imagen aquí

ENFOQUE ORIGINAL

Pero lo que hace la macro es regurgitar el párrafo palabra por palabra hasta llegar a las últimas 4 palabras. Luego, determina cuántas de esas últimas palabras deben exceder .2\linewidthy las agrupa dentro de un \mboxjunto con un \hspace{.2\linewidth}. Si las últimas 3 palabras no exceden .2\linewidth, entonces usa las 4 en el archivo \mbox.

Para lo que el OP solicita, \sloppycasi con seguridad será necesario, ya que estamos hablando de cambiar la longitud del texto de .4\linewidthuna sola vez (lo cual casi siempre es algo no deseado). Entonces lo agregué.

Una cosa que romperá el enfoque es si un grupo previamente abierto finaliza dentro de las últimas 4 palabras del párrafo. Esto se aplicaría, por ejemplo, al cerrar un párrafo largo \textitcerca del final de un párrafo.

La otra cosa a tener en cuenta es que un párrafo perfectamente rectangularnuncase creará con este enfoque, debido a lo agregado \hspaceal final del párrafo.

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

ingrese la descripción de la imagen aquí

información relacionada