Formatter
Air is first and foremost a formatter of R code. On this page, you’ll find details about what a formatter is, why you’d want to use one, and you’ll learn about how Air makes decisions on how to format your R code.
What’s a formatter?
A formatter is in charge of the layout of your R code. Formatters do not change the meaning of code; instead they ensure that whitespace, newlines, and other punctuation conform to a set of rules and standards, such as:
Making sure your code is indented with the appropriate amount of leading whitespace depending on the context. By default, Air uses an indentation of 2 spaces. You will see this indentation in pipelines:
|> data ggplot(aes(x, y)) + geom_point()
As well as expanded (i.e. vertically laid out) function calls:
list( foo = 1, bar = 2 )
Preventing your code from overflowing a given line width. By default, we use a line width of 80 characters. It does so by splitting lines of code that have become too long over multiple lines. For instance, let’s say that we’ve set the line width to be extremely small and these expressions would overflow:
|> select(foo) data <- function(bar = 1, baz = 2) { foo list(bar, baz) }
To respect the very small line width, Air would switch these expressions from a horizontal layout (called “flat”) to a vertical one (called “expanded”):
|> data select(foo) <- function( foo bar = 1, baz = 2 ) {list( bar, baz ) }
Standardizing the whitespace around code elements. Have you ever had difficulties deciphering very dense code?
1+2:3*(4/5)
Air reformats this expression to:
1 + 2:3 * (4 / 5)
In general, a formatter takes over the whitespace in your code and moves elements around to respect style conventions and maximize readability.
How does a formatter help your workflow?
By using a formatter it might seem like you’re rescinding control over the layout of your code. And indeed you are! However, putting Air in charge of styling your code has substantial advantages.
First, it automatically forces you to write legible code that is neither too wide nor too narrow, with proper breathing room around syntactic elements. Having a formatter as a companion significantly improves the process of writing code as you no longer have to think about style as much - the formatter does that for you!
Second, it reduces friction when working in a team. By agreeing to use a formatter in a project, collaborators no longer have to discuss styling and layout issues. Code sent to you by a colleague will adhere to the standards that you’re used to. Code review no longer has to be about style nitpicks and can focus on the substance of the changes instead.
How does Air decide how to format your code?
Air tries to strike a balance between enforcing rigid rules and allowing authors some control over the layout. Our main source of styling rules is the Tidyverse style guide, but we occasionally deviate from these.
There is a trend among modern formatters of being opinionated. Air certainly fits this trend and provides very few configuration options, mostly the indent style (spaces versus tabs), the indent width, and the line width. However, Air also puts code authors in charge of certain aspects of the layout through the notion of persistent line breaks.
In general, Air is in control of deciding where to put vertical space (line breaks) in your code. For instance if you write:
list(foo,
bar)
Air will figure out that this expression fits on a single line without exceeding the line width. It will discard the line break and reformat to:
list(foo, bar)
However there are very specific places at which you can enforce a line break, i.e. make it persistent.
Before the very first argument in a function call. This:
list( foo, bar)
gets formatted as:
list( foo, bar )
Before the very first right-hand side expression in a pipeline. This:
|> data select(foo) |> filter(!bar)
gets formatted as:
|> data select(foo) |> filter(!bar)
A persistent line break will never be removed by Air. But you can remove it manually. Taking the last example, if you join the first lines like this:
list(foo,
bar
)
1 + 2 +
3
Air will recognize that you’ve removed the persistent line break, and reformat as:
list(foo, bar)
1 + 2 + 3
The goal of this feature is to strike a balance between being opinionated and recognizing that users often know when taking up more vertical space results in more readable output.
When does a formatter run?
The most convenient way to run a formatter is when you save a file. Most editors don’t enable this by default, so check out the Editors section to learn how to configure your editor to format on save. Once enabled, your code will be reformatted every time you save! This prevents your code from ever diverging from the standards set by Air.
Air also provides a CLI tool. It makes it easy to reformat whole directories such as an R project or package. If you’re incorporating Air into an existing project, you may want to use the CLI tool to run air format once on the entire project, commit those results, and then rely on per-file format on save from there on out.
Note that in all of these cases, the formatter will only run if your code is syntactically correct. If the formatter is seemingly no longer working, check your code for syntax errors.