1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
#' Check if RStudio is running
#'
#' Check if RStudio is running.
#'
#' @aliases isAvailable verifyAvailable
#'
#' @param version_needed An optional version specification. If supplied, ensures
#' that RStudio is at least that version.
#'
#' @param child_ok Boolean; check if the current R process is a child process of
#' the main RStudio session? This can be useful for e.g. RStudio Jobs, where
#' you'd like to communicate back with the main R session from a child process
#' through \code{rstudioapi}.
#'
#' @return \code{isAvailable} a boolean; \code{verifyAvailable} an error message
#' if RStudio is not running
#'
#' @examples
#'
#' rstudioapi::isAvailable()
#' \dontrun{rstudioapi::verifyAvailable()}
#'
#' @export
isAvailable <- function(version_needed = NULL, child_ok = FALSE) {
if (child_ok && isJob())
return(callRemote(sys.call(), parent.frame()))
identical(.Platform$GUI, "RStudio") && version_ok(version_needed)
}
version_ok <- function(version = NULL) {
if (is.null(version)) return(TRUE)
getVersion() >= version
}
#' @rdname isAvailable
#' @export
verifyAvailable <- function(version_needed = NULL) {
if (!isAvailable()) stop("RStudio not running", call. = FALSE)
if (!version_ok(version_needed)) {
stop("Need at least version ", version_needed, " of RStudio. ",
"Currently running ", getVersion(), call. = FALSE)
}
invisible(TRUE)
}
#' Determine the version of RStudio
#'
#' Use `getVersion()` to determine the current version of RStudio.
#' This can be useful for \R packages which need to gate certain functionality
#' based on the version of RStudio currently available.
#'
#' @returns A `"numeric_version"` object, giving the version of RStudio in use.
#'
#' @export
getVersion <- function() {
# use API if available
if (hasFun("getVersion"))
return(callFun("getVersion"))
# use fallback if not
verifyAvailable()
base <- .BaseNamespaceEnv
version <- base$.Call("rs_rstudioVersion", PACKAGE = "(embedding)")
package_version(version)
}
#' Report whether RStudio Desktop or RStudio Server is in use
#'
#' Use `getMode()` if you need to differentiate between server
#' and desktop installations of RStudio.
#'
#' @returns "desktop" for RStudio Desktop installations, and
#' "server" for RStudio Server / RStudio Workbench installations.
#'
#' @export
getMode <- function() {
# use API if available
if (hasFun("getMode"))
return(callFun("getMode"))
# use fallback if not
verifyAvailable()
rstudio <- as.environment("tools:rstudio")
if (rstudio$.rs.isDesktop()) "desktop" else "server"
}
#' Call an RStudio API function
#'
#' This function will return an error if RStudio is not running, or the
#' function is not available. If you want to fall back to different behavior,
#' use \code{\link{hasFun}}.
#'
#'
#' @param fname name of the RStudio function to call.
#' @param ... Other arguments passed on to the function
#' @examples
#'
#' if (rstudioapi::isAvailable()) {
#' rstudioapi::callFun("versionInfo")
#' }
#'
#' @export callFun
callFun <- function(fname, ...) {
if (isJob())
return(callRemote(sys.call(), parent.frame()))
verifyAvailable()
# get reference to RStudio function
f <- tryCatch(findFun(fname, mode = "function"), error = identity)
if (inherits(f, "error"))
stop("Function ", fname, " not found in RStudio", call. = FALSE)
# drop arguments that aren't accepted by RStudio
# (ensure backwards-compatibility with older versions of RStudio)
args <- list(...)
if (!"..." %in% names(formals(f))) {
args <- checkApiArguments(fname, f, args)
if (length(args) > length(formals(f)))
length(args) <- length(formals(f))
}
# invoke the function
do.call(f, args)
}
#' Exists/get for RStudio functions
#'
#' These are specialized versions of \code{\link[base]{get}} and
#' \code{\link[base]{exists}} that look in the rstudio package namespace. If
#' RStudio is not running, \code{hasFun} will return \code{FALSE}.
#'
#'
#' @aliases hasFun findFun
#' @param name name of object to look for
#' @param version_needed An optional version specification. If supplied,
#' ensures that RStudio is at least that version. This is useful if function
#' behavior has changed over time.
#' @param ... other arguments passed on to \code{\link[base]{exists}} and
#' \code{\link[base]{get}}
#' @examples
#'
#' rstudioapi::hasFun("viewer")
#'
#' @export hasFun
hasFun <- function(name, version_needed = NULL, ...) {
if (!isAvailable(version_needed))
return(FALSE)
if (usingTools())
return(exists(toolsName(name), toolsEnv(), ...))
exists(name, envir = asNamespace("rstudio"), ...)
}
#' @export
#' @rdname hasFun
findFun <- function(name, version_needed = NULL, ...) {
verifyAvailable(version_needed)
if (usingTools())
get(toolsName(name), toolsEnv(), ...)
else
get(name, envir = asNamespace("rstudio"), ...)
}
usingTools <- function() {
exists(toolsName("versionInfo"), envir = toolsEnv())
}
toolsName <- function(name) {
paste(".rs.api.", name, sep = "")
}
toolsEnv <- function() {
as.environment(match("tools:rstudio", search()))
}
|