How to make \hl (highlighting) to automatically place incompatible commands in \mbox?

The soul package provides a useful command \hl for highlighting text. However, \cite, \ref, and some other commands (maybe equations too) must be placed within an \mbox in order for \hl to work properly.

Is there any way to make this automatic? Meaning that to modify \hl (and other commands provided by soul) to put everything except plain text in an \mbox?

\documentclass[12pt]{article}
\usepackage{soul}
\begin{document}

\section{1}\label{sec}
This is to show that \textbackslash{hl} fails to highlight texts containing citations or reference!

\hl{ This is one line containing a citation \mbox{\cite{}}}

\hl{ This is one line containing a reference \mbox{\ref{sec}}}

\end{document}

-
Really interesting question, but I guess a counter question is necessary: how can you tell all those commands which are incompatible? – Sean Allred Oct 18 '13 at 17:49
@Sean, good question! So far I have noticed that \cite, \ref and some inline equations are incompatible. Putting everything except a plain text in a \mbox would not be a good idea since some commands need text wrapping! For a preliminary solution, maybe defining a list of incompatible commands and automatically place them inside an \mbox (if they are used in \hl) would help! – M.Reza Oct 18 '13 at 18:02
Maybe with \soulregister\ref{7}? – Robert Oct 18 '13 at 18:59
Thanks, Yes indeed, it was quite helpful! By using \soulregister\X{7}, where X is the command name, \hl encloses that command in braces. – M.Reza Oct 18 '13 at 20:08

You can (ab)use \soulregister with the identifier 7. While this command is meant to be used to register font switching commands (with identifier 0 or 1), a look in the implementation part of the documentation reveals that it also accepts other numbers: 9 for accents, 8 for \footnote and, the one that's interesting here, 7 for "\textsuperscript or similar commands". Obviously, \cite, \ref and friends are similar enough.

When a command is registered this way, soul will first expand it (including the argument), and then feed the result as a whole to its scanner, just like \mbox would do. Note that while this is good enough for highlighting, striking out and underlining, it also means that it won't work in letterspaced text - there's no error, but no letterspacing either (which, I would guess, is probably the reason why these commands are not registered by default).

\documentclass[12pt]{article}
\usepackage{soul,color}
\soulregister\cite7
\soulregister\ref7
\soulregister\pageref7
\begin{document}
\st{This is a line containing a citation \cite{}.}

\hl{This is a line containing a reference \ref{sec} on page \pageref{sec}.}

\so{This reference: \ref{sec}, is not letterspaced.}

\setcounter{section}{122}
\section{1}\label{sec}
\end{document}


-
Thanks for the useful answer! I found out that if \xspace is defined this way, it won't function well. – M.Reza Oct 21 '13 at 10:19
I'll add for the sake of others like me who found this to work half-way: if you're using \citep or \citet, you'll need to add a line for each: \soulregister\citep7 and \soulregister\citet7. – jvriesem May 7 at 23:20
Or one can use {} like {\ref{sec}}. This doesn't require to use \souregister\ref7 command :-D – Khaaba Sep 10 at 13:22

Another option using curly braces {} around \ref, \cite or \pagerefcommands may be:

\documentclass[12pt]{article}
\usepackage{soul,color}

\begin{document}
\st{This is a line containing a citation {\cite{}}.}

\hl{This is a line containing a reference {\ref{sec}} on page {\pageref{sec}}.}

\so{This reference: {\ref{sec}}, is not letterspaced.}

\setcounter{section}{122}
\section{1}\label{sec}
\end{document}'
`
-