|
| 1 | +#' Set up VS Code configuration for an rextendr project |
| 2 | +#' |
| 3 | +#' @description This creates a `.vscode` folder (if needed) and populates it with a |
| 4 | +#' `settings.json` template. If already exists, it will be updated to include |
| 5 | +#' the `rust-analyzer.linkedProjects` setting. |
| 6 | +#' |
| 7 | +#' @param quiet If `TRUE`, suppress messages. |
| 8 | +#' @param overwrite If `TRUE`, overwrite existing files. |
| 9 | +#' @details Rust-Analyzer VSCode extension looks for a `Cargo.toml` file in the |
| 10 | +#' workspace root by default. This function creates a `.vscode` folder and |
| 11 | +#' populates it with a `settings.json` file that sets the workspace root to |
| 12 | +#' the `src` directory of the package. This allows you to open the package |
| 13 | +#' directory in VSCode and have the Rust-Analyzer extension work correctly. |
| 14 | +#' @return `TRUE` (invisibly) if the settings file was created or updated. |
| 15 | +#' @export |
| 16 | +use_vscode <- function(quiet = FALSE, overwrite = FALSE) { |
| 17 | + if (!dir.exists(".vscode")) { |
| 18 | + dir.create(".vscode") |
| 19 | + } |
| 20 | + |
| 21 | + usethis::use_build_ignore(file.path(".vscode")) |
| 22 | + |
| 23 | + settings_path <- file.path(".vscode", "settings.json") |
| 24 | + rust_analyzer_path <- "${workspaceFolder}/src/rust/Cargo.toml" |
| 25 | + files_associations <- list( |
| 26 | + "Makevars.in" = "makefile", |
| 27 | + "Makevars.win" = "makefile", |
| 28 | + "configure" = "shellscript", |
| 29 | + "configure.win" = "shellscript", |
| 30 | + "cleanup" = "shellscript", |
| 31 | + "cleanup.win" = "shellscript" |
| 32 | + ) |
| 33 | + |
| 34 | + if (file.exists(settings_path) && !overwrite) { |
| 35 | + if (!quiet) message("Updating existing .vscode/settings.json") |
| 36 | + |
| 37 | + # settings.json accepts trailing commas before braces and brackets and {jsonlite} doesn't dig that |
| 38 | + tryCatch({ |
| 39 | + settings <- jsonlite::read_json(settings_path) |
| 40 | + }, error = function(e) { |
| 41 | + if (grepl("parse error", e$message)) { |
| 42 | + stop( |
| 43 | + "Could not parse .vscode/settings.json. Do you have a trailing comma before braces or brackets?\n", |
| 44 | + "Original error: : ", e$message |
| 45 | + ) |
| 46 | + } else { |
| 47 | + stop(e$message) |
| 48 | + } |
| 49 | + }) |
| 50 | + |
| 51 | + # checking and updating cargo.toml path for Rust-Analyzer |
| 52 | + if (!"rust-analyzer.linkedProjects" %in% names(settings)) { |
| 53 | + settings[["rust-analyzer.linkedProjects"]] <- list(rust_analyzer_path) |
| 54 | + } else if (!rust_analyzer_path %in% settings[["rust-analyzer.linkedProjects"]]) { |
| 55 | + settings[["rust-analyzer.linkedProjects"]] <- c( |
| 56 | + settings[["rust-analyzer.linkedProjects"]], |
| 57 | + rust_analyzer_path |
| 58 | + ) |
| 59 | + } |
| 60 | + |
| 61 | + # checking and updating files associations |
| 62 | + if (!"files.associations" %in% names(settings)) { |
| 63 | + settings[["files.associations"]] <- files_associations |
| 64 | + } else { |
| 65 | + current_assoc <- settings[["files.associations"]] |
| 66 | + for (name in names(files_associations)) { |
| 67 | + current_assoc[[name]] <- files_associations[[name]] |
| 68 | + } |
| 69 | + settings[["files.associations"]] <- current_assoc |
| 70 | + } |
| 71 | + |
| 72 | + jsonlite::write_json( |
| 73 | + settings, |
| 74 | + settings_path, |
| 75 | + auto_unbox = TRUE, |
| 76 | + pretty = TRUE |
| 77 | + ) |
| 78 | + } else { |
| 79 | + use_rextendr_template( |
| 80 | + "settings.json", |
| 81 | + save_as = settings_path, |
| 82 | + quiet = quiet, |
| 83 | + overwrite = overwrite |
| 84 | + ) |
| 85 | + } |
| 86 | + |
| 87 | + invisible(TRUE) |
| 88 | +} |
| 89 | + |
| 90 | +#' @rdname use_vscode |
| 91 | +#' @export |
| 92 | +use_positron <- use_vscode |
0 commit comments