generated from NEFSC/NEFSC-Template
-
Notifications
You must be signed in to change notification settings - Fork 4
/
buildRPackage.R
115 lines (88 loc) · 6.12 KB
/
buildRPackage.R
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
# R package build script: MUST be run in cloned copy of repository.
library(tidyverse)
##### ID R scripts with function documentation or alternatively create buildFiles vector with the names of ONLY the files to be added/updated in the R package here #####
# Find all .R scripts
files <- list.files(path = here::here(), pattern = ".R", recursive = TRUE, full.names = TRUE)
# Find all scripts with some Roxygen documentation (assumes that documented scripts have ONLY functions, if not true, could be a problem)
documented <- rep(NA, length(files))
for(ifile in 1:length(files)){
documented[ifile] <- TRUE %in% grepl("#'", readLines(files[ifile])) # All files must end with an empty line for this to work
}
buildFiles <- files[documented == TRUE] # !!!!! May remove any specific problematic files or files that do not need to be updated here !!!!!!
buildFiles <- buildFiles[-which(buildFiles == here::here("buildRPackage.R"))] # Don't try to turn this script into an R function
# Only build files that are already tracked by git (avoids adding half-baked functions created by whomever runs this script)
# tracked_files_short <- read.table(text = base::system(command = "git ls-tree --full-tree --name-only -r main", intern = TRUE))
tracked_files_short <- base::system(command = "git ls-tree --full-tree --name-only -r main", intern = TRUE)
tracked_files <- paste0(here::here(), "/", tracked_files_short)
buildFiles <- buildFiles[which(buildFiles %in% tracked_files == TRUE)] # only build git tracked files
##### Copy documented functions into R folder #####
file.copy(buildFiles, here::here("R"), overwrite = TRUE) # If documentation removed, empty file with no content will be retained in R folder
##### Add loaded functions to DESCRIPTION file #####
packageFiles <- list.files(path = here::here("R"))
packages <- NULL
for(ifile in 1:length(packageFiles)){
readFile <- readLines(here::here("R", packageFiles[ifile]))
packages <- c(packages, readFile[grepl("library", readFile)==TRUE])
}
dependencies <- packages %>% str_split_i(., "[(]", i = 2) %>% str_split_i(., "[)]", i = 1) %>% unique()
# Update description Imports
description <- readLines(here::here("DESCRIPTION"))
description[which(grepl("Imports:", description, fixed = TRUE) == TRUE)] <- paste0("Imports: ", paste(dependencies, collapse = ", "))
writeLines(description, here::here("DESCRIPTION"))
##### Comment out library lines in R function scripts
libraryLines <- NULL
for(ifile in 1:length(packageFiles)){
readFile <- readLines(here::here("R", packageFiles[ifile]))
libraryLines[[ifile]] <- which(grepl("library",readFile)==TRUE)
# Comment out library lines
readFile[libraryLines[[ifile]]] <- paste0("# ", readFile[libraryLines[[ifile]]])
writeLines(readFile, here::here("R", packageFiles[ifile]))
}
##### Add export statement if not already in documentation !!! doesn't add export statements if multiple functions in a file and one already has export statement
export <- NULL
for(ifile in 1:length(packageFiles)){
readFile <- readLines(here::here("R", packageFiles[ifile]))
export[[ifile]] <- TRUE %in% grepl("export",readFile)
# If no Roxygen export for the function then add
if(export[[ifile]] == FALSE){
if(TRUE %in% (diff(which(grepl("#'", readFile) == TRUE)) > 3)){ # If there are more than 4 lines between documentation lines then assume multiple functions in a file and export all
docLines <- which(grepl("#'", readFile) == TRUE) # ID lines in file with roxygen documentation
docBreaks <- which(diff(which(grepl("#'", readFile) == TRUE)) > 3) # ID where breaks in documentation exist (this is last line of documentation before next break)
revisedFile <- readFile[1:docLines[docBreaks[1]]]
for(ibreak in 1:length(docBreaks)){
if(ibreak == length(docBreaks)){ # If final break add additional export after last function and append lines through end of file
revisedFile <- c(revisedFile, "#' @export", readFile[(docLines[docBreaks[ibreak]]+1):max(docLines)],
"#' @export", readFile[(max(docLines)+1):length(readFile)])
# revisedFile <- c(revisedFile, "#' @export", readFile[(docBreaks[ibreak]+1):length(readFile)])
} else{ # Otherwise append lines through next documentation block
revisedFile <- c(revisedFile, "#' @export", readFile[(docLines[docBreaks[ibreak]]+1):docLines[docBreaks[ibreak+1]]])
# revisedFile <- c(revisedFile, "#' @export", readFile[(ibreak+1):docBreaks[ibreak+1]])
}
}
} else{ # Otherwise assume one function and add @export at end of documentation
lineBreak <- max(which(grepl("#'", readFile) == TRUE)) # This is the last row of documentation
revisedFile <- c(readFile[1:lineBreak], "#' @export", readFile[(lineBreak+1):length(readFile)])
}
writeLines(revisedFile, here::here("R", packageFiles[ifile]))
}
}
##### Document R package #####
devtools::document()
# NOTE: Functions that have roxygen documentation but 1) are not tracked by git or 2) were excluded from the buildFiles vector will trigger an error that they are "listed as exports, but not present in namespace"
##### Confirm package loads as expected - after this the following need to be updated on GitHub: R, man, DESCRIPTION, NAMESPACE files #####
# install.packages("pdbCollaborations")
library(pdbCollaborations)
?pdbCollaborations::makeReportData
?pdbCollaborations::create.brp.text
# To resolve warnings/errors check the following:
# Do all functions have a roxygen2 @title
# Do all .R scripts have an empty line at the end of the file, if not this will cause readLines() to throw an error
# By default this script will export all functions with at least a title documented with roxygen2
# Documentation build doesn't like special characters like % in documentation list items and will return the following error: @return has mismatched braces or quotes.
##### Final step #####
# Must commit changes to the following files/folders and push to GitHub so package available for installation via pak or devtools::install_github()
# DESCRIPTION
# man
# NAMESPACE
# R
# LICENSE - only update if a change to the license was made which is unlikely