---
title: "Introduction to plume"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Introduction to plume}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  warning = FALSE,
  collapse = TRUE,
  comment = "#>"
)
options(str = strOptions(vec.len = 9))
library(plume)
library(readr)
library(gt)
```

The goal of the plume package is to make the handling and formatting of author data for scientific writing in R Markdown and Quarto easy and painless.

## Example data

We'll use the datasets `encyclopedists` and `encyclopedists_fr` to explore the different functionalities of the package. These datasets contain information about four notable authors of the "Encyclopédie", published in France in the 18th century. `encyclopedists_fr` is the French translation of `encyclopedists` and will be used to illustrate how to handle custom variable names. Both datasets are documented in `?encyclopedists`.

```{r}
encyclopedists
```

## Creating a plume object

plume provides two R6 classes: `Plume` and `PlumeQuarto`. You can create a plume object with `Plume$new()` or `PlumeQuarto$new()`. Alternatively, you can use their alias `new_plume()` and `new_plume_quarto()`. plume classes take a data frame or tibble as input data. The input data must have at least two columns, one for given names and another for family names.

```{r}
Plume$new(encyclopedists)
```

## Available names

The default variables handled by plume classes are organised into six categories:

**Primaries**: variables required to create a plume object.

```{r, echo = FALSE}
plume:::plm_table_vars("primaries")
```

**Secondaries**: optional variables that can be provided in the input data.

```{r, echo = FALSE}
plume:::plm_table_vars("secondaries")
```

**Nestables**: optional variables that can be provided in the input data to pass multiple independent values to authors. Nestable variables must start with the same prefix. For example, `affiliation_1`, `affiliation_2`, ..., `affiliation_n` to pass several affiliations to authors.

```{r, echo = FALSE}
plume:::plm_table_vars("nestables")
```

**Roles**: optional user-defined variables describing authors' roles (see [Defining roles and contributors](#defining_roles) for details). By default, uses CRediT roles as defined by `credit_roles()`.

**Internals**: variables created internally. These variables don't need to be provided in the input data and are ignored if supplied. You shouldn't worry much about these variables unless you want to customise names or extend plume classes with new default names.

```{r, echo = FALSE}
plume:::plm_table_vars("internals")
```

**Meta**: `PlumeQuarto`-specific variables used to pass extra information that doesn't fit in other categories. Meta columns must start with the prefix `meta-` and are followed by a custom name (e.g. `meta-custom_name`). You should only use these variables to pass data that are template specific. See Quarto's [arbitrary-metadata](https://quarto.org/docs/journals/authors.html#arbitrary-metadata) section for details.

## Using custom names

plume lets you use custom variable names. Simply provide the `names` parameter a named vector when instantiating a plume class, where keys are default names and values their respective replacements.

```{r}
Plume$new(
  encyclopedists_fr,
  names = c(
    given_name = "prénom",
    family_name = "nom",
    literal_name = "nom_complet",
    email = "courriel",
    initials = "initiales"
  )
)
```

<a name="defining_roles" />

## Defining roles and contributors

You can add roles by creating specific role columns in the input data and indicating contributors with the number `1`:

```{r, echo = FALSE}
tibble::tibble(
  given_name = c("Denis", "Jean-Jacques", "François-Marie", "Jean"),
  family_name = c("Diderot", "Rousseau", "Arouet", "Le Rond d'Alembert"),
  supervision = c(1, NA, NA, 1),
  writing = 1,
)
```

plume uses the `r plume:::link("crt")` (CRediT) by default, assuming the input data contains the appropriate columns (see `credit_roles()` for details). You can specify your own roles via the `roles` parameter when creating a plume object. The `roles` parameter takes a vector of key-value pairs where keys identify role columns and values define the actual roles to use.

```{r, eval = FALSE}
Plume$new(
  data,
  roles = c(
    supervision = "supervised the project",
    writing = "contributed to the writing"
  )
)
```

## Assigning status to authors

```{r, echo = FALSE}
status_methods <- tibble::tibble(
  Name = c(
    "set_corresponding_authors()",
    "set_main_contributors()",
    "set_cofirst_authors()",
    "set_deceased()"
  ),
  Plume = as.logical(c(1, 1, 0, 0)),
  PlumeQuarto = as.logical(c(1, 0, 1, 1)),
)
```

plume provides `r nrow(status_methods)` methods to set particular status to authors:

```{r, echo = FALSE}
plume:::plm_table(status_methods)
```

By default, `set_*()` methods assign values by authors' id. You can change this behaviour at the object or method level using the `by` or `.by` parameter.

Note that these methods are case-insensitive and dot-agnostic.

```{r}
aut <- Plume$new(dplyr::select(encyclopedists, given_name, family_name))

aut$set_corresponding_authors(dd, "j-jr", .by = "initials")
aut
```

Use `everyone()` to assign `TRUE` to all authors:

```{r}
aut$set_corresponding_authors(everyone())
aut
```

## Inserting data into a YAML or Quarto file

`PlumeQuarto` allows you to add or update author data directly into YAML files or the YAML header of `.qmd` documents.

Consider the following YAML file:

```{r, include = FALSE}
tmp_file <- withr::local_tempfile(
  lines = "title: Encyclopédie",
  fileext = ".yml"
)
```

```{r, echo = FALSE, comment = ""}
cat(read_file(tmp_file))
```

You can add author data to the file using the `to_yaml()` method:

```{r, eval = FALSE}
aut <- PlumeQuarto$new(
  dplyr::slice(encyclopedists, 1, 4),
  file = "example.yml"
)
aut$to_yaml()
```

```{r, echo = FALSE, comment = ""}
aut <- PlumeQuarto$new(
  dplyr::slice(encyclopedists, 1, 4),
  tmp_file
)
aut$to_yaml()
cat(read_file(tmp_file))
```

Authors are listed in the order they're defined in the input data.

If the YAML or Quarto file already has an `author` and `affiliations` keys, `to_yaml()` replaces old values with new ones.

```{r, eval = FALSE}
aut <- PlumeQuarto$new(
  dplyr::slice(encyclopedists, 2),
  file = "example.yml"
)
aut$to_yaml()
```

```{r, echo = FALSE, comment = ""}
aut <- PlumeQuarto$new(
  dplyr::slice(encyclopedists, 2),
  tmp_file
)
aut$to_yaml()
cat(read_file(tmp_file))
```

## Getting author information

`get_*()` methods (available in the `Plume` class) generate author information as character vectors. This is useful when you don't need or want to output author information using journal templates.

### Author lists

`get_author_list()` generates author lists. You can control the formatting of author suffixes (symbols linking authors to affiliations, notes and other metadata) using the `suffix` parameter. `suffix` takes a character string as argument and allows you to choose which symbol categories to suffix authors with, using the following keys:

- `a` for affiliations

- `c` for corresponding authors

- `n` for notes

- `o` for ORCIDs (only supported in R Markdown)

The order of the keys determines the order of symbol categories.

```{r}
aut <- Plume$new(encyclopedists)
aut$set_corresponding_authors(everyone())

aut$get_author_list(suffix = "ac")

aut$get_author_list(suffix = "ca")
```

In addition, you can use `^` to superscript and `,` to separate symbols:

```{r}
aut$set_corresponding_authors(1, 4)

aut$get_author_list("^a,^cn")
```

Use `suffix = NULL` or `suffix = ""` to ignore suffixes:

```{r}
aut$get_author_list(suffix = NULL)
```

### Affiliations & notes

`get_affiliations()` and `get_notes()` return authors' affiliations and notes.

```{r}
aut$get_affiliations()

aut$get_notes(sep = ": ", superscript = FALSE)
```

### ORCIDs

`get_orcids()` returns authors with their respective ORCID.

```{r}
aut$get_orcids(icon = FALSE, sep = " ")
```

### Contact details

You can get contact details of corresponding authors using the `get_contact_details()` method:

```{r}
aut$get_contact_details()

aut$get_contact_details(phone = TRUE)

aut$get_contact_details(template = "{name}: {details}")
```

### Contributions

plume provides a convenient way to generate contribution lists using the `get_contributions()` method.

```{r}
aut$get_contributions()

aut$get_contributions(
  roles_first = FALSE,
  by_author = TRUE,
  literal_names = TRUE
)

aut2 <- Plume$new(
  encyclopedists,
  roles = c(
    supervision = "supervised the project",
    writing = "contributed to the Encyclopédie"
  )
)
aut2$get_contributions(roles_first = FALSE, divider = " ")
```

By default, `get_contributions()` lists contributors in the order they're defined. You can arrange contributors in alphabetical order with `alphabetical_order = TRUE`:

```{r}
aut$get_contributions(alphabetical_order = TRUE)
```

It's possible to force one or more contributors to appear first in any given role by setting main contributors:

```{r}
aut$set_main_contributors(supervision = 4, writing = c(3, 2))
aut$get_contributions()
```

You can assign the same main contributors across multiple roles using the `.roles` parameter. For example, to set a main contributor across all roles:

```{r}
aut$set_main_contributors(jean, .roles = aut$roles(), .by = "given_name")
aut$get_contributions()
```

Note that main contributors have the priority over the alphabetical ordering:

```{r}
aut$get_contributions(alphabetical_order = TRUE)
```

The `.roles` parameter only applies to unnamed expressions. This allows you to set the same main contributors across all but a few specific roles at once.

```{r, eval = FALSE}
aut$set_main_contributors(4, 3, supervision = 1, .roles = aut$roles())
```

Here, authors 4 and 3 are the main contributors in all roles but `supervision`, where author 1 is the main contributor.

## Symbols

Default symbols are:

```{r, echo = FALSE}
str(unclass(plm_symbols()))
```

You can change symbols when creating a plume object using the parameter `symbols`.

Use `NULL` to display numerals:

```{r}
aut <- Plume$new(
  encyclopedists,
  symbols = plm_symbols(affiliation = letters, note = NULL)
)

aut$get_author_list("^a,n^")
```

Use `NULL` as much as possible for symbols using numerous unique items (typically affiliations). If you have to use a character vector for a given category that has more unique items than vector elements, you can control the sequencing behaviour using the `sequential()` modifier, as shown below:

```{r, eval = FALSE}
Plume$new(
  encyclopedists,
  symbols = plm_symbols(affiliation = sequential(letters))
)
```

By default, plume repeats elements when all elements in a vector are consumed. Using `sequential()` allows you to display a logical sequence of characters (e.g. `a, b, c, ..., z, aa, ab, ac, ..., az, ba, bb, bc, ...`).

## Outputting as markdown content

To output author data as markdown content, use the chunk option `results: asis` in combination with `cat()`:

````{verbatim}
```{r}
#| results: asis
cat(aut$get_contributions(), sep = "; ")
```
````

Inline chunks output values "as is" by default and can be used as follows:

`` `r knitr::inline_expr("aut$get_author_list()")` ``
