1

I try to create a command that shows the euro value. I want it to show different types (0 decimal digits, 2 decimal digits or all decimal digits) and have this set by a \seteurformat command.

That works great (uncommented part of the code).

I also want to have to option to temporarily change the length just for one call of the command and therefore created a local variable but somehow the copying from the global to the local variable does not work and it stays empty which leads to nothing being displayed...

\documentclass{scrlttr2}

\usepackage[ngerman]{babel}

\RequirePackage[defaultsans, scale=0.9]{opensans}
\renewcommand\familydefault{\sfdefault}

\usepackage[detect-all, separate-uncertainty]{siunitx}
\sisetup{group-minimum-digits = 4, group-separator = {~}, locale=DE}

\ExplSyntaxOn

\str_new:N \g__eur_length_str

\NewDocumentCommand{\seteurformat}{m}
{
    \str_gset:Nn \g__eur_length_str { #1 }
}

\str_new:N \l__eur_length_temp_str

\NewDocumentCommand{\EUR}{O{}m}
{
    \str_if_empty:nTF { #1 }
    { % true
        \str_set:Nn \l__eur_length_temp_str { \str_show:N \g__eur_length_str }
    }
    { % false
        \str_set:Nn \l__eur_length_temp_str { #1 }
    }
    
    \str_case:Vn \l__eur_length_temp_str
    {
        {full}{\num[group-separator = {.}, minimum-decimal-digits=2]{#2} \nobreakspace \unit{€}}
        {standard}{\num[group-separator = {.},round-mode = places, round-precision = 2]{#2} \nobreakspace \unit{€}}     
        {min}{\num[group-separator = {.}, round-mode = places, round-precision = 0]{#2} \nobreakspace \unit{€}}
    }

% this part works but then I lose the option to temporarily change the length with #1
%   \str_case:Vn \g__eur_length_str
%   {
%       {full}{\num[group-separator = {.}, minimum-decimal-digits=2]{#2} \nobreakspace \unit{€}}
%       {standard}{\num[group-separator = {.},round-mode = places, round-precision = 2]{#2} \nobreakspace \unit{€}}     
%       {min}{\num[group-separator = {.}, round-mode = places, round-precision = 0]{#2} \nobreakspace \unit{€}}
%   }
}

\ExplSyntaxOff


\begin{document}
    
    \seteurformat{full}
        
    \EUR{456}
    
    \seteurformat{min}
    
    \EUR{456}
    
    \EUR[full]{456}
    
    \EUR{456}
    
    \EUR[min]{456}
    
    \EUR{456}
    
\end{document}
1

1 Answer 1

2

You seem to have a wrong idea of what \str_show:N does. If you want to set a string to the value of another one, you do

\str_set_eq:NN \l__eur_length_temp_str \g__eur_length_str

Here's a fixed code:

\documentclass{article}

\usepackage[default, scale=0.9]{opensans}

\usepackage[detect-all, separate-uncertainty]{siunitx}
\sisetup{group-minimum-digits = 4, group-separator = {~}, locale=DE}

\ExplSyntaxOn

\str_new:N \g__eur_length_str
\str_new:N \l__eur_length_temp_str

\NewDocumentCommand{\seteurformat}{m}
  {
    \str_gset:Nn \g__eur_length_str { #1 }
  }

\NewDocumentCommand{\EUR}{om}
  {
    \group_begin:
    \IfNoValueTF{#1}
      {% no optional argument
        \str_set_eq:NN \l__eur_length_temp_str \g__eur_length_str
      }
      {% optional argument present
        \str_set:Nn \l__eur_length_temp_str { #1 }
      }
    \str_case:Vn \l__eur_length_temp_str
      {
        {full}{\num[group-separator = {.}, minimum-decimal-digits=2]{#2} \nobreakspace \unit{€}}
        {standard}{\num[group-separator = {.},round-mode = places, round-precision = 2]{#2} \nobreakspace \unit{€}}     
        {min}{\num[group-separator = {.}, round-mode = places, round-precision = 0]{#2} \nobreakspace \unit{€}}
      }
    \group_end:
  }

\ExplSyntaxOff


\begin{document}
    
\seteurformat{full}
        
\EUR{456} (full)
    
\seteurformat{min}
    
\EUR{456} (min)
    
\EUR[full]{456} (full)
    
\EUR{456} (min)
    
\EUR[min]{456} (min)

\EUR[standard]{456} (standard)
    
\end{document}

enter image description here

A better implementation, where the user level command is handed to an internal function and there's no need to copy strings.

\documentclass{article}

\usepackage[default, scale=0.9]{opensans}

\usepackage[detect-all, separate-uncertainty]{siunitx}
\sisetup{group-minimum-digits = 4, group-separator = {~}, locale=DE}

\ExplSyntaxOn

\str_new:N \g__eur_length_str

\NewDocumentCommand{\seteurformat}{m}
  {
    \str_gset:Nn \g__eur_length_str { #1 }
  }

\NewDocumentCommand{\EUR}{om}
  {
    \IfNoValueTF{#1}
      {% no optional argument
       \mrcarnivore_eur_print:Vn \g__eur_length_str { #2 }
      }
      {% optional argument present
       \mrcarnivore_eur_print:nn { #1 } { #2 }
      }
  }

\cs_new_protected:Nn \mrcarnivore_eur_print:nn
  {
    \str_case:nn { #1 }
      {
        {full}{\num[group-separator = {.}, minimum-decimal-digits=2]{#2} \nobreakspace \unit{€}}
        {standard}{\num[group-separator = {.},round-mode = places, round-precision = 2]{#2} \nobreakspace \unit{€}}     
        {min}{\num[group-separator = {.}, round-mode = places, round-precision = 0]{#2} \nobreakspace \unit{€}}
      }
  }
\cs_generate_variant:Nn \mrcarnivore_eur_print:nn { V }

\ExplSyntaxOff


\begin{document}
    
\seteurformat{full}
        
\EUR{456} (full)
    
\seteurformat{min}
    
\EUR{456} (min)
    
\EUR[full]{456} (full)
    
\EUR{456} (min)
    
\EUR[min]{456} (min)

\EUR[standard]{456} (standard)
    
\end{document}
6
  • Thanks for your answer. You seem to have a typo in the short answer since my g__ variable does not contain any "temp". What does the \group_begin do? What is the advantage of that and the \IfNoValueTF{#1} compared to my version? It seems to behave the same... Commented May 8, 2023 at 20:56
  • @mrCarnivore Using a group ensures that the value of the local string is not clobbered. Possibly not necessary here. The \IfNoValueTF approach is better, unless you want to be able to write \EUR[]{456}, which doesn't seem meaningful.
    – egreg
    Commented May 8, 2023 at 21:04
  • What does the \cs_generate_variant:Nn \mrcarnivore_eur_print:nn { V } do? You seem to be calling it with \mrcarnivore_eur_print:Vn \g__eur_length_str { #2 } V being the variable value, right? And the :nn { V } does what? Is it putting the variable value instead of the first n? That is very confusing syntax... Commented May 8, 2023 at 21:04
  • What is better in the \IfNoValueTF approach? What problems does it prevent? Commented May 8, 2023 at 21:05
  • @mrCarnivore To the contrary, it's clearer syntax. With V you tell LaTeX you want to use the value of the following argument, that should be a variable.
    – egreg
    Commented May 8, 2023 at 21:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .