---
title: "Manipulating citations with cffr"
description: Learn how to modify `cff` objects.
toc: true
bibliography: REFERENCES.bib
link-citations: true
vignette: >
  %\VignetteIndexEntry{Manipulating citations with cffr}
  %\VignetteEngine{quarto::html}
  %\VignetteEncoding{UTF-8}
knitr:
  opts_chunk:
    collapse: true
    comment: "#>"
    warning: false
    message: true
---

```{r}
#| include: false
library(cffr)
```

**cffr** is designed for **R** package developers. Its main goal is to create a
`CITATION.cff` file using metadata from the following files:

- Your `DESCRIPTION` file.
- Your `inst/CITATION` file, when available.

## What is a `CITATION.cff` file?

A `CITATION.cff` file follows the [Citation File Format
(CFF)](https://citation-file-format.github.io/) [@druskat_citation_2021]
(v1.2.0). It contains human- and machine-readable citation metadata for software
and datasets. Developers can include it in a repository to explain how to cite
their software.

This format is increasingly used in the software citation ecosystem.
[**GitHub**](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files),
[**Zenodo**](https://citation-file-format.github.io/#/supported-by-zenodo-) and
[**Zotero**](https://citation-file-format.github.io/#/supported-by-zotero-)
support this citation format [@druskat_stephan_making_2021].

**GitHub** support is of special interest:

<figure>

![Nat Friedman's announcement that adding a CITATION.cff file to a repository enables GitHub's Cite this repository menu, shown below the post.](tweet-1.png){.quarto-figure
.quarto-figure-center fig-align="center" width="400"}

```{=html}
<figcaption class="blockquote-footer">Nat Friedman (@natfriedman) July 27, 2021</figcaption>
</figure>
```

See [**GitHub**'s guide to CITATION
files](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files)
for more information.

## Creating a `CITATION.cff` file for your R package

Creating a `CITATION.cff` file with **cffr** is straightforward. You only need
to run `cff_write()`:

```{r}
#| label: setup
#| eval: false
library(cffr)

cff_write()

# Done.
```

Under the hood, `cff_write()` performs these tasks:

- Extracts the metadata using `cff_create()`.
- Optionally modifies it with `cff_modify()`.
- Writes a `CITATION.cff` file.
- Validates the result using `cff_validate()`.

You now have a `CITATION.cff` file populated from the available package
metadata. The validation step reports any values that do not satisfy the CFF
schema so that they can be corrected in their original metadata source.

## Modifying your `CITATION.cff` file

You can customize a `cff` object using `cff_modify()`, the package's coercion
methods and the `keys` argument.

For demonstration, we create a `cff` object using `cff()` and then add or modify
its contents.

### Adding new keys

```{r}
#| label: newfields
newobject <- cff()

newobject
```

You can display the valid keys from the [Citation File Format schema version
1.2.0](https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md)
with `cff_schema_keys()`:

```{r}
#| label: validkeys
cff_schema_keys()
```

In this case, we add `url`, `version` and `repository`. We also overwrite the
`title` key by passing these arguments to `cff_modify()`:

```{r}
#| label: modify
modobject <- cff_modify(
  newobject,
  url = "https://ropensci.org/",
  version = "0.0.1",
  repository = "https://github.com/ropensci/cffr",
  # If the key is already present, it is overridden.
  title = "Modifying a 'cff' object"
)

modobject

# Validate against the schema.

cff_validate(modobject)
```

### Persons and references

`as_cff_person()` converts `person` objects and `as_cff()` converts `bibentry`
objects to metadata that follows the [Citation File Format
schema](https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md).

Following the previous example, we first add a new author. To do that, we need
to extract the current package authors and append the converted person:

```{r}
#| label: includeauthor
# Valid person keys.

cff_schema_definitions_person()

# Create the person.

chiquito <- person(
  "Gregorio",
  "Sánchez Fernández",
  email = "fake@email2.com",
  comment = c(
    alias = "Chiquito de la Calzada",
    city = "Malaga",
    country = "ES",
    ORCID = "0000-0000-0000-0001"
  )
)

chiquito

# Convert to `cff`.
chiquito_cff <- as_cff_person(chiquito)
chiquito_cff

# Append to previous authors.

newauthors <- c(modobject$authors, chiquito_cff)
newauthors

newauthorobject <- cff_modify(modobject, authors = newauthors)

newauthorobject

cff_validate(newauthorobject)
```

Next, we add `references` to the `cff` object. This example adds two references,
one created with `bibentry()` and another with `citation()`:

```{r}
#| label: parsingcits
# Valid reference keys.

cff_schema_definitions_refs()

# Automatic coercion from another **R** package.
base_r <- citation("base")

bib <- bibentry(
  "Book",
  title = "This is a book",
  author = "Lisa Lee",
  year = 1980,
  publisher = "McGraw Hill",
  volume = 2
)

refs <- c(base_r, bib)

refs

# Convert to `cff`.

refs_cff <- as_cff(refs)

refs_cff
```

As with the `person` example, we modify the `cff` object:

```{r}
#| label: references
finalobject <- cff_modify(newauthorobject, references = refs_cff)

finalobject

cff_validate(finalobject)
```

### Write the modified `CITATION.cff` file

The result can be written with `cff_write()`:

```{r}
#| label: write
# Create a temporary output file.
tmp <- tempfile(fileext = ".cff")

cff_write(finalobject, outfile = tmp)

cat(readLines(tmp), sep = "\n")
```

Finally, we can read the resulting CFF file using `cff_read()`:

```{r}
#| label: read
reading <- cff_read(tmp)

reading
```

Note that `cff_write()` also has the `keys` argument, so the workflow can be
simplified to:

```{r}
allkeys <- list(
  "url" = "https://ropensci.org/",
  "version" = "0.0.1",
  "repository" = "https://github.com/ropensci/cffr",
  # If the key is already present, it is overridden.
  title = "Modifying a 'cff' object",
  authors = newauthors,
  references = refs_cff
)

tmp2 <- tempfile(fileext = ".cff")

res <- cff_write(cff(), outfile = tmp2, keys = allkeys)

res
```

```{r}
#| include: false
# Remove temporary files.
unlink(tmp)
unlink(tmp2)
```

## References
