[Tex/LaTex] List of Underlining Packages – Pros and Cons

emphasissoultext-decorationstikz-pgfulem

The \underline macro built into LaTeX is pretty much not useable per Why does underlined text not get wrapped once it hits the end of a line ? I have been attempting to use the soul package to underline omitting the descenders but have run into numerous issues, and now considering alternatives.

Hence, am looking for a comparison of the various options for underlining text:

  1. the soul package
  2. the ulem package
  3. Tikz as per this answer on "Cool Text Highlighting in LaTeX".
  4. Any others?

Requirements:

Ideally I would like to be able to underline content

  1. across line breaks
  2. with hyphenation
  3. with math content

Working across page breaks would be a bonus but not something I am too concerned about.

Even if some packages can not meet all the requirements it would be good to have them listed so that one is aware of the potential issues of using it.

Notes:

  • I am aware that generally underlining is frowned upon typography circles. But, I don't have a good alternative for indicating hyperlinks. Using color to indicate a hyperlink has an issue when the link text has more than one word (or two subsequent links) in which case it is not clear exactly what is being linked. More details are in the notes section in Should Hyperlinks include trailing puctuation as part of the link text?. Futhermore I prefer to reserve colors for other purposes.

References:

Best Answer

REVISED SOLUTION

With the recent changes in the censor package to incorporate a tokcycle-based cycle to censor the tokens, the original approach given below requires revision...in fact, it becomes much simpler.

Math censoring can occur with \mblackout (for character by character censoring) or with \mcensor (block underlining).

\documentclass{article}
\usepackage[none]{hyphenat}
\usepackage{censor}
\usepackage{xcolor}
\usepackage{stackengine}
\usepackage{scalerel,lipsum}
\censorruledepth=-.25ex
\censorruleheight=.1ex
\newlength\maxkern
\setlength{\maxkern}{.14ex}
\newlength\nextcharwidth
\makeatletter
\renewcommand\@cenword[1]{%
  \setlength{\nextcharwidth}{\widthof{#1}}%
  \censorrule{\nextcharwidth}%
  \kern -\nextcharwidth%
  \color{white}%
  \kern -.5\maxkern #1\kern .5\maxkern%
  \kern -\nextcharwidth%
  \kern -\maxkern #1\kern \maxkern%
  \kern -\nextcharwidth%
  \kern .5\maxkern #1\kern -.5\maxkern%
  \kern -\nextcharwidth%
  \kern \maxkern #1\kern -\maxkern%
  \kern -\nextcharwidth%
  \color{black}%
  #1}
\let\sv@cenword\@cenword
\newcommand\m@cenword[1]{\ThisStyle{%
  \stackengine{\mcensorruledepth}{$\SavedStyle#1$}%
    {\rule{\widthof{$\SavedStyle#1$}}{\the\censorruleheight}}{U}{c}{F}{T}{L}}}
\newcommand\mblackout[2][\dp\strutbox]{%
  \let\@cenword\m@cenword%
  \def\mcensorruledepth{#1}%
  \blackout{#2}%
  \let\@cenword\sv@cenword%
}
\newcommand\mcensor[2][\dp\strutbox]{%
  \let\@cenword\m@cenword%
  \def\mcensorruledepth{#1}%
  \censor{#2}%
  \let\@cenword\sv@cenword%
}
\makeatother
\begin{document}
\blackout{This is a great test today}

{\raggedright\xblackout{This is a great test today}}

\[ \mblackout{y = A x^{2}} + Bx + \mblackout{C} \]

\[ \mblackout[.3ex]{y = \frac{a^{3} + b^{2} + c}{d_{3}}}\]

\[ \mcensor[3ex]{y = \frac{a^{3} + b^{2} + c}{d_{3}}}\]


\xblackout{Quisque ullamcorper placerat ipsum. Cras nibh. Morbi vel 
  justo vitae lacus tincidunt ultrices. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In hac habitasse platea dictumst. 
Integer tempus convallis augue. Etiam facilisis. Nunc elementum 
fermentum wisi. Aenean placerat. Ut imperdiet, enim sed gravida sollicitudin, felis odio placerat quam, ac pulvinar elit purus 
eget enim. Nunc vitae tortor. Proin tempus nibh sit amet nisl. 
Vivamus quis tortor vitae risus porta vehicula.}

\end{document}

enter image description here

enter image description here

enter image description here

ORIGINAL SOLUTION (based on outdated censor package)

This is a hack on the censor package to do that which was not intended. All things considered, not too bad. It makes space for descenders, with a user-settable gap (\maxkern)! The depth (\censorruledepth) and thickness (\censorruleheight) of the underrule are fully settable. It does linebreaking and page breaking. And with this EDITED version, it now does math underlining.

However, it does not do hyphenation. For text, it has two forms, using the censor syntax, \blackout (which skips over spaces and periods, and \xblackout which attempts, through the use of carefully selected measures, to fill in underlines over the blanks and periods. As the parameters are set in my MWE, \xblackout has a negative side effect of spilling slightly into the left margin.

\documentclass{article}
\usepackage[none]{hyphenat}
\usepackage{lipsum}
\usepackage{censor}
\usepackage{xcolor}
\usepackage{stackengine}
\usepackage{scalerel}
\censorruledepth=-.25ex
\censorruleheight=.1ex
\newlength\maxkern
\setlength{\maxkern}{.14ex}
\newlength\nextcharwidth
\makeatletter
\renewcommand\@cenword[1]{%
  \setlength{\nextcharwidth}{\widthof{#1}}%
  \censorrule{\nextcharwidth}%
  \kern -\nextcharwidth%
  \color{white}%
  \kern -.5\maxkern #1\kern .5\maxkern%
  \kern -\nextcharwidth%
  \kern -\maxkern #1\kern \maxkern%
  \kern -\nextcharwidth%
  \kern .5\maxkern #1\kern -.5\maxkern%
  \kern -\nextcharwidth%
  \kern \maxkern #1\kern -\maxkern%
  \kern -\nextcharwidth%
  \color{black}%
  #1}
\long\def\xblackout#1{\rule{0ex}{0ex}%
  \def~{-}%
  \def\@justpar{F}%
  \def\@justperiod{F}%
  \def\@justspace{F}%
  \protected@edef\save@arg{#1}%
  \expandafter\xcensor@Block\save@arg\stringend%
  \let~\sv@tilde%
 }
\long\def\blackout#1{%
  \def~{-}%
  \protected@edef\save@arg{#1}%
  \expandafter\censor@Block\save@arg\stringend\let~\sv@tilde}
\newcommand\singlelipsum[1]{%
  \begingroup\let\lips@par\relax\csname lipsum@\@roman{#1}\endcsname
\endgroup }
\let\sv@cenword\@cenword
\newcommand\m@cenword[1]{\ThisStyle{%
  \stackengine{\mcensorruledepth}{$\SavedStyle#1$}%
    {\rule{\widthof{$\SavedStyle#1$}}{\the\censorruleheight}}{U}{c}{F}{T}{L}}}
\newcommand\mblackout[2][\dp\strutbox]{%
  \let\@cenword\m@cenword%
  \def\mcensorruledepth{#1}%
  \blackout{{#2}}%
  \let\@cenword\sv@cenword%
}
\makeatother
\periodrlap=1ex
\afterperiodlap=.4ex
\lletterlap=.0ex
\rletterlap=.6ex
\afterspacelap=.6ex
\begin{document}
\blackout{\singlelipsum{4}}

{\raggedright\xblackout{\singlelipsum{4}}}

\[ \mblackout{y = A x^2} + Bx + \mblackout{C} \]

\[ \mblackout[3ex]{y = \frac{a^3 + b^2 + c}{d_3}}\]

\blackout{\singlelipsum{4}}
\end{document}

If space is desired between words, \blackout works real nice.

enter image description here

If you want the spaces to be underlined, use \xblackout. With my selection of the parameters to tune \xblackout, the underline extends slightly into both margins. Also, I am using \raggedright here, because stretching glue can make gaps form in the underline.

enter image description here

For math mode, the approach is slightly different. First difference is that it cannot make a gap for descenders (because I don't know how to convert a length variable into mu's). So, as a result, I place, by default, the math underline (named \mblackout, keeping with the censor syntax) at the depth of the \strutbox. However, for math that drops below this depth, it takes an optional argument of how far below the baseline to do the underline.

Thus,

\[ \mblackout{y = A x^2} + Bx + \mblackout{C} \]

\[ \mblackout[3ex]{y = \frac{a^3 + b^2 + c}{d_3}}\]

gives the following:

enter image description here

If you are afraid the underline might be confused for math division, you could always thicken it up with a change in \censorruleheight.

Related Question