2

I wish to have a dedicated command for printing physical dimension. Something like \phydimen{M2L-3T-1}. This should output the same as $\textrm{M}^2\textrm{L}^{-3}\textrm{T}^{-1}$.

I find that the \ce command of mhchem package is quite suitable. So I hack it to do \newcommand{\phydimen}[1]{\ce{#1}} and then issue a command \phydimen{ML^2T^{-2}} to print the dimension. However I still have to use the pesky ^ and { }. The default \ce behavior is to push the numbers as subscript.

I want \phydimen to automatically detect when a (positive or negative) integer is in the argument and push it to "power". Also \phydimen should be able to accept more characters than M,L,T. Also if lowercase is supplied, it should automatically convert it to uppercase.

How do I parse the arguments character by character and decide whether it is a letter or positive integer or negative integer?

MWE:

\documentclass{article}
\usepackage{mhchem}

\newcommand{\phydimen}[1]{\ce{#1}}
\begin{document}
    $\textrm{M}^2\textrm{L}^{-3}\textrm{T}^{-1}$ 

    \phydimen{ML^2T^{-2}} % instead I want \phydimen{ML2T-2}
\end{document}
2

You can use regular expressions:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\phydimen}{m}
 {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \regex_replace_all:nnN { (\-?\d+) } { \cU\^\cB\{\1\cE\} } \l_tmpa_tl
  \ensuremath { \mathrm { \tl_use:N \l_tmpa_tl } }
 }

\ExplSyntaxOff

\begin{document}

\phydimen{ML2T-2}

\end{document}

The search expression matches a possibly signed integer, the replacement expression specifies “superscript character, left brace, the match, right brace”.

enter image description here

  • Thanks a lot. This is exactly what I wanted. After @mhchem's comment, I was digging regex manipulation of l3regex to figure out. – magguu Feb 16 '18 at 11:58
2

Here I use listofitems to conduct a 2-tier parsing, looking for digits at the first level and for the negative sign at the second level.

\documentclass{article}
\usepackage{listofitems}
\newcommand\phydimen[1]{%
  \setsepchar{0||1||2||3||4||5||6||7||8||9/-}%
  \greadlist\Dim{#1}%
  \foreachitem\i\in\Dim{%
    \textrm{\Dim[\icnt,1]}\ensuremath{^{\Dimsep[\icnt,1]\Dimsep[\icnt]}}}%
}
\begin{document}
\phydimen{ML2T-2}
\end{document}

enter image description here

1

Parsing letter by letter is a complicated thing in LaTeX. You could open mhchem.sty and look how this is done. Or see Basics of parsing or How can I parse the first word in a token stream, token by token?.

I would not recommend using \ce inside your command. It does way more stuff than just changing the font. It would double-parse the input, I think this will not be efficient.

The command you want to create already exists within mhchem for MathJax. Why it does not exist for LaTeX is explained in the question How to use `MathJax mhchem \pu{}` command in LaTex?, including reasons to use another command instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.