0

Introduction

I am sorry for the long MWE, but I was not able to make it shorter and still illustrate my problem. Again I am working on streamlining the creation of exams for my university. In the example below the user can add more lectures using

\defineInfo{jane}{
  name=Jane Doe, 
  phone=75123123,
}

(Where I got help creating the syntax in Contact list as dictionary) Add information about the exam using

\FrontpageUiTsetup{
  contact = jane,
}

(Now with the help from Labeled input parameters) Where the last command of course has a lot more parameters, irrelevant to my question. Now, I want to combine these two answers, so I can refer to a lecturer using an ID, and then print the relevant parts in \FrontpageUiT.

I first tried writing

\ifx\@contact\@empty\else
  \contactname & \contactInfo{\@contact}{name}\\%
\fi

However, it seems the \contactInfo command expands before \@contact so it outputs nothing. After a bit of googling I was able to use the following to expand \@contact first

\newcommand{\expandMacro}[1]{
  \begingroup\edef\x{\endgroup
    \noexpand#1%
  }\x
}

Problem

So here comes my problem:

  • I want the default value of @phone and @mobile to be defined by respectively the lines \contactInfo{\@contact}{mobile} and \contactInfo{\@contact}{phone}

The problem comes when I want the line

\contactmobile & \@mobile 

To be blank when no mobile number is given. Example:

    mobile        .tl_set:N  = \@mobile,
    mobile        .initial:n = {\expandMacro{\contactInfo{\@contact}{mobile}}},
    phone         .tl_set:N  = \@phone,
    phone         .initial:n = {\expandMacro{\contactInfo{\@contact}{phone}}},
.
.
.
  \ifx\@contact\@empty\else
    \contactname & \expandMacro{\contactInfo{\@contact}{name}}\\%
  \fi

  \ifx\@mobile\@empty\else
    \contactmobile & \@mobile\\%
  \fi

  \ifx\@phone\@empty\else
    \contactphone & \@phone\\%
.
.
.

\defineInfo{jane}{
  name=Jane Doe, 
  phone=75123123,
}

\FrontpageUiTsetup{
  contact = jane,
}

\begin{document}
\FrontpageUiT
\end{document}

As Jane has no mobile number, I would expect the output to be

Contact    Jane Doe
Phone      75 12 31 23

Instead I am faced with

Contact    Jane Doe
Mobile
Phone      75 12 31 23

The problem is that the code can not expand \contactInfo{\@contact}{mobile} fast enough to realize that it is empty. After a bit more googling I found

\newcommand{\IfNoText}[3]{%
  \sbox0{#1}%
  \ifdim\wd0=0pt %
    {#2}% if #1 is empty
  \else%
    \ifdim0pt=\dimexpr\ht0+\dp0\relax
      {#2}% if #1 is empty
    \else
      {#3}% if #1 is not empty
    \fi
  \fi%
}

That can detect if the output is blank. However, it does not support ampersand (&), so I can not use it in my table. E.G

\IfNoText{\@mobile}{}{Mobile & \@mobile \\}

throws me an error. I tried also to use \IfNoText earlier in my document to define toggles that expand to true or false based on the contents of \@mobile. However, these did not expand fast enough either.

  • Is there a way to check that \@mobile and @phone is empty faster, when they are given in the terms of \contactInfo?

Code

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

\usepackage{xparse}
\usepackage{xfp}

\newcommand{\IfNoText}[3]{%
  \sbox0{#1}%
  \ifdim\wd0=0pt %
    {#2}% if #1 is empty
  \else%
    \ifdim0pt=\dimexpr\ht0+\dp0\relax
      {#2}% if #1 is empty
    \else
      {#3}% if #1 is not empty
    \fi
  \fi%
}

\newcommand{\expandMacro}[1]{
  \begingroup\edef\x{\endgroup
    \noexpand#1%
  }\x
}

\ExplSyntaxOn
\NewDocumentCommand{\defineInfo}{mm}
 {
  \prop_new:c { \__nebu_contact_prop:n { #1 } }
  \prop_gset_from_keyval:cn { \__nebu_contact_prop:n { #1 } } { #2 }
 }
\NewDocumentCommand{\contactInfo}{mm}
 {
  \str_case:nnF { #2 }
   {
    {phone}  { \nebu_phone:e { \prop_item:cn { \__nebu_contact_prop:n { #1 } } { #2 } } }
    {mobile} { \nebu_phone:e { \prop_item:cn { \__nebu_contact_prop:n { #1 } } { #2 } } }
   }
   { \prop_item:cn { \__nebu_contact_prop:n { #1 } } { #2 } }
 }

% syntactic sugar
\cs_new:Nn \__nebu_contact_prop:n
 {
  g_nebu_contact_\str_lower_case:n { #1 }_prop
 }

%%% formatting phone numbers
\NewDocumentCommand{\phone}{m}
 {
  \nebu_phone:n { #1 }
 }

\tl_new:N \l__nebu_phone_tl

\cs_new_protected:Nn \nebu_phone:n
 {
  \tl_set:Nn \l__nebu_phone_tl { #1 }
  \tl_remove_all:Nn \l__nebu_phone_tl { ~ }
  \int_compare:nTF { \tl_count:N \l__nebu_phone_tl = 8 }
   {
    \__nebu_phone_eight:V \l__nebu_phone_tl
   }
   {
    \tl_use:N \l__nebu_phone_tl
   }
 }
\cs_generate_variant:Nn \nebu_phone:n { e }

\cs_new:Nn \__nebu_phone_eight:n
 {
  \str_case_e:nnF { \tl_head:n { #1 } }
   {
    {4}{ \__nebu_phone_iii_ii_iii:nnnnnnnn #1 }
    {8}{ \__nebu_phone_iii_ii_iii:nnnnnnnn #1 }
    {9}{ \__nebu_phone_iii_ii_iii:nnnnnnnn #1 }
   }
   {
    \__nebu_phone_ii:nnnnnnnn #1
   }
 }
\cs_generate_variant:Nn \__nebu_phone_eight:n { V }

\cs_new:Nn \__nebu_phone_iii_ii_iii:nnnnnnnn { #1#2#3\hspace{1ex}#4#5\hspace{1ex}#6#7#8 }
\cs_new:Nn \__nebu_phone_ii:nnnnnnnn { #1#2\hspace{0.6666ex}#3#4\hspace{0.6666ex}#5#6\hspace{0.6666ex}#7#8 }

\ExplSyntaxOff

% https://tex.stackexchange.com/a/504129/8306
%
% This creates the backbone for the frontpage. One can add new keys here
\makeatletter
  % Provide commands.
  \ExplSyntaxOn
    % Provide keys.
    \keys_define:nn { babylonia }
      {
        contact       .tl_set:N  = \@contact,
        mobile        .tl_set:N  = \@mobile,
        mobile        .initial:n = {\expandMacro{\contactInfo{\@contact}{mobile}}},
        phone         .tl_set:N  = \@phone,
        phone         .initial:n = {\expandMacro{\contactInfo{\@contact}{phone}}},
      }
    % Provide key setting command.
    \NewDocumentCommand\FrontpageUiTsetup{ m }{
      \keys_set:nn { babylonia } { #1 }
    }
  \ExplSyntaxOff
  % Provide names.
  \newcommand*\contactname{Contact}
  \newcommand*\contactmobile{Mobile}
  \newcommand*\contactphone{Phone}
  % The typesetting command.
  \newcommand\FrontpageUiT{%

    \noindent
    \begin{tabular}{p{0.2\textwidth} p{\dimexpr 0.8\textwidth - 4\tabcolsep}}

      \ifx\@contact\@empty\else
        \contactname & \expandMacro{\contactInfo{\@contact}{name}}\\%
      \fi

      \ifx\@mobile\@empty\else
        \contactmobile & \@mobile\\%
      \fi

      \ifx\@phone\@empty\else
        \contactphone & \@phone\\%
      \fi

    \end{tabular}%
  }
\makeatother

% ==============================================================================
%   User interface below here
% ==============================================================================

% This adds contacts to be used in the UiT frontpage
% Example:
%
% \defineInfo{joe}{
%   name=Joe Doe, mobile=32132132, phone=93123123,
% }

\defineInfo{jane}{
  name=Jane Doe, 
  phone=75123123,
}

\FrontpageUiTsetup{
  contact = jane,
}

\begin{document}

\FrontpageUiT

\end{document}
3

Add two commands, one for testing the presence of a property, the other for typesetting the info.

\NewExpandableDocumentCommand{\contactTestTF}{mmmm}
 {% #1 = contact, #2 = property to test, #3 = code for true, #4 = code for false
  \prop_if_in:cnTF { \__nebu_contact_prop:n { #1 } } { #2 } { #3 } { #4 }
 }
\NewDocumentCommand{\FrontpageUiTsetup}{m}
 {
  \begin{tabular}{@{} l l @{}}
  \contactname & \contactInfo{#1}{name} \\
  \contactTestTF{#1}{mobile}{\mobilename & \contactInfo{#1}{mobile} \\}{}
  \contactTestTF{#1}{phone}{\phonename & \contactInfo{#1}{phone} \\}{}
  \end{tabular}
 }

Full example:

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\defineInfo}{mm}
 {
  \prop_new:c { \__nebu_contact_prop:n { #1 } }
  \prop_gset_from_keyval:cn { \__nebu_contact_prop:n { #1 } } { #2 }
 }
\NewExpandableDocumentCommand{\contactInfo}{mm}
 {
  \str_case:nnF { #2 }
   {
    {phone}  { \nebu_phone:e { \prop_item:cn { \__nebu_contact_prop:n { #1 } } { #2 } } }
    {mobile} { \nebu_phone:e { \prop_item:cn { \__nebu_contact_prop:n { #1 } } { #2 } } }
   }
   { \prop_item:cn { \__nebu_contact_prop:n { #1 } } { #2 } }
 }
\NewExpandableDocumentCommand{\contactTestTF}{mmmm}
 {% #1 = contact, #2 = property to test, #3 = code for true, #4 = code for false
  \prop_if_in:cnTF { \__nebu_contact_prop:n { #1 } } { #2 } { #3 } { #4 }
 }
\NewDocumentCommand{\FrontpageUiTsetup}{m}
 {
  \begin{tabular}{@{} l l @{}}
  \contactname & \contactInfo{#1}{name} \\
  \contactTestTF{#1}{mobile}{\mobilename & \contactInfo{#1}{mobile} \\}{}
  \contactTestTF{#1}{phone}{\phonename & \contactInfo{#1}{phone} \\}{}
  \end{tabular}
 }

% syntactic sugar
\cs_new:Nn \__nebu_contact_prop:n
 {
  g_nebu_contact_\str_lower_case:n { #1 }_prop
 }

%%% formatting phone numbers
\NewDocumentCommand{\phone}{m}
 {
  \nebu_phone:n { #1 }
 }

\tl_new:N \l__nebu_phone_tl

\cs_new_protected:Nn \nebu_phone:n
 {
  \tl_set:Nn \l__nebu_phone_tl { #1 }
  \tl_remove_all:Nn \l__nebu_phone_tl { ~ }
  \int_compare:nTF { \tl_count:N \l__nebu_phone_tl = 8 }
   {
    \__nebu_phone_eight:V \l__nebu_phone_tl
   }
   {
    \tl_use:N \l__nebu_phone_tl
   }
 }
\cs_generate_variant:Nn \nebu_phone:n { e }

\cs_new:Nn \__nebu_phone_eight:n
 {
  \str_case_e:nnF { \tl_head:n { #1 } }
   {
    {4}{ \__nebu_phone_iii_ii_iii:nnnnnnnn #1 }
    {8}{ \__nebu_phone_iii_ii_iii:nnnnnnnn #1 }
    {9}{ \__nebu_phone_iii_ii_iii:nnnnnnnn #1 }
   }
   {
    \__nebu_phone_ii:nnnnnnnn #1
   }
 }
\cs_generate_variant:Nn \__nebu_phone_eight:n { V }

\cs_new:Nn \__nebu_phone_iii_ii_iii:nnnnnnnn { #1#2#3\nobreakspace#4#5\nobreakspace#6#7#8 }
\cs_new:Nn \__nebu_phone_ii:nnnnnnnn { #1#2\nobreakspace#3#4\nobreakspace#5#6\nobreakspace#7#8 }
\ExplSyntaxOff

\newcommand{\contactname}{Contact}
\newcommand{\mobilename}{Mobile}
\newcommand{\phonename}{Phone}

\defineInfo{jane}{
  name=Jane Doe,
  mobile=32132132,
  phone=45123123,
}
\defineInfo{joe}{
  name=Joe Doe,
  %mobile=32132132,
  phone=93123123,
}
\defineInfo{richard}{
  name=Richard Roe,
  mobile=32132132,
  phone=83123123,
}

\begin{document}

\contactInfo{Jane}{name} has \contactInfo{jane}{mobile} mobile phone.

\contactInfo{riCHard}{phone} is \contactInfo{Richard}{name}'s phone.

\bigskip

\FrontpageUiTsetup{jane}

\bigskip

\FrontpageUiTsetup{joe}

\end{document}

enter image description here

  • This seems to work great, but I can not make it work for my example. I would rather not redefine \FrontpageUiTsetup as this probably will take in 10-15 named commands, in addition to the lecturer ID. It would look something like this tex.stackexchange.com/questions/503983/labeled-input-parameters/…. I dont understand why \contactTestTF{\@contact}{mobile} does not work =/ I am working towards \FrontpageUiT to create something like i.imgur.com/VLQ1sd5.png. – N3buchadnezzar Aug 14 at 16:49
  • @N3buchadnezzar Why mixing legacy programming with expl3? – egreg Aug 14 at 17:01
  • Without trying to start a long discussion: which part is legacy programming? I am simply trying to create a setup file (like hypersetup) to create a table. One of the entries in this setup is an id that identifies an lecturer. If this id is present, then I want to be able to choose whether or not to print the name, phone and mobile associated with that id. If you have a "non legacy" way of achieving what I am trying to do, I am all ears =) – N3buchadnezzar Aug 14 at 18:15

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.