Configuration

Air can be configured using a TOML file named air.toml. Air is purposefully minimally configurable, with the main configuration points being related to line width and indent style.

Example configuration

Below is a complete air.toml file showing all available options set to their default values:

[format]
line-width = 80
indent-width = 2
indent-style = "space"
line-ending = "auto"
persistent-line-breaks = true

Configuration recommendations

For collaborative projects, we recommend creating an air.toml and placing it at your project root even if you plan to use the default Air settings. This has a number of benefits:

  • It stops Air from using user level editor settings. When an air.toml is not present, Air respects some user level editor settings, such as editor.tabWidth in VS Code or Positron. The presence of an air.toml (even an empty one) disables this, instead pulling all settings from the configuration file. This ensures that settings are the same across team members, code editors, and in CI.

  • It stops configuration discovery from extending outside your project. Without an air.toml at the project root, Air might discover your local ~/packages/air.toml as the configuration file to use for the ~/packages/dplyr project. By adding ~/packages/dplyr/air.toml, you prevent configuration discovery from looking “above” ~/packages/dplyr, again ensuring consistent settings across team members.

  • It serves as a signal to others that your project is using Air.

If you do plan to just use the defaults, the air.toml can be completely empty. The important thing is that it exists.

If you’re happy with Air’s defaults (or your IDE settings, see section on synchronization) and don’t plan for your project to ever leave your computer, you likely don’t need an air.toml.

Configuration discovery

The ideal place to put an air.toml file is at your project root. For example, note the placement of air.toml in this minimal dplyr project:

~/packages/dplyr
├── air.toml
├── DESCRIPTION
├── NAMESPACE
├── R
├── src
├── tests
└── vignettes

If you run air format with a working directory of ~/packages/dplyr or open your IDE in the dplyr project, then Air will find and use that TOML file.

Air also supports walking up the directory tree from the project root. For example, if you ran air format from within ~/packages/dplyr/R, then Air would look “up” one directory and would find and use ~/packages/dplyr/air.toml.

Settings synchronization

In IDEs that support synchronization (VS Code and Positron currently), Air does its best to ensure that the formatter and the IDE are in agreement. This is supported by two mechanisms:

  • In projects that don’t have an air.toml file, IDE settings are sent to Air. This ensures that Air will use the same indentation style and width that is configured in the IDE.

  • In projects that do have an air.toml file, the Air settings are sent to the IDE. This ensures that the IDE will use the same indentation style and width that Air uses.

The goal of this synchronization mechanism is for the IDE to work in lockstep with the Air formatter.

Dotfiles

Air supports both air.toml and .air.toml. If both are present in the same directory, then air.toml is preferred (but we don’t recommend this).

Format options

All formatting options are specified under the [format] table.

line-width

The preferred maximum line length.

An integer value between 1 and 320, with a default of 80.

While the formatter will attempt to format lines such that they remain within the line-width, it isn’t a hard upper bound, and formatted lines may exceed the line-width.

indent-width

The number of spaces per indentation level.

An integer value between 1 and 24, with a default of 2.

This option changes the number of spaces the formatter inserts when using indent-style = "space". It also represents the width of a tab when indent-style = "tab" for the purposes of computing the line-width.

indent-style

Whether to use spaces or tabs for indentation.

One of the following values, with a default of "space":

  • "space": Use spaces for indentation.

  • "tab": Use tabs for indentation.

Air defaults to spaces due to the overwhelming amount of existing R code written in this style, but consider using tabs for new projects to improve accessibility. See indent-width to configure the number of spaces per indentation and the tab width.

line-ending

The character air uses at the end of a line.

One of the following values, with a default of "auto":

  • "auto": The newline style is detected automatically on a file per file basis. Files with mixed line endings will be converted to the first detected line ending. Defaults to \n for files that contain no line endings.

  • "lf": Line endings will be converted to \n. The typical line ending on Unix.

  • "crlf": Line endings will be converted to \r\n. The typical line ending on Windows.

  • "native": Line endings will be converted to \n on Unix and \r\n on Windows.

persistent-line-breaks

Whether or not persistent line breaks are allowed.

Either true to respect persistent line breaks, or false to ignore them, with a default of true.

Air respects a small set of persistent line breaks as an indication that certain function calls or function signatures should be left expanded. For example, the following list could be flattened to one line and would still fit within a line-width of 80, however, it remains expanded due to the persistent line break between the opening ( and the first argument, apple.

dictionary <- list(
  apple = 0.75,
  banana = 0.25,
  cherry = 0.50
)

Similarly, this function signature could also be flattened, but is not, due to the persistent line break between the opening ( and the first parameter, ....

case_when <- function(
  ...,
  .default = NULL,
  .ptype = NULL,
  .size = NULL
) {
  body
}

To request flattening in these cases, just remove the persistent line break. For example:

# If you started here,
dictionary <- list(
  apple = 0.75,
  banana = 0.25,
  cherry = 0.50
)

# then do this, and run air,
dictionary <- list(apple = 0.75,
  banana = 0.25,
  cherry = 0.50
)

# to get this.
dictionary <- list(apple = 0.75, banana = 0.25, cherry = 0.50)

Alternatively, use a tool such as codegrip bound to a keyboard shortcut to flatten the code, and Air will keep it flattened as long as it fits within the line-width.

It may be preferable to ignore persistent line breaks if you prefer that line-width should be the only value that influences line breaks.