2

As a followup to this question, I'd like to ask: how to properly add hyphenation exceptions that contain underscores?

NB: Previous questions (and I found a few) settled with somehow fixing the hyphenation, even if it meant mutilating each and every instance of the word(s) to be hyphenated. But I need a solution that doesn't require me to (from the view of the LaTeX engine) pre-process the text before handing it to LaTeX. Also, modifying each and every instance of these seems to violate one of those sermons I've heard when I initially started with LaTeX during my university time: that LaTeX frees you from having to micro-manage details like that and you just type out the text and the document class in tandem with LaTeX will do the rest.

Consider the answer by Ulrike Fischer, slightly adjusted:

\documentclass{article}
\usepackage[ngerman,english]{babel}
\usepackage{xparse}
\usepackage{microtype}
\usepackage[T1]{fontenc}
\DeclareRobustCommand\funcfamily
{\fontencoding{OT1}\fontfamily\ttdefault\selectfont}
\hyphenation{
    An-Obscenely-Long-Function-Name
    Another_Name_With_Under-scores
}

\NewDocumentCommand{\funcref}{mo}{{%
        \funcfamily\hyphenchar\font=130
        \hyperref[#1]{#1(\IfValueTF{#2}{#2}{})}}}

\usepackage{hyperref}

\begin{document}
    AnObscenelyLongFunctionName AnObscenelyLongFunctionName AnObscenelyLongFunctionName
    AnObscenelyLongFunctionName AnObscenelyLongFunctionName

    foo bar baz \funcref{AnObscenelyLongFunctionName} \funcref{AnObscenelyLongFunctionName} \funcref{AnObscenelyLongFunctionName} \funcref{AnObscenelyLongFunctionName} \funcref{AnObscenelyLongFunctionName} \funcref{AnObscenelyLongFunctionName} \funcref{AnObscenelyLongFunctionName}
\end{document}

pdfLaTeX chokes on line 11 with:

Improper \hyphenation will be flushed. Another_
Improper \hyphenation will be flushed. Another_Name_
Improper \hyphenation will be flushed. Another_Name_With_

Initially I thought this answer to the question titled "Hyphenation for words with underscore" would help me out, but it doesn't. In fact I tried also with \usepackage{underscore}.

It also doesn't make much of a difference whether I use

\hyphenation{
    An-Obscenely-Long-Function-Name
    Another_Name_With_Under-scores
}

or:

\hyphenation{
    An-Obscenely-Long-Function-Name
    Another\_Name\_With\_Under-scores
}

(Well, not entirely true, I get more errors on line 11 if I use the latter, but effectively it's the same to me as both fail to work. Also, if I modify the catcode both variants behave identically.)

I read the appendix H "Hyphenation" in the TeX-book, but I reckon it doesn't discuss my case since natural languages don't use underscores.

I also tried adjusting the catcode for the underscore to be 11 before defining the hyphenation exceptions (i.e. surrounding the \hyphenation{}, inspired by this answer), but that failed as well.

So how can I define hyphenation exceptions for words/names with underscores?

I would prefer to avoid having to "treat" each and every instance of these words/names (as in this Q&A), which is why I am looking to add them to the hyphenation exceptions.

  • 2
    You are just specifying a single long word, that way. Also keep in mind that underscore doesn't make _ of catcode 11 or 12, but active. – egreg Jul 4 at 10:24
  • This all sounds as if you shouldn't use hyphenation but url break, see e.g. tex.stackexchange.com/a/95104/2388 – Ulrike Fischer Jul 4 at 11:01
  • @UlrikeFischer fair enough, although to stay explicit I'd have to define my own command. I actually stumbled over url before and had some issue. But I'll revisit this now and possibly ask in a separate question. Still I think it's worthwhile know if it's possible to use underscores in the hyphenation exceptions and how. – 0xC0000022L Jul 4 at 11:13
2

In pdflatex hyphenation depends on the lccode of a char. And the catcode should better not be 8 as \hyphenation doesn't like this.

You can change the catcode and the lccode, then the hyphenation works. But be aware that you no longer can use your command in the argument of another command.

\documentclass{article}
\usepackage[ngerman,english]{babel}
\usepackage{xparse}
\usepackage{microtype}
\usepackage[T1]{fontenc}


\DeclareRobustCommand\funcfamily
{\fontencoding{OT1}\fontfamily\ttdefault\selectfont}

\catcode`\_=12 \lccode`\_=`\_
\hyphenation{
    An-Obscenely-Long-Function-Name
    Another_Name_With_Under-scores
}
\catcode`\_=8

\NewDocumentCommand{\funcref}{}{%
 \begingroup
 \catcode`\_=12
 \funcrefaux}

\NewDocumentCommand\funcrefaux{mo}{%
 \endgroup 
 \funcfamily\hyphenchar\font=130
 \hyperref[#1]{#1(\IfValueTF{#2}{#2}{})}}

\usepackage{hyperref}

\begin{document}
    AnObscenelyLongFunctionName AnObscenelyLongFunctionName AnObscenelyLongFunctionName
    AnObscenelyLongFunctionName AnObscenelyLongFunctionName

    foo bar baz \funcref{AnObscenelyLongFunctionName} \funcref{AnObscenelyLongFunctionName} \funcref{AnObscenelyLongFunctionName} \funcref{AnObscenelyLongFunctionName} \funcref{AnObscenelyLongFunctionName} \funcref{AnObscenelyLongFunctionName} \funcref{AnObscenelyLongFunctionName} \funcref{Another_Name_With_Underscores} \funcref{Another_Name_With_Underscores}
    \funcref{Another_Name_With_Underscores}


\end{document}
  • With But be aware that you no longer can use your command in the argument of another command. you're saying that it's not a robust command anymore, right? (funcref, that is) – 0xC0000022L Jul 4 at 13:09
  • no, it has to change catcodes and this don't work if they are already frozen. – Ulrike Fischer Jul 4 at 13:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.