7

I have been told a number of times now, that I should consider implementing a key-value version of my method \createPerson. I wan't to do this, but my problem is that I don't know how to go on with it. Could you help me get started and explain how it works?

The \createPerson command places the argument in different positions based on what arguments are available and also only creates the absolutely neccesary rows.

Here is a minimum code sample of how I am using the method:

\documentclass{article}
\usepackage{tikz}
\usepackage{datetime}
\usepackage[danish]{varioref}
\usepackage{hyperref}
\usepackage{xifthen}
\RequirePackage[framemethod=TikZ]{mdframed}
\usepackage{multirow, tabularx}
\usepackage[]{units}
\usepackage{xparse}
\usepackage{adjustbox}

%=========================================================================
%                             CREATE PERSON NEW
%=========================================================================
%Arguments: 
%   1)  MANDATORY   - Image destination
%   2)  [OPTIONAL]  - Called name
%   3)  MANDATORY   - Reference to the current full name
%   4)  [OPTIONAL]  - Full birth name
%   5)  MANDATORY   - Uniqueue Reference number
%   6)  [OPTIONAL]  - Birth date in the format of dd. mmm. yyyy
%   7)  <OPTIONAL>  - Death date in the format of dd. mmm. yyyy
\NewDocumentCommand\createPerson{r<>omomo+d<>}
{
    \begin{mdframed}[style=whiteBox]%
        \profileImage[width=0.25\textwidth]{#1}
        \begin{tabularx}{0.75\textwidth}[t]{lXrc}%
            % Row one
            Navn:   &   \nameref{#3}    & \textlabel{#5}{PERSON_ID:#3}    & $\Re$%
            %Create new row if needed
            \IfNoValueTF{#2}%
                {\IfNoValueTF{#4}%
                    {\IfNoValueTF{#6}%
                        {\IfNoValueTF{#7}%
                            {}%
                            {\\}}%
                        {\\}}%
                    {\\}}%
                {\\}%
            % Row two
            \IfNoValueTF{#4}%
                % If no birth name
                {\IfNoValueTF{#2}%
                    % If no called name
                    {&&}%
                    % If a called name
                    {Kaldenavn: & \textlabel{#2}{KN:#3} &}}%
                %If a birth name
                {Fødenavn: & #4 &}%
                %
                \IfNoValueTF{#6}%
                       % If no birth date
                       {\IfNoValueTF{#7}{}{\textlabel{#7}{DD:#3} & \cross}}%
                       {\textlabel{#6}{FD:#3} & $\star$}%
            % Create new row if needed    
            \IfNoValueTF{#2}%
                {%
                \IfNoValueTF{#6}%
                        {}%
                        {\IfNoValueTF{#7}%
                            {}%
                            {\\}%
                        }%
                }%
                {\IfNoValueTF{#4}%
                    {\IfNoValueTF{#6}%
                        {}%
                        {\IfNoValueTF{#7}%
                            {}%
                            {\\}%
                        }%
                    }%
                    {\\}%
                }%
            % Row three
            \IfNoValueTF{#2}%
                % If no called name
                {%
                    \IfNoValueTF{#6}%
                        {}%
                        {\IfNoValueTF{#7}%
                            {}%
                            {&&}%
                        }%
                }%
                % If a called name
                {\IfNoValueTF{#4}%
                    % If no birth name
                    {
                        \IfNoValueTF{#6}%
                            {}%
                            {\IfNoValueTF{#7}%
                                {}%
                                {&&}%
                            }%
                    }%
                    %If birth name
                    {Kaldenavn: & \textlabel{#2}{KN:#3} &}%
                }%
            %
            \IfNoValueTF{#7}%
                       % If no death date
                       {}%
                       {\IfNoValueTF{\textlabel{#6}{FD:#3}}{}{\textlabel{#7}{DD:#3} & \cross}}%
        \end{tabularx}%
    \end{mdframed}%
}

%=========================================================================
%                               TEXT LABEL
%=========================================================================
\makeatletter%
% Arguments:
%  1) The text
%  2) The label
\newcommand*{\textlabel}[2]{%
  \edef\@currentlabel{#1}% Set target label
   #1\phantomsection\label{#2}% Print and store label
}
\makeatother



\mdfdefinestyle{whiteBox}{%
    linecolor=black,
    outerlinewidth=0.75pt,
    roundcorner=6pt,
    innertopmargin=10pt,
    innerbottommargin=10pt,
    innerrightmargin=10pt,
    innerleftmargin=10pt,
    backgroundcolor=white,
    outermargin=0cm,
    nobreak=true,
    align=center}

%=========================================================================
%                       Profile image in border
%=========================================================================
\newsavebox\profileImageBox
\NewDocumentCommand{\profileImage}%
      {O{width=0.6\linewidth}
       O{draw=black,line width=0.75pt,rounded corners=6pt}
       m}{%
   \savebox\profileImageBox{\includegraphics[#1]{#3}}%
   \begin{adjustbox}{valign=t}
       \begin{tikzpicture}%
        \draw [path picture={%
                       \node at (path picture bounding box.center) {%
                           \usebox\profileImageBox};},#2]
              (0,0)  rectangle (\wd\profileImageBox,\ht\profileImageBox);
       \end{tikzpicture}%
   \end{adjustbox}%
}

%=========================================================================
%                                 Cross
%=========================================================================
\newcommand{\cross}[1][.7pt]{\ooalign{%
  \rule[1ex]{1ex}{#1}\cr% Horizontal bar
  \hss\rule{#1}{.7em}\hss\cr}% Vertical bar
}

\begin{document}

\section{Carl Wilhelm Larsen}
    \label{CarlWilhelmLarsen1867}

    \createPerson%
        <summer>%
        [Carl]%
        {CarlWilhelmLarsen1867}%
        {315}%
        [5 maj 1867]%
        <18 maj 1953>%
\end{document}
  • You may wish to look at expl3 property lists or my prototype project tex-obj. There is key/value interface support in expl3. – Sean Allred Dec 15 '15 at 21:56
  • Since you are using TikZ, you might consider using PGF keys support since you are using it already and it is more compatible than the expl3 stuff with TikZ's use of spaces. – cfr Dec 15 '15 at 22:05
  • 1
    Why don't you create a more minimal version of the command for use in your MWE? Right now it would be a lot of work to demonstrate with your code. You may find that you get a more descriptive and explanatory answer with a smaller example. – cfr Dec 15 '15 at 22:08
  • TikZ is fine, but I'd really recommend expl3 for a lot of this. You've got a lot of branching going on -- i.e. programming -- and expl3 is designed to be a programming language (for typesetting, but still). – Sean Allred Dec 15 '15 at 22:14
3

Here's an implementation. I simplified the processing of rows two and three by setting four token lists for the four “corners”, thus largely avoiding code duplication and nesting of conditions.

\documentclass{article}
\usepackage{tikz}
\usepackage{datetime}
\usepackage[danish]{varioref}
\usepackage{hyperref}
\usepackage{xifthen}
\RequirePackage[framemethod=TikZ]{mdframed}
\usepackage{multirow, tabularx}
\usepackage[]{units}
\usepackage{xparse}
\usepackage{adjustbox}

%=========================================================================
%                             CREATE PERSON NEW
%=========================================================================
% Keys (M = mandatory, O = optional)
% image (M)     - Image destination
% name  (O)     - Called name
% fullname (M)  - Reference to the current full name
% birthname (O) - Full birth name
% ref (M)       - Unique Reference number
% birthdate (O) - Birth date in the format of dd. mmm. yyyy
% deathdate (O) - Death date in the format of dd. mmm. yyyy

\ExplSyntaxOn
\NewDocumentCommand\createPerson{m}
 {
  \group_begin:
  \keys_set:nn { firefly/persons } { #1 }
  \firefly_person_make:
  \group_end:
 }

\keys_define:nn { firefly/persons }
 {
  image .tl_set:N = \l_firefly_persons_image_tl,
  image .value_required:n = true,
  name .tl_set:N = \l_firefly_persons_name_tl,
  fullname .tl_set:N = \l_firefly_persons_fullname_tl,
  fullname .value_required:n = true,
  birthname .tl_set:N = \l_firefly_persons_birthname_tl,
  ref .tl_set:N = \l_firefly_persons_ref_tl,
  ref .value_required:n = true,
  birthdate .tl_set:N = \l_firefly_persons_birthdate_tl,
  deathdate .tl_set:N = \l_firefly_persons_deathdate_tl,
 }

\tl_new:N \l__firefly_persons_ul_tl
\tl_new:N \l__firefly_persons_ur_tl
\tl_new:N \l__firefly_persons_ll_tl
\tl_new:N \l__firefly_persons_lr_tl
\tl_const:Nn \c__firefly_persons_test_tl { & }

\cs_new_protected:Nn \firefly_person_make:
 {
  \begin{mdframed}[style=whiteBox]%
    % initialize data for rows two and three
    \tl_set:Nn \l__firefly_persons_ul_tl { & }
    \tl_set:Nn \l__firefly_persons_ur_tl { & }
    \tl_set:Nn \l__firefly_persons_ll_tl { & }
    \tl_set:Nn \l__firefly_persons_lr_tl { & }

    \tl_if_empty:NTF \l_firefly_persons_birthname_tl
     { % no birth name
      \tl_if_empty:NF \l_firefly_persons_name_tl
       { % name
        \tl_set:Nn \l__firefly_persons_ul_tl
         {
          Kaldenavn: & \firefly_persons_label:Vn \l_firefly_persons_name_tl {KN}
         }
       }
     }
     { % birth name
      \tl_set:Nn \l__firefly_persons_ul_tl
       {
        F\o denavn: & \l_firefly_persons_birthname_tl
       }
      \tl_if_empty:NF \l_firefly_persons_name_tl
       { % name
        \tl_set:Nn \l__firefly_persons_ll_tl
         {
          Kaldenavn: & \firefly_persons_label:Vn \l_firefly_persons_name_tl {KN}
         }
       }
     }
     \tl_if_empty:NTF \l_firefly_persons_birthdate_tl
      {% no birth date
       \tl_if_empty:NF \l_firefly_persons_deathdate_tl
        {
         \tl_set:Nn \l__firefly_persons_ur_tl
          {
           \firefly_persons_label:Vn \l_firefly_persons_deathdate_tl {DD} & \cross
          }
        }
      }
      { % birth date
       \tl_set:Nn \l__firefly_persons_ur_tl
        {
         \firefly_persons_label:Vn \l_firefly_persons_birthdate_tl {FD} & $\star$
        }
       \tl_if_empty:NF \l_firefly_persons_deathdate_tl
        {
         \tl_set:Nn \l__firefly_persons_lr_tl
          {
           \firefly_persons_label:Vn \l_firefly_persons_deathdate_tl {DD} & \cross
          }
        }
      }
    % print the data
    \hspace{-0.75pt}
    \profileImage[width=0.25\textwidth]{\l_firefly_persons_image_tl}
    \begin{tabularx}{0.75\textwidth}[t]{l>{\raggedright}Xrc}%
    % Row one
    Navn: &
    \nameref{\l_firefly_persons_fullname_tl} &
    \firefly_persons_label:Vn \l_firefly_persons_ref_tl {PERSON_ID} & $\Re$
    \\
    % Row two
    \bool_if:nF
     {
      \tl_if_eq_p:NN \l__firefly_persons_ul_tl \c__firefly_persons_test_tl
      &&
      \tl_if_eq_p:NN \l__firefly_persons_ur_tl \c__firefly_persons_test_tl
     }
     {
      \l__firefly_persons_ul_tl & \l__firefly_persons_ur_tl \\
     }
    % Row three
    \bool_if:nF
     {
      \tl_if_eq_p:NN \l__firefly_persons_ll_tl \c__firefly_persons_test_tl
      &&
      \tl_if_eq_p:NN \l__firefly_persons_lr_tl \c__firefly_persons_test_tl
     }
     {
      \l__firefly_persons_ll_tl & \l__firefly_persons_lr_tl \\
     }
    \end{tabularx}
  \end{mdframed}
}

\cs_new_protected:Nn \firefly_persons_label:nn
 {
  \tl_set:cn { @currentlabel } { #1 }
  #1\phantomsection\label{#2:\l_firefly_persons_name_tl}
 }
\cs_generate_variant:Nn \firefly_persons_label:nn { V }
\ExplSyntaxOff



\mdfdefinestyle{whiteBox}{%
    linecolor=black,
    outerlinewidth=0.75pt,
    roundcorner=6pt,
    innertopmargin=10pt,
    innerbottommargin=10pt,
    innerrightmargin=10pt,
    innerleftmargin=10pt,
    backgroundcolor=white,
    outermargin=0cm,
    nobreak=true,
    align=center}

%=========================================================================
%                       Profile image in border
%=========================================================================
\newsavebox\profileImageBox
\NewDocumentCommand{\profileImage}%
      {O{width=0.6\linewidth}
       O{draw=black,line width=0.75pt,rounded corners=6pt}
       m}{%
   \savebox\profileImageBox{\includegraphics[#1]{#3}}%
   \begin{adjustbox}{valign=t}
       \begin{tikzpicture}%
        \draw [path picture={%
                       \node at (path picture bounding box.center) {%
                           \usebox\profileImageBox};},#2]
              (0,0)  rectangle (\wd\profileImageBox,\ht\profileImageBox);
       \end{tikzpicture}%
   \end{adjustbox}%
}

%=========================================================================
%                                 Cross
%=========================================================================
\newcommand{\cross}[1][.7pt]{\ooalign{%
  \rule[1ex]{1ex}{#1}\cr% Horizontal bar
  \hss\rule{#1}{.7em}\hss\cr}% Vertical bar
}

\begin{document}

\section{Carl Wilhelm Larsen}
    \label{CarlWilhelmLarsen1867}

\createPerson{
  image=../duck,
  name=Carl,
  fullname=CarlWilhelmLarsen1867,
  birthname=Xyz,
  ref=315,
  birthdate=5 maj 1867,
  deathdate=18 maj 1953,
}
\end{document}

The big advantage of key-value syntax is that their order is completely irrelevant.

enter image description here

  • Looks like it works even though the code sample doesn't compile out of the box. Do you have a manual for this stuff and a name for it? – 7heViking Dec 16 '15 at 14:23
  • @FireFly3000 Not yet. But perusal of texdoc interface3 is good. – egreg Dec 16 '15 at 15:45

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.