Skip to content

Commit

Permalink
version 0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
feddelegrand7 authored and cran-robot committed Nov 2, 2023
0 parents commit efc985d
Show file tree
Hide file tree
Showing 12 changed files with 329 additions and 0 deletions.
25 changes: 25 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Package: rfold
Type: Package
Title: Working with many R Folders Within an R Package
Version: 0.1.0
Authors@R:
person(given = "Mohamed El Fodil",
family = "Ihaddaden",
role = c("aut", "cre"),
email = "ihaddaden.fodeil@gmail.com")
Description:
Allows developers to work with many R folders inside a package. It offers functionalities to transfer R scripts (saved outside the R folder) into
the R folder while making additional checks.
License: MIT + file LICENSE
Encoding: UTF-8
Imports: cli (>= 3.6.1), fs (>= 1.5.0), here (>= 1.0.1), usethis (>=
2.0.1)
RoxygenNote: 7.1.1
Suggests: testthat (>= 3.0.0)
Config/testthat/edition: 3
NeedsCompilation: no
Packaged: 2023-11-01 22:37:29 UTC; Administrateur
Author: Mohamed El Fodil Ihaddaden [aut, cre]
Maintainer: Mohamed El Fodil Ihaddaden <ihaddaden.fodeil@gmail.com>
Repository: CRAN
Date/Publication: 2023-11-02 15:50:02 UTC
2 changes: 2 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
YEAR: 2023
COPYRIGHT HOLDER: rfold authors
11 changes: 11 additions & 0 deletions MD5
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
3680a516b6ed0be936a838738de0db71 *DESCRIPTION
ce7c21a851fc05d855d30ded2dd4dca4 *LICENSE
818722a25944f8f44c044f54cb89f6cd *NAMESPACE
5793a5608b1f247fa72d16e10bb303a9 *NEWS.md
7453e420754cad0e8d5d7d3e7d719e3a *R/main.R
b4844025274abe17014899b8352c7388 *README.md
90189bfb82ebe81e65db92e71a32854a *man/figures/figure1.png
e631da678fd55a6dd635e12a7f6a7bac *man/figures/figure2.png
9f02da1d16599452a48c616fe75b2bd6 *man/rfold.Rd
e6cfab9a5c250596a1a122da5f026ace *tests/testthat.R
7510abeeea816f2d7cb19640d08536f5 *tests/testthat/test-main.R
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Generated by roxygen2: do not edit by hand

export(rfold)
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# rfold 0.1.0

# rfold 0.0.1

* Added a `NEWS.md` file to track changes to the package.
166 changes: 166 additions & 0 deletions R/main.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@

.get_files_that_are_not_in_r_folder <- function(folders_to_ignore) {

r_folder_exists <- unname(fs::dir_exists(here::here("R")))

if (!r_folder_exists) {
message("R folder does not exist, creating it")
fs::dir_create(here::here("R"))
}

r_folders <- list.dirs(here::here("R"))

if (length(r_folders) > 1) {
stop("Looks like you've folders insider your R folder, please inspect")
}

all_r_files <- fs::dir_ls(
path = ".",
regexp = "\\.R$|\\.r$",
recurse = TRUE
)

tmp_df <- data.frame(
r_files = all_r_files,
dir_name = dirname(all_r_files),
row.names = NULL,
stringsAsFactors = FALSE
)

r_files_without_dir <- tmp_df[tmp_df$dir_name == ".", ]

if (nrow(r_files_without_dir) > 0) {
stop(
"The following .R files are on the top-level
of the package and don't have a parent directory, please inspect: ",
toString(r_files_without_dir$r_files)
)
}

folders_to_be_ignored <- c("R", "tests", "tests/testthat", folders_to_ignore)

r_files_not_in_r_dir_df <- tmp_df[!tmp_df$dir_name %in% folders_to_be_ignored, ]

r_files_not_in_r_dir <- r_files_not_in_r_dir_df$r_files

r_check_folder <- grepl(".Rcheck/", x = r_files_not_in_r_dir)

r_files_not_in_r_dir <- r_files_not_in_r_dir[!r_check_folder]

if (length(r_files_not_in_r_dir) == 0) {
cli::cli_alert_warning(
"No R files available outside of the R directory, nothing to do"
)
return(character(0))
}

r_files_names_not_in_r_dir <- basename(r_files_not_in_r_dir)

dupli <- duplicated(r_files_names_not_in_r_dir)

duplicated_files <- r_files_names_not_in_r_dir[dupli]

if (length(duplicated_files) > 0) {
stop(
"The following file(s) are duplicated across your package: ",
toString(duplicated_files)
)
}

r_files_not_in_r_dir

}


#' Transfer .R files into the R directory
#'
#' @return called for the side effect of transferring all R files
# available inside a project into the R folder
#' @param folders_to_ignore a string vector of plain names folders that should be ignored
#' where transferring .R files into the main R folder (for example a dev folder). Defaults to NULL
#'
#' @param script_name_prefix characters string of length 1 that will be appended to the start of the .R scripts when transferring them to the R folder. Defaults to 'DO_NOT_EDIT', set it to NULL for no appending
#'
#' @export
#'

rfold <- function(
folders_to_ignore = NULL,
script_name_prefix = "DO_NOT_EDIT_"
) {

if (length(script_name_prefix) > 1) {
stop("script_name_prefix must be of length 1")
}

if (is.null(script_name_prefix)) {
script_name_prefix <- ""
}

if (!is.null(folders_to_ignore)) {
dir_exist <- dir.exists(folders_to_ignore)

if (!any(dir_exist)) {
dir_no_exist <- folders_to_ignore[!dir_exist]
stop("The following directories do not exist. Can't ignore them: ", dir_no_exist)

}
}

r_files <- .get_files_that_are_not_in_r_folder(folders_to_ignore)

if (length(r_files) == 0) {
return(invisible(NULL))
}

dir_components <- unique(unlist(strsplit(r_files, "/")))

dir_components <- dir_components[!grepl("\\.R$", dir_components)]

usethis::use_build_ignore(dir_components)

r_files_string <- paste(toString(r_files), collapse = ", ")

cli::cli_alert_info(
"Copying the following R files with prefix '{script_name_prefix}' into the R folder: {r_files_string}"
)

file_names <- basename(r_files)

new_file_names <- paste0(script_name_prefix, file_names)

fs::file_copy(
path = r_files,
new_path = here::here("R", new_file_names),
overwrite = TRUE
)

for (i in seq_along(new_file_names)) {

script_to_consider <- here::here("R", new_file_names[i])

existing_script_content <- readLines(script_to_consider)

comment <- "# GENERATED BY RFOLD: DO NOT EDIT BY HAND ####"

if (length(existing_script_content) == 0) {
writeLines(comment, con = script_to_consider)
next()
}

if (existing_script_content[1] == comment) {
next()
}

new_content <- c(
comment,
existing_script_content,
comment
)

writeLines(new_content, con = script_to_consider)
}

cli::cli_alert_success("Success")
}

76 changes: 76 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@

<!-- README.md is generated from README.Rmd. Please edit that file -->

# rfold

<!-- badges: start -->
<!-- badges: end -->

The goal of the `rfold` package is to allow `R` developers to work with
many `R` directories within an `R` package. A considerable limitation
regarding `R` packages development, is that one cannot create other
directories/sub directories (other than the `R` directory) and bind them
to the package ecosystem.

Using `rfold`, you can create as many directories/sub directories
(**outside of your `R` directory**).

The `rfold()` function will list all the `.R` scripts available outside
of the `R` folder, assign their names to `.Rbuildignore` file and
transfer them within the main `R` directory, giving you all the
flexibility you need to organize your package into many
directories/sub-directories.

## Installation

You can install the development version of `rfold` with:

``` r
remotes::install_github("feddelegrand7/rfold")
```

## Usage

Just use `rfold::rfold()` before building or documenting your package
and you’re all set.

## Example

Suppose that within this package, I would decide to have the following
structure:

![](man/figures/figure1.png)

Running `rfold::rfold()`, all the external (external to the `R` folder)
`.R` scripts will be moved within the `R` folder:

``` r
rfold::rfold()
```

As such, I’ll get now the following structure:

![](man/figures/figure2.png)

Notice, that script names that will be transferred to the `R` folder
have their name prefixed with the character `DO_NOT_EDIT`. You can tweak
this feature or deactivate it using the `script_name_suffix` parameter
of the `rfold()` function.

The following comment will also be inserted at the top of each script
transferred into the R folder: **\# GENERATED BY FOLD: DO NOT EDIT BY
HAND \####**

There’s another parameter available, called `folders_to_ignore` which
allows you to ignore certain directories (for example `dev` directory)
when running the `rfold` function.

Note also that `devtools::build()` and `devtools::document()` will only
consider the scripts available within your `R` folder.

## Code of Conduct

Please note that the rfold project is released with a [Contributor Code
of
Conduct](https://contributor-covenant.org/version/2/0/CODE_OF_CONDUCT.html).
By contributing to this project, you agree to abide by its terms.
Binary file added man/figures/figure1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added man/figures/figure2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions man/rfold.Rd

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

4 changes: 4 additions & 0 deletions tests/testthat.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
library(testthat)
library(rfold)

test_check("rfold")
17 changes: 17 additions & 0 deletions tests/testthat/test-main.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
testthat::test_that("rfold works as expected", {

testthat::expect_error(
object = {
rfold::rfold(folders_to_ignore = "dont_exist")
},
regexp = "The following directories do not exist. Can't ignore them: dont_exist"
)

testthat::expect_error(
object = {
rfold::rfold(script_name_prefix = c("pref1", "pref2"))
},
regexp = "script_name_prefix must be of length 1"
)

})

0 comments on commit efc985d

Please sign in to comment.