Parsing Cancel Variants In Siunitx As Non-Standard Symbolic Units
Hey guys! Have you ever run into issues when using the \cancel
command from the cancel
package with siunitx
? It turns out that variants like \bcancel
and \xcancel
can sometimes mess with the per-mode settings, leading to some unexpected behavior. In this article, we'll dive deep into this problem, explore a cool workaround, and discuss why it would be awesome if this fix could be integrated directly into siunitx
. Let's get started!
The Problem: \bcancel
and \xcancel
Forcing Literal Mode
So, here's the deal. When you're working with units in LaTeX, the siunitx
package is a total lifesaver. It helps you format units consistently and correctly. But, as pointed out in this TeX.SE post, things can get a bit tricky when you introduce \bcancel
and \xcancel
from the cancel
package. These variants of \cancel
have a sneaky habit of forcing literal mode, which can throw off your carefully crafted unit formatting, especially when using per-mode=power
. It's like inviting a guest to a party who suddenly changes the dress code – not cool!
To understand this better, let's break it down. The siunitx
package has different modes for handling fractions and units, and the per-mode
setting lets you control how these are displayed. For example, per-mode=power
will render units like meters per second squared as m/s², which is super neat and tidy. However, when \bcancel
or \xcancel
steps into the picture, they can override this setting, causing your units to appear in a less desirable format. This is because these commands, by default, might not play nicely with siunitx
's parsing mechanism, leading to the literal interpretation of the unit expression rather than the intended symbolic representation.
This issue arises because siunitx
needs to understand how to interpret these cancellation commands within its unit parsing system. Without specific instructions, siunitx
might not recognize \bcancel
and \xcancel
as symbolic units that should be handled according to the defined per-mode
. Instead, it might treat them as literal text, disrupting the formatting process. This is where the workaround comes in, providing a way to teach siunitx
how to correctly process these commands.
The Workaround: Parsing \bcancel
and \xcancel
Fear not, fellow LaTeX enthusiasts! There's a clever workaround to this issue. The key is to make siunitx
recognize \bcancel
and \xcancel
as symbolic units, just like it does with the original \cancel
command. This involves leveraging siunitx
's internal control sequences, specifically \__siunitx_set_symbolic:Npnn
. This powerful tool allows us to define how siunitx
should interpret these commands within its unit parsing system. By properly setting up these definitions, we ensure that \bcancel
and \xcancel
are treated as part of the unit expression, respecting the per-mode
setting and maintaining consistent formatting.
The magic happens in the following code snippet:
\documentclass{article}
\usepackage{siunitx,cancel}
\ExplSyntaxOn
\__siunitx_unit_set_symbolic:Nnn \bcancel
{ }
{ \__siunitx_unit_parse_special:n { \bcancel } }
\__siunitx_unit_set_symbolic:Nnn \xcancel
{ }
{ \__siunitx_unit_parse_special:n { \xcancel } }
\AtBeginDocument {
\cs_if_exist:NT \bcancel
{
\cs_set_protected:Npn \__siunitx_vcancel:n #1
{ \__siunitx__real_bcancel:n { \__siunitx_print:nn { unit } {#1} } }
\cs_set_eq:NN \__siunitx__real_bcancel:n \bcancel
\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \bcancel }
\cs_new_protected:cpn
{ __siunitx_ \token_to_str:N \bcancel _function:w }
{ \__siunitx_unit_parse_special:n { \__siunitx_bcancel:n } }
}
\cs_if_exist:NT \xcancel
{
\cs_set_protected:Npn \__siunitx_xcancel:n #1
{ \__siunitx__real_xcancel:n { \__siunitx_print:nn { unit } {#1} } }
\cs_set_eq:NN \__siunitx__real_xcancel:n \xcancel
\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \xcancel }
\cs_new_protected:cpn
{ __siunitx_ \token_to_str:N \xcancel _function:w }
{ \__siunitx_unit_parse_special:n { \__siunitx_xcancel:n } }
}
}
\ExplSyntaxOff
\begin{document}
${
\qty[per-mode=power]{2}{\cancel\metre\per\second}
}$
${
\qty[per-mode=power]{2}{\bcancel\metre\per\second}
}$
${
\qty[per-mode=power]{2}{\xcancel\metre\per\second}
}$
\end{document}
Let's break down what's happening here:
-
Load Packages: We start by loading the necessary packages,
siunitx
andcancel
. These are the building blocks for our unit formatting and cancellation magic. -
Enter the
expl3
Zone: We dive into theexpl3
syntax, which issiunitx
's internal language. This gives us access to powerful tools for manipulating TeX's inner workings. -
Define Symbolic Units: The core of the workaround lies in these lines:
\__siunitx_unit_set_symbolic:Nnn \bcancel { } { \__siunitx_unit_parse_special:n { \bcancel } } \__siunitx_unit_set_symbolic:Nnn \xcancel { } { \__siunitx_unit_parse_special:n { \xcancel } }
Here, we're using
\__siunitx_unit_set_symbolic:Nnn
to tellsiunitx
that\bcancel
and\xcancel
should be treated as symbolic units. This means they'll be parsed and handled according tosiunitx
's rules, including respecting theper-mode
setting. The{ }
indicates that we're not adding any prefix or postfix behavior, and\__siunitx_unit_parse_special:n
ensures that the commands are processed in a special way that preserves their intended effect within the unit. -
Handle at the Beginning of the Document: The
\AtBeginDocument
block ensures that the following code is executed right before the document content starts. This is crucial for setting up the cancellation commands correctly. -
Check for Existence: We use
\cs_if_exist:NT
to check if\bcancel
and\xcancel
are actually defined. This is a safety measure, as thecancel
package might not always be loaded. -
Define Internal Commands: Inside the conditional blocks, we define some internal commands to handle the cancellation. For
\bcancel
, this looks like:\cs_set_protected:Npn \__siunitx_vcancel:n #1 { \__siunitx__real_bcancel:n { \__siunitx_print:nn { unit } {#1} } } \cs_set_eq:NN \__siunitx__real_bcancel:n \bcancel \seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \bcancel } \cs_new_protected:cpn { __siunitx_ \token_to_str:N \bcancel _function:w } { \__siunitx_unit_parse_special:n { \__siunitx_bcancel:n } }
\__siunitx_vcancel:n
is a protected command that wraps the actual\bcancel
command (\__siunitx__real_bcancel:n
) and ensures that the unit is properly printed using\__siunitx_print:nn
. This is key to maintainingsiunitx
's formatting.\cs_set_eq:NN \__siunitx__real_bcancel:n \bcancel
creates an alias for the original\bcancel
command, allowing us to use it within thesiunitx
context.\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \bcancel }
adds\bcancel
to the list of symbolic units thatsiunitx
knows about.- The final
\cs_new_protected:cpn
line creates a parsing function specifically for\bcancel
. This function, named\__siunitx_bcancel_function:w
, uses\__siunitx_unit_parse_special:n
to handle the command in a way that respectssiunitx
's unit parsing rules.
The code for
\xcancel
follows a similar pattern. -
Showcase the Solution: Finally, we demonstrate the workaround with a few examples:
${ \qty[per-mode=power]{2}{\cancel\metre\per\second} }$ ${ \qty[per-mode=power]{2}{\bcancel\metre\per\second} }$ ${ \qty[per-mode=power]{2}{\xcancel\metre\per\second} }$
These examples show how
\cancel
,\bcancel
, and\xcancel
now work correctly withper-mode=power
, producing the desired output.
The result is beautiful, consistently formatted units, even with the cancellation commands in the mix! Check out the output:
Why This Should Be in siunitx
This workaround is great, but wouldn't it be even better if this functionality was built directly into siunitx
? Here’s why:
- Seamless Integration: Having native support for
\bcancel
and\xcancel
would make the package more user-friendly. No more hunting for workarounds or worrying about compatibility issues. It would just work, straight out of the box. This ease of use is crucial for maintaining a smooth workflow, especially for users who are not deeply familiar with the intricacies of LaTeX package interactions. - Maintainability: Including this in
siunitx
would ensure that the parsing of these commands is maintained and updated as the package evolves. This is important for long-term stability, as changes to eithersiunitx
or thecancel
package could potentially break the workaround. By integrating the fix directly, thesiunitx
developers can ensure that it remains functional and consistent across updates. - Consistency: Consistency is key in LaTeX, especially when dealing with units. By handling
\bcancel
and\xcancel
in the same way as\cancel
,siunitx
can provide a more uniform experience. This avoids unexpected formatting quirks and ensures that documents look professional and polished. Consistency in formatting also makes documents easier to read and understand, as users can rely on a predictable visual style. - Accessibility: For users who rely on these cancellation commands in their mathematical notation, having native support in
siunitx
would greatly improve accessibility. It means they can use these commands without having to worry about compatibility issues or implementing custom fixes. This inclusivity is an important consideration for any widely used LaTeX package.
By incorporating this functionality, siunitx
would become even more robust and versatile, solidifying its position as the go-to package for handling units in LaTeX. It would also save users time and effort, allowing them to focus on the content of their documents rather than the technical details of formatting.
Conclusion
So, there you have it! We've tackled the issue of \bcancel
and \xcancel
messing with siunitx
's per-mode, implemented a solid workaround, and made a case for why this fix deserves a permanent home in the siunitx
package. It's all about making LaTeX easier and more consistent for everyone. Let's hope Joseph Wright and the siunitx
team consider adding this to the official release. Keep those units formatting clean, guys! By addressing these compatibility issues, we contribute to a more seamless and efficient LaTeX experience for all users, reinforcing the importance of community-driven improvements in the world of scientific document preparation. This collaborative approach ensures that LaTeX remains a powerful and versatile tool for academics, researchers, and professionals alike.