6

I've developed a package in which I want to define a command \power, but that name is taken by a command in the SIunits package (which my package uses). I initially named my command \powr but decided to try renaming the \power command in SIunits and use \power in my own package. The problem is that I've apparently missed something or done something incorrect because I can't get the intended result.

(Note that I don't want to use siunitx over SIunits at present, although I will migrate to it in the future.)

Here is a MWE which does NOT included all the packages my own package uses. My major problem is that \square doesn't work as after renaming \power and I simply don't understand why. \sisquare doesn't work either but I don't use it. What am I missing?

\documentclass{article}
\usepackage{letltxmacro}
\usepackage{SIunits}

\newcommand*{\m}{\ensuremath{\mathrm{m}}

\LetLtxMacro{\sipower}{\power}
\renewcommand{\power}[1]{\ensuremath{#1 \; \mathrm{J/s}}}

\LetLtxMacro{\sisquare}{\square}
\renewcommand*{\square}[1]{\mathrm{#1}^{2}}

\renewcommand*{\squared}{\ensuremath{^{\mathrm{2}}}}
\renewcommand*{\cubic}[1]{\sipower{#1}{3}}
\renewcommand*{\cubed}{\ensuremath{^{\mathrm{3}}}}
\renewcommand*{\fourth}[1]{\sipower{#1}{4}}
\renewcommand*{\reciprocal}[1]{\sipower{#1}{\SIminus1}}
\renewcommand*{\rp}{\ensuremath{^{\mathrm{\SIminus1}}}}
\renewcommand*{\rpsquare}[1]{\sipower{#1}{\SIminus2}}
\renewcommand*{\rpsquared}{\ensuremath{^{\mathrm{\SIminus2}}}}
\renewcommand*{\rpcubic}[1]{\sipower{#1}{\SIminus3}}
\renewcommand*{\rpcubed}{\ensuremath{^{\mathrm{\SIminus3}}}}
\renewcommand*{\rpfourth}[1]{\sipower{#1}{\SIminus4}}

\begin{document}

\sipower{\m}{2} \par
\power{3}       \par
$\sisquare\m$   \par
\square\m       \par
\m\squared      \par
\cubic\m        \par
\m\cubed        \par
\fourth\m       \par
\reciprocal\m   \par
\m\rp           \par
\rpsquare\m     \par
\m\rpsquared    \par
\rpcubic\m      \par
\m\rpcubed      \par
\rpfourth\m

\end{document}
9
  • 1
    That is not a minimal working example (MWE) … though SIunits hooks into \AtBeginDocument and your re-defined macro gets re-set. You can do the same (\AtBeginDocument{\LetLtxMacro … \renewcommand* …}). If you provide a MWE and describe your goal (what macro should output what?), an answer will come soon … Commented Dec 24, 2012 at 6:04
  • 1
    @Qrrbrbirlbel Looks like the kernel of an answer: care to post one?
    – Joseph Wright
    Commented Dec 24, 2012 at 7:44
  • 1
    Well, Qrr, it was the best I could come up with given that I didn't know where to begin looking for an answer and didn't know for sure which package was causing the problem (though I suspected SIunits). I would have thought the examples make the intended output quite clear, but perhaps not. The answer is indeed to use \AtBeginDocument around my renames. I won't answer my own question so if you answer I'll accept it.
    – user19024
    Commented Dec 24, 2012 at 16:17
  • 1
    I always cut and paste examples here and compile them myself to see what happens and I, apparently erroneously, assumed others did the same. As I said above, I didn't know WHAT was causing \square to malfunction so I renamed everything that depends on \power in SIunits. I renamed \m to isolate it from SIunits because I WAS certain it wasn't the problem.
    – user19024
    Commented Dec 24, 2012 at 16:52
  • 1
    Also keep in mind that demanding a "MWE" isn't always practical if one has no idea whatsoever is causing the problem that needs to be solved. Geez sorry I ever asked.
    – user19024
    Commented Dec 24, 2012 at 16:56

1 Answer 1

4

The SIunits package uses the \AtBeginDocument hook to (re)define \square as that macro name is also used by the amssymb package for a (graphical) square.

Therefore it provides two package options that deal with this clash:

  • amssymb overwrites \square with no backup of amssymb’s original \square macro.
  • squaren provides the macro name \squaren instead and leaves \square alone.

As the user might load amssymb after SIunits this redefiniton problem is postponed until \begin{document} (after that you can’t load any packages):

%%%%%% siunits.sty, lines 75ff.
%%%%%% \typeout messages removed
%%%%%% Comments provided by me           \%/

\AtBeginDocument{%
 \ifredefsquare                           % option "amssymb": \square is overwritten
  \providecommand{\square}[1]{\power{#1}{2}}
  \renewcommand{\square}[1]{\power{#1}{2}}
 \else
   \ifdefsquaren                          % option "squaren": \squaren is defined
    \providecommand{\squaren}[1]{\power{#1}{2}}
    \renewcommand{\squaren}[1]{\power{#1}{2}}
   \else                                  % neither "amssymb" nor "squaren"
    \@ifundefined{square}{%               % if \square is undefined, define it (no amssymb)
     \newcommand*{\square}[1]{\power{#1}{2}}
     }{%                                  % if \square is defined, yell at user:
     \PackageWarningNoLine{SIunits}{%     % "Use either amssymb or squaren option"
     The command `square' was already defined.\MessageBreak
     Possibly due to the amssymb package}
    }  %\ifundefined{square}
   \fi %\ifsefsquaren
 \fi   %\ifredefsquare
 }     %\AtBeginDocument

The solution to your problem is to hook yourself into \AtBeginDocument and redefine \square there.

I also patched \sisquare as it is internally defined with \power that you also redefine (similar reasons why you need to redefine all those other macros with \sipower).

Code

\documentclass{article}
\usepackage{letltxmacro}
\usepackage{SIunits}
\newcommand*{\m}{\ensuremath{\mathrm{m}}}

\renewcommand*{\squared}{\ensuremath{^{\mathrm{2}}}}
\renewcommand*{\cubed}{\ensuremath{^{\mathrm{3}}}}
\renewcommand*{\cubic}[1]{\sipower{#1}{3}}
\renewcommand*{\fourth}[1]{\sipower{#1}{4}}

\renewcommand*{\reciprocal}[1]{\sipower{#1}{\SIminus1}}
\renewcommand*{\rpsquare}[1]{\sipower{#1}{\SIminus2}}
\renewcommand*{\rpcubic}[1]{\sipower{#1}{\SIminus3}}
\renewcommand*{\rpfourth}[1]{\sipower{#1}{\SIminus4}}

\renewcommand*{\rp}{\ensuremath{^{\mathrm{\SIminus1}}}}
\renewcommand*{\rpsquared}{\ensuremath{^{\mathrm{\SIminus2}}}}
\renewcommand*{\rpcubed}{\ensuremath{^{\mathrm{\SIminus3}}}}

\LetLtxMacro{\sipower}{\power}%
\renewcommand*{\power}[1]{\ensuremath{#1 \; \mathrm{J/s}}}%

\AtBeginDocument{%
    \LetLtxMacro{\sisquare}{\square}%
    \renewcommand*{\square}[1]{\mathrm{#1}^{2}}%
    \renewcommand*{\sisquare}[1]{\sipower{#1}{2}}% to correct the output of the original square, now sisquare, command
}

\begin{document}
\sipower{\m}{5} \par
$\sisquare\m$   \par
\power{120}     \par
$\square\m$     \par\bigskip

\m\squared      \par
\cubic\m        \par
\m\cubed        \par
\fourth\m       \par
\reciprocal\m   \par
\m\rp           \par
\rpsquare\m     \par
\m\rpsquared    \par
\rpcubic\m      \par
\m\rpcubed      \par
\rpfourth\m
\end{document}

Output

enter image description here

1
  • Thanks! Because I'm using SIunits in a package rather than in a standalone document, I ended up having to use \AtBeginOfPackageFile instead, but everything else works.
    – user19024
    Commented Dec 27, 2012 at 22:32

You must log in to answer this question.