Balancing ragged right line lengths

horizontal alignmentparagraphs

I have a \section-like command that takes an optional title. The title may be empty (default), short or so long that it doesn't fit on one line. In the latter case, I would like it to be split into lines of about equal length and printed \raggedright. Is this possible?

I found other questions where the approach is to reduce the glue added at the end of each line, but I don't think I can go that route since the title may be empty and I would need the glue to stretch over the whole line in that case.


Here's a toy version of my command.

\documentclass{article}

\newcommand*\foo[1]{%
  \par
  {\raggedright\Large\bfseries\sffamily
    \strut #1%
    \par
  }%
  \hrule
  \noindent\ignorespaces
}

\begin{document}

\noindent
asdf

\foo{}
asdf

\foo{short}
asdf

\foo{long, I mean really long, so long that it can't fit on a single line}
asdf

\end{document}

MWE output


Desired output:
MWE output

Best Answer

I compute the natural width of the text and then set \rightskip to the line width minus an approximate width for the lines to typeset, with some stretchability.

Also applying a rather high value for \linepenalty, we keep the number of lines at the minimum.

\documentclass[draft]{article}
\usepackage{xfp}

\newcommand{\fooformat}{\Large\bfseries\sffamily}

\newcommand*\foo[1]{%
  \par
  \sbox0{\fooformat #1}%
  {%
   \raggedright
   \fooformat
   \linepenalty3000
   \rightskip=\dimexpr\linewidth-\wd0/\fpeval{1+round(\wd0/\textwidth)}\relax plus 4em\relax
   \strut #1\par
  }%
  \hrule
  \noindent\ignorespaces
}

\begin{document}

\noindent
asdf

\foo{}
asdf

\foo{short}
asdf

\foo{long, I mean really long, so long that it can't fit on a single line}
asdf

\foo{long, I mean really long, so long that it can't fit on a single line
 and even longer, but really really longer}
asdf

\end{document}

enter image description here