Skip to content

Commit

Permalink
render_docs(parallel = TRUE) using future.apply (#96)
Browse files Browse the repository at this point in the history
Co-authored-by: Etienne Bacher <[email protected]>
  • Loading branch information
vincentarelbundock and etiennebacher authored Nov 20, 2023
1 parent 0205857 commit 28b9669
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 30 deletions.
4 changes: 3 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Type: Package
Package: altdoc
Title: Package Documentation Websites with 'Docsify.js', 'Docute', or 'Mkdocs
Version: 0.2.2.9006
Version: 0.2.2.9007
Authors@R:
c(person(given = "Etienne",
family = "Bacher",
Expand Down Expand Up @@ -29,6 +29,8 @@ Imports:
xml2
Suggests:
covr,
future,
future.apply,
knitr,
rstudioapi,
servr,
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Breaking changes:
New:

* Support for Quarto vignettes (.qmd) stored in the `vignettes/` folder.
* `render_docs(parallel=TRUE)` uses `future` to parallelize the rendering of vignettes and man pages.
* Settings files are now permanently stored in the `altdoc/` directory. These files can be edited manually to customize the website.
* Major internal changes to the .Rd -> .md conversion system. We now use Quarto to convert man pages and execute examples, and the man pages are stored in separate markdown files instead of combined in a single large file.
* `mkdocs` now behaves like the other documentation generators and stores its files in `docs/`. This means that `mkdocs` websites can be deployed to Github Pages.
Expand Down
35 changes: 21 additions & 14 deletions R/man.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Convert and unite .Rd files to 'docs/reference.md'.
.import_man <- function(path = ".", verbose = FALSE) {
.import_man <- function(path = ".", verbose = FALSE, parallel = FALSE) {
# source and target file paths
# using here::here() breaks tests, so we rely on directory check higher up
man_source <- list.files(path = "man", pattern = "\\.Rd$")
Expand All @@ -9,26 +9,20 @@

n <- length(man_source)

# can't use message_info with {}
cli::cli_alert_info("Found {n} man page{?s} to convert.")
i <- 0
cli::cli_progress_step("Converting {cli::qty(n)}man page{?s}: {i}/{n}", spinner = TRUE)

conversion_worked <- vector(length = n)
cli::cli_alert_info("Found {n} man page{?s} to convert.")

# process man pages one by one
for (i in seq_along(man_source)) {
f <- man_source[i]
render_one_man <- function(fn) {
# fs::path_ext_set breaks filenames with dots, ex: 'foo.bar.Rd'
origin_Rd <- fs::path_join(c("man", paste0(f, ".Rd")))
origin_Rd <- fs::path_join(c("man", paste0(fn, ".Rd")))
destination_dir <- fs::path_join(c(.doc_path(path = "."), "man"))
destination_qmd <- fs::path_join(c(destination_dir, paste0(f, ".qmd")))
destination_md <- fs::path_join(c(destination_dir, paste0(f, ".md")))
destination_qmd <- fs::path_join(c(destination_dir, paste0(fn, ".qmd")))
destination_md <- fs::path_join(c(destination_dir, paste0(fn, ".md")))
fs::dir_create(destination_dir)
.rd2qmd(origin_Rd, destination_dir)
conversion_worked[i] <- .qmd2md(destination_qmd, destination_dir, verbose = verbose)
worked <- .qmd2md(destination_qmd, destination_dir, verbose = verbose)
fs::file_delete(destination_qmd)

# section headings are too deeply nested by default
# this is a hack because it may remove one # from comments. But that's
# probably not the end of the world, because the line stick stays commented
Expand All @@ -38,8 +32,21 @@
tmp <- gsub("^##", "#", tmp)
writeLines(tmp, destination_md)
}
return(worked)
}

cli::cli_progress_update(inc = 1)
if (isTRUE(parallel)) {
.assert_dependency("future.apply", install = TRUE)
conversion_worked <- future.apply::future_sapply(man_source, render_one_man, future.seed = NULL)
} else {
# can't use message_info with {}
i <- 0
cli::cli_progress_step("Converting {cli::qty(n)}man page{?s}: {i}/{n}", spinner = TRUE)
conversion_worked <- vector(length = n)
for (i in seq_along(man_source)) {
conversion_worked[i] <- render_one_man(man_source[i])
cli::cli_progress_update(inc = 1)
}
}

successes <- which(conversion_worked == TRUE)
Expand Down
12 changes: 9 additions & 3 deletions R/render_docs.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#' overwrites the files in the 'docs/' folder.
#'
#' @param verbose Logical. Print Rmarkdown or Quarto rendering output.
#' @param parallel Logical. Render man pages and vignettes in parallel using the `future` framework. In addition to setting this argument to TRUE, users must define the parallelism plan in `future`. See the examples section below.
#' @inheritParams setup_docs
#' @export
#'
Expand All @@ -15,8 +16,13 @@
#'
#' render_docs()
#'
#' # parallel rendering
#' library(future)
#' plan(multicore)
#' render_docs(parallel = TRUE)
#'
#' }
render_docs <- function(path = ".", verbose = FALSE) {
render_docs <- function(path = ".", verbose = FALSE, parallel = FALSE) {

dir_altdoc <- fs::path_join(c(path, "altdoc"))
if (!fs::dir_exists(dir_altdoc) || length(fs::dir_ls(dir_altdoc)) == 0) {
Expand All @@ -41,11 +47,11 @@ render_docs <- function(path = ".", verbose = FALSE) {

# Update functions reference
cli::cli_h1("Man pages")
.import_man(path = path, verbose = verbose)
.import_man(path = path, verbose = verbose, parallel = parallel)

# Update vignettes
cli::cli_h1("Vignettes")
.import_vignettes(path, verbose = verbose)
.import_vignettes(path, verbose = verbose, parallel = parallel)

cli::cli_h1("Update HTML")
.import_settings(path = path, doctype = .doc_type(path))
Expand Down
26 changes: 16 additions & 10 deletions R/vignettes.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# that it is "md_document" instead of "html_vignette"
# * render all of the modified .Rmd files (in "docs/vignettes"), which produce .md files.

.import_vignettes <- function(path = path, verbose = FALSE) {
.import_vignettes <- function(path = path, verbose = FALSE, parallel = FALSE) {
# source directory
src_dir <- fs::path_abs("vignettes", start = path)
if (!fs::dir_exists(src_dir) || .folder_is_empty(src_dir)) {
Expand Down Expand Up @@ -45,22 +45,15 @@

n <- length(src_files)

# can't use message_info with {}
cli::cli_alert_info("Found {n} vignette{?s} to convert.")
i <- 0
cli::cli_progress_step("Converting {cli::qty(n)}vignette{?s}: {i}/{n}", spinner = TRUE)

conversion_worked <- vector(length = n)

fs::dir_copy(src_dir, tar_dir, overwrite = TRUE)

for (i in seq_along(src_files)) {
render_one_vignette <- function(i) {
# only process new or modified vignettes
origin <- fs::path_join(c(src_dir, src_files[i]))
destination <- fs::path_join(c(tar_dir, src_files[i]))

fs::file_copy(origin, destination, overwrite = TRUE)

if (fs::path_ext(origin) == "md") {
fs::file_copy(origin, tar_dir, overwrite = TRUE)

Expand All @@ -73,7 +66,20 @@
# conversion_worked[i] <- .rmd2md(origin, tar_dir, path = path, verbose = verbose)
# cli::cli_progress_update()
} else {
conversion_worked[i] <- .qmd2md(origin, tar_dir, verbose = verbose)
worked <- .qmd2md(origin, tar_dir, verbose = verbose)
}
return(worked)
}

if (isTRUE(parallel)) {
.assert_dependency("future.apply", install = TRUE)
conversion_worked <- future.apply::future_sapply(seq_along(src_files), render_one_vignette, future.seed = NULL)
} else {
i <- 0
cli::cli_progress_step("Converting {cli::qty(n)}vignette{?s}: {i}/{n}", spinner = TRUE)
conversion_worked <- vector(length = n)
for (i in seq_along(src_files)) {
conversion_worked[i] <- render_one_vignette(i)
cli::cli_progress_update()
}
}
Expand Down
18 changes: 17 additions & 1 deletion docs/man/render_docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ modifies and overwrites the files in the ‘docs/’ folder.

## Usage

<pre><code class='language-R'>render_docs(path = ".", verbose = FALSE)
<pre><code class='language-R'>render_docs(path = ".", verbose = FALSE, parallel = FALSE)
</code></pre>

## Arguments
Expand All @@ -33,6 +33,17 @@ Path to the package root directory.
Logical. Print Rmarkdown or Quarto rendering output.
</td>
</tr>
<tr>
<td style="white-space: nowrap; font-family: monospace; vertical-align: top">
<code id="render_docs_:_parallel">parallel</code>
</td>
<td>
Logical. Render man pages and vignettes in parallel using the
<code>future</code> framework. In addition to setting this argument to
TRUE, users must define the parallelism plan in <code>future</code>. See
the examples section below.
</td>
</tr>
</table>

## Value
Expand All @@ -48,5 +59,10 @@ if (interactive()) {

render_docs()

# parallel rendering
library(future)
plan(multicore)
render_docs(parallel = TRUE)

}
```
9 changes: 8 additions & 1 deletion man/render_docs.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 28b9669

Please sign in to comment.