4

I try to use the phonenumbers-package to format phonenumbers. As argument I want to use a macro (in the actual document the macro will be defined with pgfkeys!)

What I tried so far:

\documentclass{article}

\usepackage[ngerman]{babel}
\usepackage[area-code-sep=hyphen, country=DE]{phonenumbers}

\begin{document}
\def\tel{01601234567}

\noindent
\phonenumber{01601234567}\\                                 % Correct!
\phonenumber{\tel}\\                                        % No Output
\expandafter\phonenumber{\tel}\\                            % No Output
\expandafter\phonenumber\tel\\                              % Unformatted
\expandafter\phonenumber\bgroup\tel\egroup\\                % Unformatted
\expandafter\phonenumber\expandafter\bgroup\tel\egroup\\    % Unformatted
\end{document}

I don't understand, how I can expand my \tel-macro before using it as an argument.

Thanks in advance!

5
\expandafter\phonenumber\expandafter{\tel}

works in the example. You need the first \expandafter to 'jump over' \phonenumber and the second \expandafter to 'jump over' the {, so that \tel is expanded before \phonenumber{ and you end up with \phonenumber{01601234567}.

In the example it is important that \phonenumber be passed the actual number and not just a macro containing the number. So we have to expand (unpack) the argument (once) before we use it.

If you use a different definition for \tel in your real-world document you may need more \expandafters if it turns out the definition uses more "layers". If you additionally have \def\telA{\tel}, one \expandafter is not enough, you will need three on each side of \phonenumber, because you now need to expand \telA twice to get to the number. For three levels of expansion you would need seven. See \expandafter and \aftergroup: where do the 2n+1 and n^2-1 rules come from?.

If you are sure that your macros expand to a number if you just keep expanding them until that is not possible any more, you can use a different approach that saves you a lot of \expandafters in situations where several expansion steps are required. Just expand the argument completely. You can use \edef and \noexpand (see When to use \edef, \noexpand, and \expandafter?) or the \romannumeral trick (https://www.texdev.net/2011/07/05/expansion-using-romannumeral/). The differences betwen \edef and \romannumeral become important when your macro consists of several elements, \romannumeral will only go on expanding the first token as far as possible, \edef will expand everything.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage[area-code-sep=hyphen, country=DE]{phonenumbers}

\def\tel{01601234567}
\def\telA{\tel}
\def\telB{\telA}

\def\telp{0160}
\def\telq{1234567}
\def\telpA{\telp\telq}
\def\telpB{\telpA}

\def\myphonenumber#1{\phonenumber{#1}\quad(\texttt{\detokenize{#1}})}

\begin{document}
\begin{enumerate}
\item
\myphonenumber{01601234567}

\item % does not work, \tel is not a number
\myphonenumber{\tel}

\item
\expandafter\myphonenumber\expandafter{\tel}

\item % does not work, \telA needs two expansion steps to get a number
\expandafter\myphonenumber\expandafter{\telA}

\item
\expandafter\expandafter\expandafter
\myphonenumber
\expandafter\expandafter\expandafter{\telA}

\item
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
\myphonenumber
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
{\telB}

\item
\begingroup
\edef\temp{\endgroup
  \noexpand\myphonenumber{\tel}}
\temp

\item
\begingroup
\edef\temp{\endgroup
  \noexpand\myphonenumber{\telA}}
\temp

\item
\begingroup
\edef\temp{\endgroup
  \noexpand\myphonenumber{\telB}}
\temp

\item 
\expandafter\myphonenumber\expandafter{\romannumeral-`0\tel}

\item
\expandafter\myphonenumber\expandafter{\romannumeral-`0\telA}

\item
\expandafter\myphonenumber\expandafter{\romannumeral-`0\telB}

\item
\begingroup
\edef\temp{\endgroup
  \noexpand\myphonenumber{\telpB}}
\temp

\item
\expandafter\myphonenumber\expandafter{\romannumeral-`0\telpB}
\end{enumerate}
\end{document}

{ and \bgroup and } and \egroup are not equivalent as argument delimiters. That's why \expandafter\phonenumber\expandafter\bgroup\tel\egroup did not work correctly. You can see what happens when you use \bgroup/\egroup instead of {/} in

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

\def\foo#1{-\detokenize{#1}-}

\begin{document}
\foo{DEF}

\foo\bgroup ABC\egroup
\end{document}

The first line works as expected and shows "-DEF-", but the second line throws an error about too many }s and shows "-\bgroup-ABC", this demonstrates that \foo assumes \bgroup is its argument and not the entire string ABC.

  • Thanks for the solution and for the explanation! – Wulle Oct 28 '18 at 15:34
4

Here's how I'd define \phonenumber

\documentclass{article}

\usepackage[ngerman]{babel}
\usepackage[area-code-sep=hyphen, country=DE]{phonenumbers}

\newcommand\tel{01601234567}

\ExplSyntaxOn

\RenewDocumentCommand \phonenumber {O{}mo}
 {
  \group_begin:
  \keys_set:nn {phonenumbers} {#1}
  \IfNoValueTF { #3 }
   { \phone_nummer_ueberpruefen:f { #2 } }
   { \phone_nummer_ueberpruefen:ff { #2 } { #3 } }
  \phone_nummer_ausgeben:
  \group_end:
 }

\cs_new_protected:Nn \phone_nummer_ueberpruefen:nn
 {
  \phone_durchwahl_ueberpruefen:n {#2}
  \phone_nummer_ueberpruefen:n {#1}
  \bool_lazy_or:nnF
   {\str_if_eq_p:Vn \l_phone_land_str {DE}}
   {\str_if_eq_p:Vn \l_phone_land_str {AT}}
   {
    \bool_if:NF \l_phone_durchwahl_leer_bool
     {
      \msg_warning:nn {phonenumbers} {illegal~extension}
     }
   }
 }
\cs_generate_variant:Nn \phone_nummer_ueberpruefen:n {f}
\cs_generate_variant:Nn \phone_nummer_ueberpruefen:nn {ff}

\ExplSyntaxOff

\begin{document}

\phonenumber{01601234567}

\phonenumber{\tel}

\end{document}

I've first split up the big definition in the package, using \NewDocumentCommand for just sorting out the optional arguments and call internal functions. Here it's necessary to use \RenewDocumentCommand.

This way one needs less boolean checks and also better flexibility; for instance, just changing \phone_nummer_ueberpruefen:n into \phone_nummer_ueberpruefen:f allows to specify input for \phonenumber as a macro.

\documentclass{article}

\usepackage[ngerman]{babel}
\usepackage[area-code-sep=hyphen, country=DE]{phonenumbers}

\newcommand\tel{01601234567}

\ExplSyntaxOn

\RenewDocumentCommand \phonenumber {O{}mo}
 {
  \group_begin:
  \keys_set:nn {phonenumbers} {#1}
  \IfNoValueTF { #3 }
   { \phone_nummer_ueberpruefen:f { #2 } }
   { \phone_nummer_ueberpruefen:nn { #2 } { #3 } }
  \phone_nummer_ausgeben:
  \group_end:
 }

\cs_new_protected:Nn \phone_nummer_ueberpruefen:nn
 {
  \phone_durchwahl_ueberpruefen:n {#2}
  \phone_nummer_ueberpruefen:f {#1} % <--- change :n to :f
  \bool_lazy_or:nnF
   {\str_if_eq_p:Vn \l_phone_land_str {DE}}
   {\str_if_eq_p:Vn \l_phone_land_str {AT}}
   {
    \bool_if:NF \l_phone_durchwahl_leer_bool
     {
      \msg_warning:nn {phonenumbers} {illegal~extension}
     }
   }
 }
\cs_generate_variant:Nn \phone_nummer_ueberpruefen:n {f}

\ExplSyntaxOff

\begin{document}

\phonenumber{01601234567}

\phonenumber{\tel}

\end{document}

enter image description here

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.