Skip to content

Commit e6501b9

Browse files
use_air() also turns on "format on save" for qmd + other updates (#2136)
* use_air() also turns on "format on save" for qmd + other updates * Use modifyList() * Be a bit more robust * Apply suggestions from code review Co-authored-by: Davis Vaughan <davis@rstudio.com> --------- Co-authored-by: Davis Vaughan <davis@rstudio.com>
1 parent 9ba926d commit e6501b9

6 files changed

Lines changed: 59 additions & 35 deletions

File tree

.Rbuildignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@
2424
^internal$
2525
^revdep-cloud$
2626
^CRAN-SUBMISSION$
27-
^[\.]?air\.toml$
2827
^\.vscode$
28+
^[.]?air[.]toml$

.vscode/settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,9 @@
22
"[r]": {
33
"editor.formatOnSave": true,
44
"editor.defaultFormatter": "Posit.air-vscode"
5+
},
6+
"[quarto]": {
7+
"editor.formatOnSave": true,
8+
"editor.defaultFormatter": "quarto.quarto"
59
}
610
}

R/air.R

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313
#' used by the Air extension installed through either VS Code or Positron, see
1414
#' the Installation section for more details. Specifically it:
1515
#'
16-
#' - Sets `editor.formatOnSave = true` for R files to enable formatting on
17-
#' every save.
16+
#' - Sets `editor.formatOnSave = true` for R and Quarto files to enable
17+
#' formatting on every save.
1818
#'
1919
#' - Sets `editor.defaultFormatter` to Air for R files to ensure that Air is
20-
#' always selected as the formatter for this project.
20+
#' always selected as the formatter for this project. Likewise, sets the
21+
#' default formatter for Quarto.
2122
#'
2223
#' - Sets the Air extension as a "recommended" extension for this project,
2324
#' which triggers a notification for contributors coming to this project
@@ -31,20 +32,21 @@
3132
#' may prefer another editor.
3233
#'
3334
#' Note that `use_air()` does not actually invoke Air, it just configures your
34-
#' project with the recommended settings. Consult the [editors
35+
#' project with the recommended settings. Consult [Air's editors
3536
#' guide](https://posit-dev.github.io/air/editors.html) to learn how to invoke
3637
#' Air in your preferred editor.
3738
#'
3839
#' ## Installation
3940
#'
40-
#' Note that this setup does not install an Air binary, so there is an
41+
#' Note that this setup does not install an Air binary, so there may be an
4142
#' additional manual step you must take before using Air for the first time:
4243
#'
4344
#' - For RStudio, follow the [installation
4445
#' guide](https://posit-dev.github.io/air/editor-rstudio.html).
4546
#'
46-
#' - For Positron, install the [OpenVSX
47-
#' Extension](https://open-vsx.org/extension/posit/air-vscode).
47+
#' - For Positron, the [Air extension](https://open-vsx.org/extension/posit/air-vscode)
48+
#' is installed by default and that already includes the Air binary. A typical
49+
#' Positron user does not need to do anything to install Air.
4850
#'
4951
#' - For VS Code, install the [VS Code
5052
#' Extension](https://marketplace.visualstudio.com/items?itemName=Posit.air-vscode).
@@ -118,7 +120,7 @@ create_air_toml <- function(ignore = FALSE) {
118120

119121
air_toml_regex <- function() {
120122
# Pre-escaped regex allowing both `air.toml` and `.air.toml`
121-
"^[\\.]?air\\.toml$"
123+
"^[.]?air[.]toml$"
122124
}
123125

124126
create_vscode_json_file <- function(name) {
@@ -142,20 +144,19 @@ create_vscode_json_file <- function(name) {
142144
}
143145

144146
write_air_vscode_settings_json <- function(path) {
145-
settings <- jsonlite::read_json(path)
146-
settings_r <- settings[["[r]"]]
147-
148-
if (is.null(settings_r)) {
149-
# Mock it
150-
settings_r <- set_names(list())
151-
}
152-
153-
# Set these regardless of their previous values. Assume that calling
154-
# `use_air()` is an explicit request to opt in to these settings.
155-
settings_r[["editor.formatOnSave"]] <- TRUE
156-
settings_r[["editor.defaultFormatter"]] <- "Posit.air-vscode"
157-
158-
settings[["[r]"]] <- settings_r
147+
settings <- jsonlite::read_json(path) %||% set_names(list())
148+
149+
patch <- list(
150+
`[r]` = list(
151+
"editor.formatOnSave" = TRUE,
152+
"editor.defaultFormatter" = "Posit.air-vscode"
153+
),
154+
`[quarto]` = list(
155+
"editor.formatOnSave" = TRUE,
156+
"editor.defaultFormatter" = "quarto.quarto"
157+
)
158+
)
159+
settings <- utils::modifyList(settings, patch)
159160

160161
write_vscode_json(x = settings, path = path)
161162
}

man/use_air.Rd

Lines changed: 9 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/_snaps/air.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use_air()
55
Message
66
v Creating 'air.toml'.
7-
v Adding "^[\\.]?air\\.toml$" to '.Rbuildignore'.
7+
v Adding "^[.]?air[.]toml$" to '.Rbuildignore'.
88
v Creating '.vscode/'.
99
v Adding "^\\.vscode$" to '.Rbuildignore'.
1010
v Creating '.vscode/settings.json'.
@@ -21,6 +21,10 @@
2121
"[r]": {
2222
"editor.formatOnSave": true,
2323
"editor.defaultFormatter": "Posit.air-vscode"
24+
},
25+
"[quarto]": {
26+
"editor.formatOnSave": true,
27+
"editor.defaultFormatter": "quarto.quarto"
2428
}
2529
}
2630

tests/testthat/test-air.R

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ test_that("creates correct default package files", {
1717
settings[["[r]"]][["editor.defaultFormatter"]],
1818
"Posit.air-vscode"
1919
)
20+
expect_true(settings[["[quarto]"]][["editor.formatOnSave"]])
21+
expect_identical(
22+
settings[["[quarto]"]][["editor.defaultFormatter"]],
23+
"quarto.quarto"
24+
)
2025

2126
settings <- jsonlite::read_json(proj_path(".vscode", "extensions.json"))
2227
recommendations <- settings[["recommendations"]]
@@ -48,6 +53,11 @@ test_that("creates correct default project files", {
4853
settings[["[r]"]][["editor.defaultFormatter"]],
4954
"Posit.air-vscode"
5055
)
56+
expect_true(settings[["[quarto]"]][["editor.formatOnSave"]])
57+
expect_identical(
58+
settings[["[quarto]"]][["editor.defaultFormatter"]],
59+
"quarto.quarto"
60+
)
5161

5262
settings <- jsonlite::read_json(proj_path(".vscode", "extensions.json"))
5363
recommendations <- settings[["recommendations"]]
@@ -68,6 +78,9 @@ test_that("respects existing `settings.json`, but overwrites settings we own", {
6878
),
6979
"[rust]" = list(
7080
"editor.formatOnSave" = FALSE
81+
),
82+
"[quarto]" = list(
83+
"editor.wordWrap" = "wordWrapColumn"
7184
)
7285
)
7386

@@ -76,11 +89,10 @@ test_that("respects existing `settings.json`, but overwrites settings we own", {
7689
use_air()
7790

7891
# Here is all that should change
79-
settings[["[r]"]] <- list(
80-
# Overwrite both of these to Air's recommendations
81-
"editor.formatOnSave" = TRUE,
82-
"editor.defaultFormatter" = "Posit.air-vscode"
83-
)
92+
settings[["[r]"]][["editor.formatOnSave"]] <- TRUE
93+
settings[["[r]"]][["editor.defaultFormatter"]] <- "Posit.air-vscode"
94+
settings[["[quarto]"]][["editor.formatOnSave"]] <- TRUE
95+
settings[["[quarto]"]][["editor.defaultFormatter"]] <- "quarto.quarto"
8496

8597
actual_settings <- jsonlite::read_json(path)
8698

0 commit comments

Comments
 (0)