josephwright / siunitx

A comprehensive (SI) units package for LaTeX
LaTeX Project Public License v1.3c
359 stars 26 forks source link

`free-standing-units=false` still defines macros #750

Open sim642 opened 2 weeks ago

sim642 commented 2 weeks ago

When upgrading from TeXLive 2021 to 2024, I spent hours debugging an LaTeX Error: Command \C already defined.. Turns out this is reproducible with:

\documentclass{standalone}

\usepackage[free-standing-units=false]{siunitx}

\begin{document}

    \newcommand{\C}{\mathcal{C}}
    foo

\end{document}

Apparently this package defines the macros even when explicitly disabling free-standing-units. However, the documentation claims that it doesn't: https://github.com/josephwright/siunitx/blob/549cad913591b92a3a199b7477a325866303bf29/siunitx.tex#L2459-L2460

It's quite annoying if new (single-letter!) macros are defined even if the user tries to shield themselves against it by disabling free-standing-units.

josephwright commented 2 weeks ago

I will tighten up the docs here.

The free-standing-units option is about whether something like \metre is set up to 'work' outside the scope of the unit argument to \unit, \qty, etc.: it is off as-standard as I don't think it's a great input syntax.

However, that doesn't affect the need to have the document commands defined for everything - there are technical reasons. So what happens is siunitx checks at the start of a document if the unit commands exist - and if they don't creates holders - which error if used out-of-context.

If your example, you are defining a document command after the preamble, which is what catches siunitx out. In a well-structured LaTeX document, all of the document commands should be created before the document starts - they after all define the document. So you can fix with a simple move of your document command to the preamble.

(There's been no change in the approach - it's only that v2 didn't have an abbreviation for \degreeCelsius. You'd have had an error in v2 if you'd tried to define for example \metre.)

sim642 commented 2 weeks ago

However, that doesn't affect the need to have the document commands defined for everything - there are technical reasons.

What's the reason? I would think that they could be defined in a local group just in \unit and \qty. This comment from the issue that introduced \C also sounded like it would defined only in such group, but maybe I misunderstood.

If your example, you are defining a document command after the preamble, which is what catches siunitx out. In a well-structured LaTeX document, all of the document commands should be created before the document starts - they after all define the document. So you can fix with a simple move of your document command to the preamble.

I also noticed that difference, but it's not possible/desirable to always do that. For example, I use subfiles to heavily modularize a large document (but the same applies to all environment-local macros) and only define convenient single-letter macros in small scopes instead of polluting the global namespace.

josephwright commented 2 weeks ago

However, that doesn't affect the need to have the document commands defined for everything - there are technical reasons.

What's the reason? I would think that they could be defined in a local group just in \unit and \qty. This comment from the issue that introduced \C also sounded like it would defined only in such group, but maybe I misunderstood.

In expansion contexts, a non-defined unit command would lead to a undefined control sequence error. One cannot arrange that \qty, etc., are always 'in control' in such contexts, thus it's a requirement that there is some non-error definition in these places.

If your example, you are defining a document command after the preamble, which is what catches siunitx out. In a well-structured LaTeX document, all of the document commands should be created before the document starts - they after all define the document. So you can fix with a simple move of your document command to the preamble.

I also noticed that difference, but it's not possible/desirable to always do that. For example, I use subfiles to heavily modularize a large document (but the same applies to all environment-local macros) and only define convenient single-letter macros in small scopes instead of polluting the global namespace.

LaTeX documents should always have commands defined in global scope even if they are locally modified - as document commands define LaTeX.

josephwright commented 4 days ago

I will tighten the docs here for the next release