Nothing
#' Update Collate field in DESCRIPTION
#'
#' @description
#' By default, R loads files in alphabetical order. This is fine if your
#' package doesn't have any cross-file dependencies, but if you're using a tool
#' like S4, you'll need to make sure that classes are loaded before subclasses
#' and generics are defined before methods. You can do this by hand by setting
#' the `Collate` field in the `DESCRIPTION` or automate it by using `@include`
#' tags to specify the cross-file dependencies:
#'
#' ```R
#' #' @include before.R
#' NULL
#' ```
#'
#' If there are no `@include` tags, roxygen2 will leave the `Collate` field as
#' is. This makes it easier to use roxygen2 with an existing collate directive,
#' but if you remove all your `@include` tags, you'll need to also
#' manually delete the collate field.
#'
#' Generally, you should not need to run this function yourself; it will be
#' run automatically by any package that needs to load your R files in
#' collation order.
#'
#' `update_collate()` is not not technically a [roclet], like [rd_roclet()]
#' and [namespace_roclet()], because you have to be able to load the pacakge
#' before you can process it with roclets. However, because it was historical
#' implemented as a roclet, it's still controlled by the `roclets` argument of
#' [roxygenize()].
#'
#' @param base_path Path to package directory.
#' @examples
#' #' If `example-a.R`, `example-b.R` and `example-c.R` live in `R/`
#' #' and we're in `example-a.R`, then the following @include tag
#' #' ensures that example-b and example-c are sourced before example-a.
#' #' @include example-b.R example-c.R
#' NULL
#' @export
#' @aliases @include
update_collate <- function(base_path) {
check_string(base_path)
if (!file.exists(base_path)) {
cli::cli_abort("{.path {base_path}} doesn't exist.")
}
new <- generate_collate(file.path(base_path, "R"))
if (is.null(new)) {
return(invisible())
}
desc_path <- file.path(base_path, "DESCRIPTION")
old <- desc::desc_get_collate(file = desc_path)
if (!identical(old, new)) {
cli::cli_inform("Updating collate directive in {.path {desc_path}}")
desc::desc_set_collate(new, file = desc_path)
}
invisible()
}
generate_collate <- function(base_path) {
paths <- sort_c(dir(base_path, pattern = "[.][Rr]$", full.names = TRUE))
includes <- lapply(paths, find_and_filter_includes, paths = basename(paths))
names(includes) <- paths
n <- sum(map_int(includes, length))
if (n == 0) {
return()
}
topo <- TopoSort$new()
for (path in paths) {
file <- base_path(path, base_path)
topo$add(file)
for (include in includes[[path]]) {
topo$add_ancestor(file, include)
}
}
topo$sort()
}
find_and_filter_includes <- function(path, paths) {
includes <- find_includes(path)
invalid <- setdiff(includes, paths)
if (length(invalid) > 0) {
for (include in invalid) {
path <- cli::style_hyperlink(basename(path), paste0("file://", path))
cli::cli_inform(c(
x = "{path}: unknown path in `@include {invalid}`."
))
}
}
intersect(includes, paths)
}
base_path <- function(path, base) {
path <- normalizePath(path, winslash = "/")
base <- normalizePath(base, winslash = "/")
sub(paste0(base, "/"), "", path, fixed = TRUE)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.