Pandoc template: different separator for last item
Asked Answered
B

2

6

I'm writing a custom Pandoc template and want it to print a list of authors so that all authors are separated with ", " except for the last author who instead is separated with an "and". Can this be done?

Let's say this is my template:

$if(title)$
$title$
$endif$
$if(author)$
$for(author)$$author$$sep$, $endfor$
$endif$
$body$

Which outputs:

My title
Author 1, Author 2, Author 3
Document body

But I want it to output:

My title
Author 1, Author 2 and Author 3
Document body
Britneybritni answered 20/2, 2017 at 21:47 Comment(2)
Did you find a solution for this ?Floaty
@Floaty Sorry, I did not. Please post if you do.Britneybritni
B
7

You have to use so-called "pipes" from Pandoc template syntax (see https://pandoc.org/MANUAL.html).

We'll make a for loop for all-but-last items in our array (it is considered as a pronoun inside the loop, refering to the values from authors/allbutlast). For those elements of our authors array, we'll use ", " as a separator, but outside the loop, we'll simply put the "final separator" ("and" in this case), and the last element of authors array (~ stands for unbreakable space, if you are going to output to LaTeX).

$for(authors/allbutlast)$$it$$sep$, $endfor$ and~$authors/last$

EDIT: In case there's only one author, use something like this:

$if(author/allbutlast)$
$for (author/allbutlast)$
${it}$sep$, 
$endfor$
and ${author/last}
$else$
${author/last}
$endif$
Blanka answered 19/5, 2021 at 19:0 Comment(4)
This solution works well if there is always more than one author. But if the array only has a single item it will add 'and' in front of the only author, as it is both the first and last item in the array.Bunting
@NickBarreto answer edited to include this case.Celtuce
Amazing. I was toying around with some ifs to try and get a solution like this but hadn't quite managed. Will try this out as soon as I get the chance. Thanks!Bunting
The edited answer doesn't work for me (pandoc 3.1.6). The starting conditional evaluates as true even when there's only one author, and I get the same name twice with "and" in between.Oecology
D
0

I changed Jan's answer a little to get it to work in my use-case (a Quarto template). Why do I have by-author? Not sure, but that is what the Quarto template I am changing uses.

    $if(by-author/allbutlast)$
    $for(by-author/allbutlast)$
    {\large{$by-author.name.literal$}}$sep$, 
    $endfor$
    $for(by-author/last)$
    {and \large{$by-author.name.literal$}}
    $endfor$
    $else$
    ${by-author/last}
    $endif$

Here is my full use case. I know this is way more than what was asked, but if you end up on this answer and are making pandoc templates, this might be helpful. I've learned a lot from seeing full use cases. I am working on a title page template for a Quarto book.

YAML _quarto.yml

project:
  type: book

book:
  title: The title
  subtitle: The subtitle
  author:
    - name: Jane Doe
    - name: Eva Nováková
    - name: Matti Meikäläinen
  chapters:
    - index.qmd
    - chap1.qmd
    - chap2.qmd
    - references.qmd

bibliography: references.bib

format:
  pdf:
    documentclass: scrbook
    template-partials: ["partials/before-body.tex"]
    toc: true
    include-in-header: 
      text: |
        \newcommand*{\plogo}{\fbox{$\mathcal{PL}$}} % logo
        \usepackage[utf8]{inputenc} % international characters
        \usepackage[T1]{fontenc} % international characters
        \usepackage{hyphenat} % don't hyphenate the title
        \usepackage{authblk}

partials/before-body.tex

\begin{frontmatter} % why not titlepage? dunno, titlepage threw errors.

    \raggedleft % Right align the title page
    
    \rule{1pt}{\textheight} % Vertical line
    \hspace{0.05\textwidth} % Whitespace between the vertical line and title page text
    \parbox[b]{0.85\textwidth}{ % Paragraph box for holding the title page
    
        {\large\bfseries\nohyphens{$title$}}\\[2\baselineskip] % Title
        $if(subtitle)$
        {\large\textit{$subtitle$}}\\[4\baselineskip] % Subtitle
        $endif$
        
        $if(by-author/allbutlast)$
        $for(by-author/allbutlast)$
        {\large{$by-author.name.literal$}}$sep$, 
        $endfor$
        $for(by-author/last)$
        {and \large{$by-author.name.literal$}}
        $endfor$
        $else$
        ${by-author/last}
        $endif$
        
        \vspace{0.5\textheight} % Whitespace
        
        {\noindent The Publisher~~\plogo}\\[\baselineskip] % Publisher+logo
    }

\end{frontmatter}

title page

Diffuser answered 4/8, 2022 at 1:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.