Ragged right with hyphenation if and if there is an hyphen in the word

The standard \raggedright prevent any hyphenation at all. The ragged2eor similar method through manipulating the right file allows all hyphenation. Is there a way to set raggedright, but a word that already has a hyphen in it can be breakup, but normal word won't be hyphenated at all?

• There's no inhibition to breaking lines at explicit hyphens in \raggedright. – egreg Feb 11 '17 at 23:18
• @egreg: That’s not correct: an explicit hyphen is charged an \exhyphenpenalty of 50. – GuM Feb 12 '17 at 1:43
• @GustavoMezzetti Is that an inhibition? – egreg Feb 12 '17 at 8:34
• No, @egreg, strictly speaking it is not; but you know perfectly well what I meant, you explained it in your answer (+1, by the way :-)… – GuM Feb 12 '17 at 13:50

TeX charges line breaks at explicit hyphen the current value of the \exhyphenpenalty parameter, whereas “implicit” hyphens (hyphens that TeX inserts automatically during hyphenation) are charged a penalty given by the current value of the different parameter \hyphenpenalty. So, all you need to do is to define a variant of the \raggedright declaration that zeros the former parameter, but not the latter:

% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly
% declare the paper format.

\usepackage[T1]{fontenc}         % Not always necessary, but recommended.
% End of standard header.  What follows pertains to the problem at hand.

\usepackage{lipsum}

\newcommand*{\YZraggedright}{%
\raggedright
\exhyphenpenalty 0 % space is intentional
}
\newenvironment*{YZflushleft}{\trivlist \YZraggedright \item\relax}{}

\begin{document}

In the normal setting, $$\verb|\hyphenpenalty| = \number\hyphenpenalty$$ and
$$\verb|\exhyphenpenalty| = \number\exhyphenpenalty$$.

\begin{flushleft}
Inside this environment,
$$\verb|\hyphenpenalty| = \number\hyphenpenalty$$ and
$$\verb|\exhyphenpenalty| = \number\exhyphenpenalty$$.

This means that \TeX\ will never choose a line break at a word containing an
explicit hyphen, like mother-in-law'', as we can see here:
moooootheeeer-iiin-laaaww and faaaaatheeeeer-iiiiiin-laaaaaaawww (the break
will appeal to \TeX\ only if it makes the paragraph at least one line
shorter, see \verb|\linepenalty|).
\end{flushleft}

\begin{YZflushleft}
Inside this environment,
$$\verb|\hyphenpenalty| = \number\hyphenpenalty$$ and
$$\verb|\exhyphenpenalty| = \number\exhyphenpenalty$$.

This means that, this time, \TeX\ \emph{can} choose a line break at a word
containing an explicit hyphen, like mother-in-law'', as we can see here:
moooootheeeer-iiin-laaaww and faaaaatheeeeer-iiiiiin-laaaaaaawww (the break
will appeal to \TeX\ only if it makes the paragraph at least one line
shorter, see \verb|\linepenalty|).
\end{YZflushleft}

\end{document}


The standard \raggedright setting doesn't inhibit line breaking at explicit hyphens:

\documentclass{article}

% for showing what happens
\usepackage{showframe}
\setlength{\textwidth}{4cm}

\begin{document}

\begin{flushleft}
aaabbb abcdef-ghijklmno-pqr-stuv
aaa gggggg abcdef-ghijklmno-pqr-stuv
aaabbb abcdef-ghijklmno-pqr-stuv
aaa ggggg abcdef-ghijklmno-pqr-stuv
aaabbb abcdef-ghijklmno-pqr-stuv
aaa ggggg abcdef-ghijklmno-pqr-stuv
aaabbb abcdef-ghijklmno-pqr-stuv
\end{flushleft}

\end{document}


What happens is that breaking at hyphens is, at TeX’s eyes, less desirable than breaking at spaces. The result is that a short fragment before the explicit hyphen is likely to be pushed to the next line, rather than allowing a break at the hyphen. You can do

\newenvironment{hflushleft}[1][\exhyphenpenalty]
{\flushleft\exhyphenpenalty=#1 }
{\endflushleft}


so in the hflushleft environment the penalty for breaking at explicit hyphens can be changed. If you do

\begin{hflushleft}
<text>
\end{hflushleft}


the behavior will be the same as for the standard flushleft; with

\begin{hflushleft}[0]
<text>
\end{hflushleft}


or even

\begin{hflushleft}[-50]
<text>
\end{hflushleft}


you make breaking at hyphens “more desirable”. Experiment with these values and then decide what to add to \raggedright, which you can do by

\usepackage{etoolbox}

\preto{\raggedright}{\exhyphenpenalty=<value>}


For instance

\preto{\raggedright}{\exhyphenpenalty=0}

• Many thanks for the detailed explanation. It's very helpful. – Yan Zhou Feb 12 '17 at 9:59