5

In this thread, writing newcommands, user interface advice request, some of you taught me how to write a function that can generate an elaborate header.

In that case, my problem was complicated because the number of authors in the document could be more than 1. We planned out an approach for 3 authors, but the strategy is very cumbersome. It is necessary to insert new stanzas and conditionals for additional authors. You taught me how to do that, and it works, and I am grateful for the effort.

Output I currently get looks like this:

header from document

Author wants to be able to easily exclude the "Guide No", "Keywords" and "url" sections. Their suggestion is to just leave blank fields, or even omit keys from document function call.

I want you to tell me how to make this more flexible.

Following the twoauthors and threeauthors example from last time, I need to create a bool for each one and then conditionalize the output. I fiddled around with the syntax and did not get it to work. But, even if I could make that work, I can't quite believe it is the best way. It is so tedious.

Here's the document that generates above MRE:

\documentclass[11pt,letterpaper,english]{extarticle}
\usepackage{lmodern}
\renewcommand{\sfdefault}{lmss}
\renewcommand{\ttdefault}{lmtt}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[demo]{graphicx}

\usepackage[includehead, includefoot,
lmargin=1in,
rmargin=1in,
tmargin=0.75in,
bmargin=1.0in,
headheight=0pt,
headsep=0pt,
marginparwidth=0pt,
footskip=1.5\baselineskip,
]{geometry}



\usepackage{xcolor}
\definecolor{darkblue}{HTML}{1e2277}


% $ This nullifies emacs subscripting in following%
%%BEGIN: This begins the custom header
\usepackage{array, tabularx}
\usepackage{xparse}
\usepackage{datetime}
\usepackage[unicode=true,pdfusetitle,
bookmarks=true,bookmarksnumbered=false, bookmarksopen=false,
breaklinks=true, pdfborder={0 0 0},
pdfborderstyle={}, backref=false,
colorlinks=true, linkcolor=darkblue, urlcolor=darkblue, 
citecolor=darkblue] {hyperref}


\newdateformat{crmda}{\small{}\textbf{\shortmonthname[\THEMONTH] \THEDAY, \THEYEAR}}


\ExplSyntaxOn
\NewDocumentCommand \guidesetup { +m }
{
  \bool_set_false:N \l_guide_twoauthors_bool
  \bool_set_false:N \l_guide_threeauthors_bool
  \keys_set:nn { guide } { #1 }
}
\keys_define:nn { guide }
{
    firstauthor .code:n = {
      \keys_set:nn { guide / firstauthor } { #1 }
    },
    secondauthor .code:n = {
      \keys_set:nn { guide } { twoauthors }
      \keys_set:nn { guide / secondauthor } { #1 }
    },
    thirdauthor .code:n = {
      \keys_set:nn { guide } { threeauthors }
      \keys_set:nn { guide / thirdauthor } { #1 }
    },
    twoauthors .bool_set:N = \l_guide_twoauthors_bool,
    twoauthors .default:n = true,
    twoauthors .initial:n = false,
    threeauthors .bool_set:N = \l_guide_threeauthors_bool,
    threeauthors .default:n = true,
    threeauthors .initial:n = false,
    firstauthor / firstname .tl_set:N = \l_guide_first_firstname_tl,
    firstauthor / lastname .tl_set:N = \l_guide_first_lastname_tl,
    firstauthor / affiliation .tl_set:N = \l_guide_first_affil_tl,
    firstauthor / email .tl_set:N = \l_guide_first_email_tl,
    secondauthor / firstname .tl_set:N = \l_guide_second_firstname_tl,
    secondauthor / lastname .tl_set:N = \l_guide_second_lastname_tl,
    secondauthor / affiliation .tl_set:N = \l_guide_second_affil_tl,
    secondauthor / email .tl_set:N = \l_guide_second_email_tl,
    thirdauthor / firstname .tl_set:N = \l_guide_third_firstname_tl,
    thirdauthor / lastname .tl_set:N = \l_guide_third_lastname_tl,
    thirdauthor / affiliation .tl_set:N = \l_guide_third_affil_tl,
    thirdauthor / email .tl_set:N = \l_guide_third_email_tl,
    leftlogo .tl_set:N = \l_guide_leftlogo_tl,
    rightlogo .tl_set:N = \l_guide_rightlogo_tl,
    number .int_set:N = \l_guide_number_int,
    title .tl_set:N = \l_guide_title_tl,
    keywords .tl_set:N = \l_guide_keywords_tl,
    url .tl_set:N = \l_guide_url_tl,
    firstauthor .initial:n = { firstname = a, lastname = b,
      affiliation = c, email = d},
    secondauthor .initial:n = { firstname = g, lastname = h,
      affiliation = i, email = j},
    thirdauthor .initial:n = { firstname = g, lastname = h,
      affiliation = i, email = j},
    url .initial:n = {https://ku.edu},
    number .initial:n = 42,
    title .initial:n = {Guide ~ to ~ Guides},
    keywords .initial:n = {guide},
}
\NewDocumentCommand \guidehdr { +o }
{
  \group_begin:
    \IfValueT { #1 } 
    {
      \bool_set_false:N \l_guide_twoauthors_bool 
      \keys_set:nn { guide } { #1 }
    }
    \guide_hdr:
    \group_end:
}
\cs_new_protected:Nn \guide_hdr:
{
  \noindent
  \begin{tabularx}{\textwidth}{|>{\centering\arraybackslash}p{1.25in}>{\centering\arraybackslash}X>{\raggedleft\arraybackslash}p{1.25in}|}
    \hline 
    \begin{minipage}[c]{\linewidth}
      \begin{center}
        \includegraphics[width=\linewidth]{\l_guide_leftlogo_tl}
        \par
        \bigskip
        {\small{}\textbf{Guide ~ No}: ~ \int_to_arabic:n { \l_guide_number_int  }}
      \end{center}%
    \end{minipage} & 
    \begin{minipage}[c][1\totalheight][b]{3.5in}%
      \bigskip
      \begin{center}
        \begin{minipage}[t][1\totalheight][b]{1\columnwidth}%
          \begin{center}
            \textbf{ \large \l_guide_title_tl }\\
            \rule[0.5ex]{1\linewidth}{1pt}
            \par\end{center}%
        \end{minipage}
        \par
      \end{center}
      \begin{minipage}[t]{1\columnwidth}
        \begin{center}
          \textbf{\l_guide_first_firstname_tl {} ~ \l_guide_first_lastname_tl}, ~\l_guide_first_affil_tl {} ~ <\href{mailto:\l_guide_first_email_tl}{\l_guide_first_email_tl} >
          \bool_if:NT \l_guide_twoauthors_bool
          {
            \\
            \textbf{\l_guide_second_firstname_tl {} ~ \l_guide_second_lastname_tl}, ~\l_guide_second_affil_tl {} ~ <\href{mailto:\l_guide_second_email_tl}{\l_guide_second_email_tl} >
          }
          \bool_if:NT \l_guide_threeauthors_bool
          {
            \\
            \textbf{\l_guide_third_firstname_tl {} ~ \l_guide_third_lastname_tl}, ~\l_guide_third_affil_tl {} ~ <\href{mailto:\l_guide_third_email_tl}{\l_guide_third_email_tl} >
          }
          \par
        \end{center}
      \end{minipage}      
      \smallskip
      \par     
      \begin{flushleft}
        \medskip
        \textbf{Keywords}: ~ \l_guide_keywords_tl \\
        See ~ \url{\l_guide_url_tl} ~ for ~ updates.
        \par
      \end{flushleft}
      \smallskip
    \end{minipage} &
    \begin{minipage}[c]{\linewidth}
      \begin{center}
        \includegraphics[width=\linewidth]{\l_guide_rightlogo_tl}
        \par
        \bigskip
        \crmda\today
      \end{center}%
    \end{minipage} 
    \tabularnewline
    \hline 
  \end{tabularx}
}
\ExplSyntaxOff
%%END This ends the custom header



\begin{document}
%% Fill in values of the arguments here, 
%% If blanks are needed, must insert value " ~ "
%% If comma needed inside value, wrap in {}.
%% Delete secondauthor and thirdauthor if not needed
\guidesetup{%
  firstauthor={
    lastname=Author, 
    firstname=First, 
    affiliation=Title{,}~Institute,
    email=first@ku.edu},
  secondauthor={
    lastname=Author, 
    firstname=Second, 
    affiliation=Title{,}~Institute, 
    email=second@ku.edu}, 
 thirdauthor={
    lastname=Author,
    firstname=Third, 
    affiliation=Title{,}~Institute,
    email=third@ku.edu}, 
  url={https://your.website.here.edu/guides},
keywords={knitr, LaTeX, reproducible documents},
  title={A Title for Skeleton Template: rnw2pdf-guide-knit},
  leftlogo={theme/logoleft.pdf},
  rightlogo={theme/logo-vert.pdf},
  number=-1
}
\guidehdr



HOWDY!

\end{document}
  • Related, but not duplicate: tex.stackexchange.com/questions/417047/… (the answer uses \prop list) – user31729 Feb 24 '18 at 20:17
  • 1
    I am very fond of the \prop list feature of expl3 --- you could easily store the various authors to a prop list and then check with \prop_if_in:NnTF \my_prop_list {firstauthor} { Do this}{ Do that} etc, with secondauthor etc. as well instead of defining a new \bool macro for each – user31729 Feb 24 '18 at 20:24
5

Here's an attempt at a more friendly syntax; instead of declaring different keys for authors, just use one and a property list to store the data.

\documentclass{article}
\usepackage[demo]{graphicx}

\usepackage[includehead, includefoot,
lmargin=1in,
rmargin=1in,
tmargin=0.75in,
bmargin=1.0in,
headheight=0pt,
headsep=0pt,
marginparwidth=0pt,
footskip=1.5\baselineskip,
]{geometry}

\usepackage{xcolor}
\definecolor{darkblue}{HTML}{1e2277}

\usepackage{array}
\usepackage{xparse}
\usepackage{datetime}
\usepackage{hyperref}

\newdateformat{crmda}{{\small\bfseries\shortmonthname[\THEMONTH] \THEDAY, \THEYEAR}}

\ExplSyntaxOn
\NewDocumentCommand \guidesetup { m }
 {
  \keys_set:nn { guide } { #1 }
 }

\int_new:N \g_guide_authors_int
\prop_new:N \g_guide_authors_prop
\tl_new:N \l__guide_authors_tl

\keys_define:nn { guide }
 {
  author .code:n =
   {
    \int_gincr:N \g_guide_authors_int
    \keys_set:nn { guide / author } { #1 }
   },
  author/firstname .code:n = { \guide_add_author:nn { firstname } { #1 } },
  author/lastname .code:n = { \guide_add_author:nn { lastname } { #1 } },
  author/affiliation .code:n = { \guide_add_author:nn { affiliation } { #1 } },
  author/email .code:n = { \guide_add_author:nn { email } { #1 } },
  leftlogo .tl_set:N = \l_guide_leftlogo_tl,
  rightlogo .tl_set:N = \l_guide_rightlogo_tl,
  number .tl_set:N = \l_guide_number_tl,
  title .tl_set:N = \l_guide_title_tl,
  keywords .tl_set:N = \l_guide_keywords_tl,
  url .tl_set:N = \l_guide_url_tl,
  title .initial:n = {TITLE~NEEDED},
}
\NewDocumentCommand \guidehdr { +O{} }
 {
  \group_begin:
  \keys_set:nn { guide } { #1 }
  \guide_hdr:
  \group_end:
 }

\cs_new_protected:Nn \guide_hdr:
 {
  \centering
  \begin{tabular}
   {
    |c
    m{ \dim_eval:n { \textwidth - 2.5in - 6\tabcolsep - 2\arrayrulewidth } }
    c|
   }
  \hline
  &&\tabularnewline[-\dim_eval:n { -\normalbaselineskip + 3ex }]
  \begin{tabular}{@{}c@{}}
  \includegraphics[width=1.25in]{\l_guide_leftlogo_tl} \\[\medskipamount]
  \small\bfseries
  \tl_if_empty:NTF \l_guide_number_tl %<--- there was a typo
   { \leavevmode\vphantom{G} }
   { Guide~No: ~ \tl_use:N \l_guide_number_tl }
  \end{tabular}
  &
  \centering
  \textbf{\large\l_guide_title_tl\\}
  \rule[0.5ex]{1\linewidth}{1pt} \\
  \guide_print_authors:
  \vspace{\bigskipamount}
  \raggedright
  \tl_if_empty:NF \l_guide_keywords_tl
   {
    \textbf{Keywords}: ~ \l_guide_keywords_tl \\
   }
  \tl_if_empty:NF \l_guide_url_tl
   {
    See ~ \url{\l_guide_url_tl} ~ for ~ updates.
   }
  &
  \begin{tabular}{@{}c@{}}
  \includegraphics[width=1.25in]{\l_guide_rightlogo_tl} \\[\medskipamount]
  \small\bfseries
  \crmda\today
  \end{tabular}
  \tabularnewline
  \hline 
  \end{tabular}
}

\cs_new_protected:Nn \guide_add_author:nn
 {
  \prop_gput:Nxn \g_guide_authors_prop
   { #1 \int_to_arabic:n { \g_guide_authors_int } }
   { #2 }
 }
\cs_generate_variant:Nn \prop_gput:Nnn { Nx }
\cs_new_protected:Nn \guide_print_authors:
 {
  \tl_clear:N \l__guide_authors_tl
  \int_step_inline:nnnn { 1 } { 1 } { \g_guide_authors_int }
   {
    \tl_put_right:Nn \l__guide_authors_tl
     {
      \textbf
       {
        \prop_item:Nn \g_guide_authors_prop { firstname ##1 }~
        \prop_item:Nn \g_guide_authors_prop { lastname ##1 }:~
       }
      \prop_item:Nn \g_guide_authors_prop { affiliation##1 }~
      \prop_item:Nn \g_guide_authors_prop { email##1 } \\
     }
   }
   \tl_use:N \l__guide_authors_tl
 }
\ExplSyntaxOff
%%END This ends the custom header



\begin{document}

\guidesetup{%
  author={
    lastname=Author, 
    firstname=First, 
    affiliation=Title{,}~Institute,
    email=first@ku.edu},
  author={
    lastname=Author, 
    firstname=Second, 
    affiliation=Title{,}~Institute, 
    email=second@ku.edu}, 
  author={
    lastname=Author,
    firstname=Third, 
    affiliation=Title{,}~Institute,
    email=third@ku.edu}, 
  url={https://your.website.here.edu/guides},
  keywords={knitr, LaTeX, reproducible documents},
  title={A Title for Skeleton Template: rnw2pdf-guide-knit},
  leftlogo={theme/logoleft.pdf},
  rightlogo={theme/logo-vert.pdf},
  number=-1
}
\guidehdr

\bigskip

\ExplSyntaxOn % for experimenting
\prop_gclear:N \g_guide_authors_prop
\int_gzero:N \g_guide_authors_int
\ExplSyntaxOff

\guidesetup{%
  author={
    lastname=Author, 
    firstname=First, 
    affiliation=Title{,}~Institute,
    email=first@ku.edu},
  author={
    lastname=Author, 
    firstname=Second, 
    affiliation=Title{,}~Institute, 
    email=second@ku.edu}, 
  url={https://your.website.here.edu/guides},
  title={A Title for Skeleton Template: rnw2pdf-guide-knit},
  leftlogo={theme/logoleft.pdf},
  rightlogo={theme/logo-vert.pdf},
  number=20
}
\guidehdr

\end{document}

enter image description here

  • Thank you. This solves entirely the varying number of authors problem. The other part is not solved, however. Where you insert \tl_if_empty:..., I see no effect. I've tried with various inputs for guide number or keywords, but the output never follows the T path for an empty token list. I've tried, for example, "number={}", "number=", and omitting number entirely, but still those features are displayed. Does this depend on the version of pdflatex? Mine shows "pdfTeX 3.14159265-2.6-1.40.18 (TeX Live 2017/Debian)". For you, does the conditional input work for those things? – pauljohn32 Feb 25 '18 at 17:55
  • @pauljohn32 If I comment out the keywords and url keys in the first example, I get this picture. However there was a typo in the code, now fixed, that prevented the disappearance of “Guide No:”. – egreg Feb 25 '18 at 17:59
  • That fixed it. Marked this as correct answer, now this example fully works. For future readers, it is acceptable to either delete "number=" or to set "number={}" or "number=" and the "Guide No:" element is removed. Same works fine for URL. – pauljohn32 Feb 25 '18 at 18:20
  • Also I appreciate the cleanup of my LaTeX code in \NewDocumentCommand. – pauljohn32 Feb 25 '18 at 18:20
  • One disappointing fact: the documents using \prop fail unless the xparse package is new. Worked OK on Ubuntu or Fedora, but our actual workstations--RedHat 7.0--were a horrible fail. In the end, I had to remove the whole TeX distribution and replace with TexLive. – pauljohn32 Mar 31 '18 at 15:57

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.