# Save and reapply math class after boxing

Is there an easy way to capture the math class (\mathord, \mathrel, …) before boxing a term and then reapply it to the box when using it?

In the following example I’d like to have the same spacing in both equations.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{ \highlight }{ m }{
\hbox_set:Nn \l_tmpa_box { #1 }
\box_use:N \l_tmpa_box
}

\ExplSyntaxOff

\begin{document}
$a + b$

$a \highlight{+} b$
\end{document}


I know that bm.sty knows a trick (see also David’s answer on Non-invasive replacement for \fbox?) to do it but I didn’t get how it works and could figure out how to transfer it to my code.

Note: I know that my example is kind of wrong as a box doesn’t allow math content and it only works because + can also be in text mode (\int e.g. would fail here). In my real code if have a test for the correct mode and also math style while saving the box, but I omitted it here to keep the example as short as possible. I’m just looking for a solution to capture the class and apply it like \mathCLASS { \box_use:N \l_tmpa_box }.

Background: I need this for the following: The \highlight should color it’s content but as I use a light font, for the highlight three should also be a bolder font choosen. To make it non-invasive I used something like

\NewDocumentCommand{ \highlight }{ m }{
\begingroup
\color { red }
\bfseries
#1
\endgroup
}


but this won't work for math as \bfseries is forbidden in math mode. There is \boldmath but it can’t be applied for only a part of an equation so I cam up with code like this

\NewDocumentCommand{ \highlight }{ m }{
\tobi_set_text_or_math_hbox:Nnn \l_tmpa_box { \color { red } \bfseries \boldmath } { #1 }
\box_use:N \l_tmpa_box
}


Where \tobi_set_text_or_math_hbox cares for setting the box content in the right font and mode and also applies the right math style if necessary. But then the spacing in math mode doesn’t work anymore so I’m searching for a way to add the correct \mathord, \mathrel etc.

These are the definitions of my math style saving (requires LuaTeX) and boxing macros:

\cs_new_eq:NN \tobi_saved_math_style: \textstyle
\cs_new:Npn \tobi_save_math_style: {
\int_case:nn { \mathstyle } {
{ \displaystyle } { \cs_set_eq:NN \tobi_saved_math_style: \displaystyle }
{ \textstyle } { \cs_set_eq:NN \tobi_saved_math_style: \textstyle }
{ \scriptstyle } { \cs_set_eq:NN \tobi_saved_math_style: \scriptstyle }
{ \scriptscriptstyle } { \cs_set_eq:NN \tobi_saved_math_style: \scriptscriptstyle }
}
}

% #1 = box register
% #2 = font macros (always outside math mode)
% #3 = box content
\cs_new:Npn \tobi_set_text_or_math_hbox:nnn #1#2#3 {
\mode_if_math:TF {
\tobi_save_math_style:
\hbox_gset:Nn #1 {
#2
$$\m@th \tobi_saved_math_style: #3$$
}
} {
\hbox_set:Nn #1 {
#2 #3
}
}
}

• a box can not hold a math list, you avoided an error in your example as + is also allowed in text mode but it comes from the text font not the math font and has text (no) spacing. Perhaps you just want { $#1$ } in the definition but hard to be sure of the exact spec that you expected. – David Carlisle May 15 '17 at 21:16
• @DavidCarlisle: I omitted the whole part testing for math mode/style for boxing to keep the code as short as possible. I’m only looking for a way to add the correct \mathXX{ \box_use:N \l_tmpa_box } – Tobi May 15 '17 at 21:21
• in general a math expression doesn't have a math class, your syntax would suggest \highlight {a+b} and a+b doesn't have a class. If your syntax just took a single symbol it would perhaps have a clearer answer. also where do you want to store the class (you can't store it in the box (not really). so you would have to store it in some macro and then access it by some wrapper for \usebox that retrieved the box and the saved class in a macro associated with each saved box – David Carlisle May 15 '17 at 21:26
• @DavidCarlisle: Pleas see my edit :-) – Tobi May 15 '17 at 21:38
• why not just \textcolor{red}{\bm{#1}} why box at all? – David Carlisle May 15 '17 at 21:42

This is what I came up with: Do a simple test what the box contains and then apply the correct math class. The test will certainly not always give the correct/desired result and therefore \highlight has an optional argument to manually set the class.

% !TeX program = lualatex
\documentclass[11pt]{scrartcl}

\usepackage{xparse}
\usepackage{amsmath}
\usepackage{xcolor}
\usepackage{tikz}

\ExplSyntaxOn\makeatletter

\cs_new_eq:NN \tobi_saved_math_style: \textstyle
\cs_new:Npn \tobi_save_math_style: {
\int_case:nn { \mathstyle } {
{ \displaystyle } { \cs_set_eq:NN \tobi_saved_math_style: \displaystyle }
{ \textstyle } { \cs_set_eq:NN \tobi_saved_math_style: \textstyle }
{ \scriptstyle } { \cs_set_eq:NN \tobi_saved_math_style: \scriptstyle }
{ \scriptscriptstyle } { \cs_set_eq:NN \tobi_saved_math_style: \scriptscriptstyle }
}
}

% - #1: Box register
% - #2: font switches (always outside math)
% - #3: box content
\cs_new:Npn \tobi_set_text_or_math_hbox:nnn #1#2#3 {
\mode_if_math:TF {
\tobi_save_math_style:
\hbox_gset:Nn #1 {
#2
$$\m@th \tobi_saved_math_style: #3$$
}
} {
\hbox_set:Nn #1 {
#2 #3
}
}
}
\cs_generate_variant:Nn \tobi_set_text_or_math_hbox:nnn { Nnn, NNN, NnN, NNn }

\tikzset {
highlight~node/.style = {
fill = yellow,
inner~sep = \z@,
},
}

\tl_new:N \tobi_current_math_class_tl
\tl_set:Nn \tobi_current_math_class_tl { ord }

\cs_generate_variant:Nn \tl_if_in:NnT { Nf }
\cs_generate_variant:Nn \tl_if_in:NnF { Nf }
\cs_generate_variant:Nn \tl_if_in:NnTF { Nf }

\tl_const:Nx \c_tobi_math_rel_symbols_tl { \tl_to_str:n { = < > \neq } }
\tl_const:Nx \c_tobi_math_bin_symbols_tl { \tl_to_str:n { + - \cdot \times } }
\tl_const:Nx \c_tobi_math_open_symbols_tl { \tl_to_str:n { ( [ \{ } }
\tl_const:Nx \c_tobi_math_close_symbols_tl { \tl_to_str:n { ) ] \} } }
\tl_const:Nx \c_tobi_math_operator_symbols_tl { \tl_to_str:n { \int \sum \prod } }

% - #1: content (text or math)
% - #2 (optional): manual math class = rel|op|bin|ord|close|open
\NewDocumentCommand{ \highlight }{ m o }{
\tobi_set_text_or_math_hbox:Nnn \l_tmpa_box { \color { red } \bfseries \boldmath } { #1 }
\tl_set:Nn \tobi_current_math_class_tl { ord }
\IfNoValueTF { #2 } {
\tl_if_in:NfTF \c_tobi_math_rel_symbols_tl { \tl_to_str:n { #1 } } {
\tl_set:Nn \tobi_current_math_class_tl { rel }
} {
\tl_if_in:NfTF \c_tobi_math_bin_symbols_tl { \tl_to_str:n { #1 } } {
\tl_set:Nn \tobi_current_math_class_tl { bin }
} {
\tl_if_in:NfTF \c_tobi_math_open_symbols_tl { \tl_to_str:n { #1 } } {
\tl_set:Nn \tobi_current_math_class_tl { open }
} {
\tl_if_in:NfTF \c_tobi_math_close_symbols_tl { \tl_to_str:n { #1 } } {
\tl_set:Nn \tobi_current_math_class_tl { close }
} {
\tl_if_in:NfT \c_tobi_math_operator_symbols_tl { \tl_to_str:n { #1 } } {
\tl_set:Nn \tobi_current_math_class_tl { operator }
}
}
}
}
}
} {
\tl_set:Nn \tobi_current_math_class_tl { #2 }
}
\begin{tikzpicture} [ baseline = (N.base) ]
\node [ highlight~node ] (N) {
\box_use:N \l_tmpa_box
%            \textsubscript{\tobi_current_math_class_tl}
};
\end{tikzpicture}
}
}

\mode_if_math:TF {
\use:c { math #1 } { #2 }
} {
#2
}
}

\ExplSyntaxOff\makeatother

\begin{document}

%\tl_const:Nx \c_tobi_math_rel_symbols_tl { \tl_to_str:n { = < > \neq } }
$\highlight{=}$
$\highlight{<}$
$\highlight{>}$
$\highlight{\neq}$

%\tl_const:Nx \c_tobi_math_bin_symbols_tl { \tl_to_str:n { + - \cdot \times } }
$\highlight{+}$
$\highlight{-}$
$\highlight{\cdot}$
$\highlight{\times}$

%\tl_const:Nx \c_tobi_math_open_symbols_tl { \tl_to_str:n { ( [ \{ } }
$\highlight{(}$
$\highlight{[}$
$\highlight{\{}$

%\tl_const:Nx \c_tobi_math_close_symbols_tl { \tl_to_str:n { ) ] \} } }
$\highlight{)}$
$\highlight{]}$
$\highlight{\}}$

%\tl_const:Nx \c_tobi_math_operator_symbols_tl { \tl_to_str:n { \int \sum \prod } }
$\highlight{\int}$
$\highlight{\sum}$
$\highlight{\prod}$

$\highlight{a+b}$

$\highlight{=}[ord]$

Text \highlight{highlighted} Text

$\highlight{-}3 m\highlight{2a}th \highlight{+} math = \highlight{\int}_0^5 math \, \highlight{\mathrm{d}x}$
$-3 m2ath + math = \int_0^5 math \, \mathrm{d}x$

\end{document}


It turns out that this works on operators and variables.

\documentclass{article}
\usepackage{xcolor}
\usepackage{mathtools}

\newcommand\highlight[1]% #1 = math
{\mathmbox{\color{red}{}#1{}}}

\begin{document}
$a + b c d$

$a \highlight{+} b \highlight{c} d$
\end{document}


• But this doesn’t help much, as the content of \highlight isn’t always and operator and I don’t want to input the formulas twice always … – Tobi May 16 '17 at 14:28
• It hit me that all you really needed was a \mathmbox and something for an operator to "push against". – John Kormylo May 16 '17 at 19:42
• sorry … what do you mean? – Tobi May 16 '17 at 19:43
• It's like starting or ending a line with \hfill. Nothing happens unless you add a \null first (or last). It actually has to do with all the extra space getting absorbed, but I like to think of it as having something to push against. – John Kormylo May 16 '17 at 19:52
• Using the extra braces before and after is a nice idea, but it’ll fail in cases like \highlight{-}3 + 3, i.e. where the minus is a sign an not an operator … – Tobi May 17 '17 at 17:00