Search code examples
rdevtoolsroxygen2

read roxygen2 @importFrom when reading R code


Goal

I would like to read an R function into the environment and import it's dependent functions listed in roxygen2 in-line documentation. This mimics the behavior of loading an R package, but does so for R scripts that are not part of a package.

How can an R function outside of a package be sourced & import the functions upon which it depends as happens in packages?

reprex

Example R function (not part of a package)

gh_file.R is an R function that downloads files from GitHub repositories. It is not part of a package, instead it is available as a GitHub gist.

A glance at the roxygen2 comments shows that gh_file.R should import several functions from other packages.

#' @importFrom gh gh
#' @importFrom stringi stri_match_all_regex
#' @importFrom purrr %||% keep
#' @importFrom base64enc  base64decode

Attempt read + import of dependent functions

# read in the R function from GitHub Gist
library(devtools)
devtools::source_gist("gist.github.com/noamross/73944d85cad545ae89efaa4d90b049db",
                      filename = "gh_file.R")

# attempt to use new R function to import a .csv file from GitHub (FAILS)
ghurl <- "github.com/wpetry/RockyMountainAphids/blob/master/Palmer1952hostlist.csv"
aphids <- read.csv(text = readBin(gh_file(url = ghurl, to_disk = FALSE)))

returns error:

Error in stri_match_all_regex(url, "(github\\.com/)?([^\\/]+)/([^\\/]+)/[^\\/]+/([^\\/]+)/([^\\?]+)") : 
could not find function "stri_match_all_regex"

Desired behavior (requires loading all packages from which R function imports)

# load packages from which gh_file.R function imports
library(gh)
library(stringi)
library(purrr)
library(base64enc)

aphids <- read.csv(text = readBin(gh_file(url = ghurl, to_disk = FALSE), "character"))
head(aphids)

works!

              host host_common               aphid
1   Abies concolor   White Fir     Cinara curvipes
2   Abies concolor   White Fir Cinara occidentalis
3 Abies lasiocarpa  Alpine Fir     Cinara curvipes
4 Abies lasiocarpa  Alpine Fir  Cinara lasiocarpae
5 Abies lasiocarpa  Alpine Fir Cinara occidentalis
6 Abies lasiocarpa  Alpine Fir  Mindarus abietinus

Solution

  • You can parse the script for a list of library and then load them.

    loadlib <- function(fpath) {
        l <- readLines(fpath)
        libs <- lapply(strsplit(l[grepl("@import", l)], " "), `[[`, 3)
        lapply(libs, library, character.only=TRUE)
    }
    
    loadlib("gh_file.R")