---
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.
- Citation information from `inst/CITATION`, when available.

## What is a `CITATION.cff` file?

[Citation File Format (CFF)](https://citation-file-format.github.io/)
[@druskat_citation_2021] (v1.2.0) files are plain text files with human- and
machine-readable citation information for software (and datasets). Software
developers can include them in their repositories to let others know how to
correctly 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>

![GitHub citation support announcement](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 complete `CITATION.cff` file for your **R** package.

## Modifying your `CITATION.cff` file

You can customize a `cff` object (a custom **cffr** S3 class) using the coercion
system provided in the package 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
```

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)
can be displayed 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

**cffr** provides two functions that convert `person` and `bibentry` objects
(see `?person` and `?bibentry`) to objects that follow 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 author of the package and append the coerced 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 our data. In the following example, we add 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
```

The process is similar to the example with `person`: we modify our `cff` object:

```{r}
#| label: references
finalobject <- cff_modify(newauthorobject, references = refs_cff)

finalobject

cff_validate(finalobject)
```

### Create your modified `CITATION.cff` file

The result can be written with `cff_write()`:

```{r}
#| label: write
# Create a temporary output file.
tmp <- tempfile(fileext = ".cff")

see_res <- cff_write(finalobject, outfile = tmp)

cat(readLines(tmp), sep = "\n")
```

Finally, we can read the created `CITATION.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 as:

```{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
# Clean temporary files.
unlink(tmp)
unlink(tmp2)
```

## References
