|
79 | 79 | #' are listed under Suggests rather than Imports since this workflow is |
80 | 80 | #' only needed for the WikiAves data source and depends on a local Chrome- |
81 | 81 | #' or Chromium-based browser installation and a usable display (e.g. the |
82 | | -#' `DISPLAY` environment variable on Linux). |
| 82 | +#' `DISPLAY` environment variable on Linux). If either package is missing, |
| 83 | +#' in an interactive session the function asks for permission before |
| 84 | +#' installing them via `install.packages()`; declining stops the function |
| 85 | +#' with instructions to install manually. In a non-interactive session |
| 86 | +#' (e.g. within `R CMD check`, CI, or `Rscript`), the function cannot |
| 87 | +#' prompt and instead stops immediately with the same instructions. |
83 | 88 | #' |
84 | 89 | #' **Browser auto-detection.** When `chrome_bin = NULL` (the default), the |
85 | 90 | #' function first checks whether the **chromote** package happens to be |
@@ -202,15 +207,65 @@ access_wikiaves <- function( |
202 | 207 | return(invisible(NULL)) |
203 | 208 | } |
204 | 209 |
|
205 | | - if ( |
206 | | - !requireNamespace("websocket", quietly = TRUE) || |
207 | | - !requireNamespace("later", quietly = TRUE) |
208 | | - ) { |
209 | | - stop( |
210 | | - "Packages 'websocket' and 'later' are required for this function. ", |
211 | | - "Install them with: install.packages(c('websocket', 'later'))", |
212 | | - call. = FALSE |
| 210 | + ## check for required optional packages, offering to install them |
| 211 | + ## interactively rather than just stopping |
| 212 | + required_pkgs <- c("websocket", "later") |
| 213 | + missing_pkgs <- required_pkgs[ |
| 214 | + !vapply(required_pkgs, requireNamespace, logical(1), quietly = TRUE) |
| 215 | + ] |
| 216 | + |
| 217 | + if (length(missing_pkgs) > 0) { |
| 218 | + install_cmd <- paste0( |
| 219 | + "install.packages(c(", |
| 220 | + paste(sprintf('"%s"', missing_pkgs), collapse = ", "), |
| 221 | + "))" |
213 | 222 | ) |
| 223 | + |
| 224 | + if (interactive()) { |
| 225 | + ans <- utils::menu( |
| 226 | + choices = c("Yes", "No"), |
| 227 | + title = paste0( |
| 228 | + "The following package(s) are required but not installed: ", |
| 229 | + paste(missing_pkgs, collapse = ", "), |
| 230 | + ".\nInstall them now?" |
| 231 | + ) |
| 232 | + ) |
| 233 | + |
| 234 | + if (ans == 1) { |
| 235 | + utils::install.packages(missing_pkgs) |
| 236 | + |
| 237 | + # re-check in case installation failed silently for any of them |
| 238 | + still_missing <- missing_pkgs[ |
| 239 | + !vapply(missing_pkgs, requireNamespace, logical(1), quietly = TRUE) |
| 240 | + ] |
| 241 | + |
| 242 | + if (length(still_missing) > 0) { |
| 243 | + stop( |
| 244 | + "Failed to install: ", |
| 245 | + paste(still_missing, collapse = ", "), |
| 246 | + ". Please install manually with:\n ", |
| 247 | + install_cmd, |
| 248 | + call. = FALSE |
| 249 | + ) |
| 250 | + } |
| 251 | + } else { |
| 252 | + stop( |
| 253 | + "Cannot proceed without required package(s). Install them with:\n ", |
| 254 | + install_cmd, |
| 255 | + call. = FALSE |
| 256 | + ) |
| 257 | + } |
| 258 | + } else { |
| 259 | + # non-interactive sessions (CI, R CMD check, Rscript, etc.) cannot |
| 260 | + # be prompted, so fail immediately with clear instructions instead |
| 261 | + stop( |
| 262 | + "Package(s) '", |
| 263 | + paste(missing_pkgs, collapse = "', '"), |
| 264 | + "' are required for this function. Install them with:\n ", |
| 265 | + install_cmd, |
| 266 | + call. = FALSE |
| 267 | + ) |
| 268 | + } |
214 | 269 | } |
215 | 270 |
|
216 | 271 | os_type <- .Platform$OS.type # "windows" or "unix" |
|
0 commit comments