Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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}
share|improve this question
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 … –  Qrrbrbirlbel Dec 24 '12 at 6:04
1  
@Qrrbrbirlbel Looks like the kernel of an answer: care to post one? –  Joseph Wright Dec 24 '12 at 7:44
    
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 Dec 24 '12 at 16:17
1  
@JoeH I think I understand why you feel frustrated. Yes MWE might seem weird to ask for a problem that already doesn't work anyhow but consider also the procedure to obtain a MWE; if you start eliminating bit by bit the code lines then you'll end up with an MWE that reproduces the problem in 5-6 lines. So it's a good practice to locate the real offending part of the code. Hence the W in a MWE means that this is the minimal offending code (not necessarily compiling) But I can assure you that this is friendly bunch here but sometimes comments sound harsher when written down than intentions. –  percusse Dec 24 '12 at 17:12
1  
As @percusse says, a MWE here is the minimum lines which show the problem, so 'working' is perhaps slightly misleading! ('Necessary and sufficient to show the point' would be I guess accurate if wordy.) The question itself is perfectly valid, and I'll post an answer if Qrrbrbirlbel doesn't. –  Joseph Wright Dec 24 '12 at 17:23
show 4 more comments

1 Answer

up vote 4 down vote accepted

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

share|improve this answer
    
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 Dec 27 '12 at 22:32
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.