5

I'm trying to combine the \num and \SI command of siunitx and change the order of the arguments. In particular, what I want to achieve is a new command \Zahl[siunitx-options]<pre-unit>{number}[measure] where everything but number is optional.

The MWE below achieves my objective by copying siunitx internals, which is a bad idea. In particular, I create a new Npn "jorg" based in \SI that changes the order of the original SI command and define \Zahl accordingly. Is there a more consistent and reliable way to achieve the same?

\documentclass{scrartcl}

\usepackage{siunitx,xparse,expl3}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\ExplSyntaxOn
% Create \Zahl based on siunitx' \num and \SI
%  The syntax is then \Zahl[siunitx-options]<pre-unit>{number}[measure]
\cs_new_protected:Npn \__siunitx_jorg:nnnn #1#2#3#4 {
  \IfNoValueTF {#2}
    { \tl_clear:N \l__siunitx_pre_unit_tl }
    {
      \group_begin:
        \__siunitx_unit_in:nn {#2} {#1}
        \cs_set_eq:NN \l__siunitx_pre_unit_tl \l__siunitx_unit_tl
      \exp_args:NNNo \group_end:
      \tl_set:Nn \l__siunitx_pre_unit_tl { \l__siunitx_unit_tl }
    }
  \cs_set_eq:NN \l__siunitx_brackets_bool
    \l__siunitx_multi_brackets_bool
  \__siunitx_combined_unit:nnn {#3} {#4} {#1}
  \__siunitx_combined_output:n {#3}
}

\NewDocumentCommand\Zahl{o D<>{} m O{}}%
 {
  \leavevmode
  \group_begin:
    \IfNoValueTF {#1}
      { \__siunitx_jorg:nnnn { } {#2} {#3} {#4} }
      {
        \keys_set:nn { siunitx } {#1}
        \__siunitx_jorg:nnnn {#1} {#2} {#3} {#4}
      }
  \group_end:
}
\ExplSyntaxOff

\DeclareSIUnit\%{\char37}



\begin{document}

\Zahl{200}

\Zahl{200}[\percent]

\Zahl<£>{200}

\Zahl<£>{200}[\percent]

\Zahl[round-mode=figures,round-precision=3]<£>{200.7}[\percent]

\end{document}
Jörg
  • 7,653
  • 1
    This seems like a situation where using key values instead of optional arguments might be more user-friendly – A.Ellett Dec 05 '12 at 16:02
  • 1
    I've wondered about a keyval 'pre-unit' argument, but it's not really correct. I also suspect I should have coded the pre-unit part completely separately from the main unit as it's conceptually entirely different. – Joseph Wright Dec 05 '12 at 17:47

1 Answers1

3

You don't need to have a relay function here, as part of the point of xparse is that the code-level functions should 'just work' with the correct number of mandatory arguments.

\documentclass{article}
\usepackage{siunitx}
\ExplSyntaxOn
\NewDocumentCommand \Zahl {o D<>{} m O{}}
  {
    \leavevmode
    \group_begin:
      \IfNoValueTF {#1}
        { \__siunitx_combined:nnnn { } {#3} {#2} {#4} }
        {
          \keys_set:nn { siunitx } {#1}
          \__siunitx_combined:nnnn {#1} {#3} {#2} {#4}
        }
    \group_end:
  }
\ExplSyntaxOff
\begin{document}

\Zahl{200}

\Zahl{200}[\percent]

\Zahl<\pounds>{200}

\Zahl<\pounds>{200}[\percent]

\Zahl[round-mode=figures,round-precision=3]<\pounds>{200.7}[\percent]

\end{document}

There are a few reasons I don't particularly like this idea, from an interface point of view

  • Trailing optional arguments are not very common in LaTeX2e (certain for general use document commands)
  • I chose to separate out \num and \SI for a reason :-) (The concepts 'a number' and 'a quantity' are different.)

plus one from a coding point of view

  • There is not a proper documented code level interface for siunitx (my fault!)

However, it should work well enough. I'm not about to alter the internal interface at the moment, and if I do it will be to provide a documented code-level one.

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
  • Thanks, I forgot to ask in the main question: Is there a drawback of \DeclareSIUnit\%{\char37} and using \% instead of \percent for si-numbers? – Jörg Dec 05 '12 at 17:49
  • @Jörg No, should be fine: it's just a convention that unit names are words. To be honest, % is an odd one as it's not really a unit, but is in siunitx for reasons of realism :-) – Joseph Wright Dec 05 '12 at 17:57