Введение

Введение

Введение

Извините за длинный MWE, но я не смог сделать его короче и все же проиллюстрировать свою проблему. Я снова работаю над оптимизацией создания экзаменов для моего университета. В примере ниже пользователь может добавить больше лекций, используя

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

(Где мне помогли создать синтаксис вСписок контактов как словарь) Добавьте информацию об экзамене, используя

\FrontpageUiTsetup{
  contact = jane,
}

(Теперь с помощьюМаркированные входные параметры) Где последняя команда, конечно, имеет гораздо больше параметров, не имеющих отношения к моему вопросу. Теперь я хочу объединить эти два ответа, чтобы я мог ссылаться на лектора, используя идентификатор, а затем вывести соответствующие части в \FrontpageUiT.

Я сначала попробовал писать

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

Однако, похоже, \contactInfoкоманда расширяется раньше, \@contactпоэтому ничего не выводит. Немного погуглив, я смог использовать следующее, чтобы \@contactсначала расширить

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

Проблема

Итак, вот моя проблема:

  • Я хочу, чтобы значение по умолчанию @phone и @mobile определялось соответственно линиями \contactInfo{\@contact}{mobile}и\contactInfo{\@contact}{phone}

Проблема возникает, когда я хочу, чтобы линия

\contactmobile & \@mobile 

Оставить пустым, если номер мобильного телефона не указан. Пример:

    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}

Поскольку у Джейн нет номера мобильного телефона, я ожидаю, что вывод будет таким:

Contact    Jane Doe
Phone      75 12 31 23

Вместо этого я сталкиваюсь с

Contact    Jane Doe
Mobile
Phone      75 12 31 23

Проблема в том, что код не может \contactInfo{\@contact}{mobile}достаточно быстро расширяться, чтобы понять, что он пуст. Немного погуглив, я нашел

\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%
}

Это может определить, является ли вывод пустым. Однако он не поддерживает амперсанд (&), поэтому я не могу использовать его в своей таблице. Например

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

выдает мне ошибку. Я также пытался использовать \IfNoTextранее в своем документе, чтобы определить переключатели, которые расширяются до true или false в зависимости от содержимого \@mobile. Однако они также не расширялись достаточно быстро.

  • Есть ли способ проверить это \@mobileи @phoneопустеть быстрее, когда они заданы в терминах \contactInfo?

Код

\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_lowercase: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}

решение1

Добавьте две команды: одну для проверки наличия свойства, другую для набора информации.

\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}
 }

Полный пример:

\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_lowercase: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}

введите описание изображения здесь

Связанный контент