Skip to content

Instantly share code, notes, and snippets.

@richierocks
Created December 8, 2015 11:26
Show Gist options
  • Save richierocks/21b29f13320716ba6fca to your computer and use it in GitHub Desktop.
Save richierocks/21b29f13320716ba6fca to your computer and use it in GitHub Desktop.
Generate R pkg NAMESPACE from roxygen tags, to avoid issue r-lib/roxygen2#372
# Workaround for roxygen2 issue. See:
# https://github.com/klutometis/roxygen/issues/372
# https://stat.ethz.ch/pipermail/r-package-devel/2015q3/000456.html
library(magrittr)
library(stringi)
library(assertive.properties)
library(assertive.code)
r_files <- dir("R", full.names = TRUE)
lines_by_file <- r_files %>%
setNames(basename(r_files)) %>%
lapply(readLines)
# Search files for lines like "#' @importFrom pkg fn"
namespace_importFrom <- lines_by_file %>%
lapply(
function(lines)
{
importFrom_lines <- lines[stri_detect_regex(lines, "^#' *@importFrom")]
if(is_empty(importFrom_lines))
{
return(character())
}
matches <- stri_match_first_regex(
importFrom_lines,
"^#' *@importFrom +([[:alnum:]._]+) +([[:graph:]]+)"
)
pkgs <- matches[, 2]
fns <- matches[, 3]
# non-standard names like mutators need enquoting
ok <- is_valid_variable_name(fns)
fns[!ok] <- shQuote(fns[!ok])
paste0("importFrom(", pkgs, ",", fns, ")")
}
)
# Search files for lines like "#' @export", then
# find the next line that doesn't start "#'", then
# see if that contains "function(", then
# extract the function name
namespace_export <- lines_by_file %>%
lapply(
function(lines)
{
export_indicies <- stri_detect_regex(lines, "^#' *@export") %>%
which
if(is_empty(export_indicies))
{
return(character())
}
not_roxygen_indicies <- stri_detect_regex(lines, "^#'") %>%
not %>%
which
object_indicies <- vapply(
export_indicies,
function(i)
{
min(not_roxygen_indicies[not_roxygen_indicies > i])
},
integer(1)
)
object_lines <- lines[object_indicies]
function_lines <- object_lines[stri_detect_fixed(object_lines, "function(")]
matches <- stri_match_first_regex(
function_lines,
" *([[:graph:]]+) *(?:<-|=) *function"
)
paste0("export(", matches[, 2], ")")
}
)
# Combine importFroms and exports
# TODO: For more general case, should also find whole package imports
namespace <- c(namespace_importFrom, namespace_export) %>%
unlist(use.names = FALSE) %>%
unique
# Write the NAMESPACE file
writeLines(namespace, "NAMESPACE")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment