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'm trying to create a LaTeX3 command that works the same whether its argument comes before or after the command. For example, I'd like to define \squared to be used as either \m\squared or \squared\m where \m is defined as \mathrm{m}. Both should yield $\mathrm{m}^2$. Here's the markup I've been working with.

\documentclass[10pt]{article}
\usepackage{xparse}

\newcommand*{\unit}[2]{\ensuremath{#1\;#2}}
\newcommand*{\metre}{\ensuremath{\mathrm{m}}}
\newcommand*{\m}{\metre}

\DeclareDocumentCommand \square { m } {%

  \IfNoValueTF #1 {%
    $^2$
  }{%
    $#1^2$
  }%
}%

\begin{document}

The command used as a prefix gives \square\m.

The command used as a postfix gives \m\square\ .

\end{document}

The first example typesets correctly except for a line break that I can't explain, but the second example also has a line break between the \m and the exponent. I tried making the argument optional but that didn't work either.

It's okay if the construct I have in mind isn't possible since I can make slightly different commands for use before and after the argument.

share|improve this question
    
The line break is caused by the empty line in the definition, which produces a \par at each call of \square. I don't think it's a good idea to have such a behavior of \square; surely the way you're trying will not work: a macro with an m argument will always find one and \IfNoValueTF{#1} will follow the true branch in all cases. Also I can't understand why trying to reinvent the wheel: \si{m^2} is available with siunitx and is definitely clearer. –  egreg Dec 27 '12 at 23:59
    
I know it's weird, but I want to create a command that works the way one thinks when writing, which is not the way LaTeX is designed. For my purposes, siunitx isn't appropriate. Besides, reinventing the wheel can only lead to a better wheel. There are needs that haven't been considered anywhere else yet. If it's not possible then so be it. –  user19024 Dec 28 '12 at 0:07
    
I completely disagree. –  egreg Dec 28 '12 at 0:09
    
You can use g instead of m, then you can use \square{\m} and \m\square. You will also need to add % after $. –  Qrrbrbirlbel Dec 28 '12 at 1:17
3  
Not an answer to the question, but do note that I've written three entirely independent unit processors for siunitx to get one that will cover all of the cases correctly! Also, using units at the document level leads to some issues with naming (for example \square is used for math symbols, as is \bar). –  Joseph Wright Dec 28 '12 at 9:17

1 Answer 1

up vote 9 down vote accepted

In general, TeX does not allow use to 'look before' a command, only to 'look after' (exceptions are primitives such as \over and LuaTeX callbacks to alter the flow of processing). As such, the only way to deal with both cases is to make them 'aware' of what follows. Thus one could for example do

\documentclass{article}
\newcommand*{\metre}{%
  \ensuremath{\mathrm{m}}%
}
\newcommand*{\m}{\metre}
\makeatletter
\newcommand*{\square}{%
  \@ifnextchar\metre
    {\square@aux}
    {%
      \@ifnextchar\m
        {\square@aux}
        {\ensuremath{^{2}}}%
    }%
}
\newcommand{\square@aux}[1]{%
  \ensuremath{#1^{2}}%
}
\begin{document}
The command used as a prefix gives \square\m.

The command used as a postfix gives \m\square.
\end{document}

which looks ahead at the token following \square and makes a choice accordingly. You can see that this would get unwieldy for a long list of units: one possible way around that would be to use a 'marker token' at the start of each unit, do a partial expansion and then check for that token. That might look like

\documentclass{article}
\usepackage{pdftexcmds}
\makeatletter
\let\joeh@unit@marker\relax
\newcommand*{\metre}{%
  \joeh@unit@marker
  \@firstofone{\ensuremath{\mathrm{m}}}% \@firstofone needed to remove "{" and "}"
}
\newcommand*{\m}{\metre}
\newcommand*{\square}{%
  \expandafter\square@aux@i
  \romannumeral-`0%
}
\newcommand{\square@aux@i}{%
  \@ifnextchar\joeh@unit@marker % Tests by meaning
    {\square@aux@ii}
    {\ensuremath{^{2}}}%
}
\newcommand{\square@aux@ii}[1]{%
  \ifnum\pdf@strcmp{\unexpanded{#1}}{\unexpanded{\joeh@unit@marker}}=\z@
    \expandafter\square@aux@iii
  \else
    \expandafter\square@aux@iv
  \fi
    {#1}%
}
\newcommand{\square@aux@iii}[3]{%
  % #1 = \joeh@unit@marker
  % #2 = \@firstofone
  % #3 = Unit code
  \ensuremath{#3^{2}}%
}
\newcommand{\square@aux@iv}[1]{%
  #1%
  \ensuremath{^{2}}%
}
\begin{document}
The command used as a prefix gives \square\m.

The command used as a postfix gives \m\square.
\end{document}

You'll see this gets a bit tricky, particularly to cover many cases.

The bigger problem comes when you get to more complex units. For example, what would

\m\square\kg

actually mean? Getting the spacing and meaning right in more complex cases is what siunitx aims to do, and one part of that is differentiating between 'power to add to the next unit' and 'power to add to the previous unit'.

share|improve this answer
    
Thanks for the meaningful answer. You're correct about the ambiguity of \m\square\kg and I had not considered that issue. Now, the package I've developed (which I hope to release onto CTAN later this weekend) was begun about three years ago, long before I knew of siunitx. I began with SIunits and its syntax is so natural and intuitive. I use it mainly for predefined unit names and the \unit{}{} command. It would be VERY difficult to migrate to siunitx at this point, so I'm considering writing my own unit name support. –  user19024 Dec 29 '12 at 2:57
    
@JoeH AS I say, one problem with what in siunitx I call 'free standing units' is the names. 'Short' names (\m, \s, etc.) are very likely to clash with other possible 'shortcuts', while \bar and \square are definitely issues the moment there is any serious mathematics in a document. –  Joseph Wright Dec 29 '12 at 8:23
    
@JoeH At something of a tangent, I'm slightly abotu the 'natural' nature of the SIunits syntax: one of the reasons I wrote siunitx was that the \usk business is a pain. –  Joseph Wright Dec 29 '12 at 8:25

Your Answer

 
discard

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