class: inverse background-image: url(https://images.unsplash.com/photo-1509239129736-8c395375220d?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D) background-size: cover # .Large[[{readme2pkg}](https://github.com/EvaMaeRey/readme2pkg)] <br><br><br><br><br><br><br><br><br><br><br><br> ## .small[Package construction and narrative from README.Rmd] #### .small[Gina Reynolds | 2024-03-27 | Denver RLadies, Image credit: Jamie Templeton, Upsplash] ??? Title slide --- # R packages are composed of many files. -- # These multiple, un-ordered (alphabetical) constituents often fail to yield a clear big-picture package narrative. --- class: inverse, center, middle # But, could using a single meta-document to manage constituent files and their content help preserve a 'narrative arc'? --- class: inverse, center, middle ## Such a meta document could explain motivations for the package and design descision while clarify how functions relate. --- # Recent initiatives include helper packages [{litr}](https://jacobbien.github.io/litr-project/), [{fusen}](https://github.com/Thinkr-open/fusen/), and {readme2pkg} that implement this vision; see also [{rlp}](https://yihui.org/rlp/). -- # readme2pkg proposes the *README.Rmd* to be used as this meta document. --- # Main function: # `readme2pkg::chunk_to_dir()` --- ## usage ````default ```{r times_two} times_two <- function(x){ x*2 } ``` ```{r} readme2pkg::chunk_to_r(chunk_name = "times_two") ``` ```` -- ### Function 'home' is .Rmd, but code is copied into files which is required to package them. --- # readme2pkg dependencies: # - {knitr} (knit::knit_code$get()) -- # - {rstudioapi} (live session use of chunk_to_dir; via flair - Kelly Bodwin) # - {stringr} --- ## The workflow also assumes use of a template. https://github.com/EvaMaeRey/readme2pkg.template -- It prompts users to use {devtools} and {usethis} functions to build their package. --- ```r knitr::include_graphics("template_screenshot.png") ``` <img src="template_screenshot.png" width="1641" /> --- ## The template breaks down package building into phases: ### - Part 1. Goals definition; what package functionality should deliver -- ### - Part 2. Construct functions and *minimal viable package* -- ### - Part 3. Listen and iterate; (soliciting feedback) -- ### - Part 4. Refine and make robust -- ### - Part 5. Spread the good news; seek a wider audience -- ### - Part 6. Commit. Share on CRAN or R-Universe --- # Noteworthy? readme2pkg *pragmatic* packaging philosophy. -- # There are many reasonable pausing, stopping, and even abandon-the-project points along this progression. -- # you can't CRAN-orphan a package if you never submit it to CRAN. --- ## readme2pkg sees readme as: ### 1. a point of entry for new comers to development (readme template can be used as a getting started template) -- ### 2. checklist for more seasoned developers -- ### 3. As a package story board, -- ### 4. Centralized contributor meeting place (facilitates pointing potential contributors to trouble spots in context) --- # Template walk through, time permiting. ## https://github.com/EvaMaeRey/readme2pkg.template --- class: inverse, center, middle # End --- # Summary: The intent of [{readme2pkg}](https://github.com/EvaMaeRey/readme2pkg) is to let you build quick packages right from a README.Rmd. The function readme2pkg::chunk_to_dir (and friends) lets you send code chunk contents to a new file in a sub-directory. This means you don’t have to manage a bunch of function files that constitute a package - at least in the early stages. Instead you can work with them in your README.Rmd. -- Also, the [EvaMaeRey/readme2pkg.template](https://github.com/EvaMaeRey/readme2pkg.template) repo on github is a template repository meant to complement the readme2pkg workflow. Using the README.Rmd in the template, you can populate the sections with your material (introduction and functions, etc). And this README template contains a ‘living’ checklist that will help you get through the steps of creating a package, including building the file architecture, licensing, documentation, and builds. The checklist items are run through {devtools} and {usethis} packages. Code is included that lets you ‘check-off’ the items as you run the code. --- # Proposed future-date demo: *Package building with {readme2pkg}* --- If we had time for a demo, I hope to get through function documentation (adding a roxygen skeleton) in Part 3 of the readme2pkg.template. # Mini workshop requirements A. Installed Packages: - on CRAN: `usethis`; `devtools`; `ggplot2` or `stringr` (depending on worked example below) - on Github: `remotes::install_github("EvaMaeRey/readme2pkg")` B. Template repo: [EvaMaeRey/readme2pkg.template](https://github.com/EvaMaeRey/readme2pkg.template) C. Github account linked to RStudio --- ### Option 1: {redhistogram} package The goal of {redhistogram} is to make ... easier. Without the package, we live in the effort-ful world that follows 🏋: ```r library(ggplot2) ggplot(data = cars, aes(x = dist)) + geom_histogram(fill = "red") ``` ![](rladies-readme2pkg-slides_files/figure-html/unnamed-chunk-4-1.png)<!-- --> --- With the {redhistogram} package, we'll live in a different world (🦄 🦄 🦄) where the task is a snap 🫰: Proposed API: ``` library(redhistogram) library(ggplot2) ggplot(data = cars, aes(x = dist)) + geom_histogram_red() ``` --- # Part I. Work out functionality ✅ Here is a function that will do some work... ```r library(ggplot2) geom_histogram_red <- function(...){ geom_histogram(fill = "red", ...) } ``` --- ## Try it out ```r ggplot(data = cars, aes(x = dist)) + geom_histogram_red() ``` ![](rladies-readme2pkg-slides_files/figure-html/unnamed-chunk-5-1.png)<!-- --> --- ### Option 2: {ind.recode} package (based on real-life [{ind2cat}]()). The goal of {ind.recode} is to make ... easier. Without the package, we live in the effort-ful world that follows 🏋: ```r december_grad <- c(1,1,1,0) cat_december_grad <- ifelse(december_grad, "december grad", "not december grad") ``` --- With the {ind.recode} package, we'll live in a different world (🦄 🦄 🦄) where the task is a snap 🫰: Proposed API: ``` library(ind.recode) december_grad <- c(1,1,1,0) cat_december_grad <- ind.recode::ind_recode(x = december_grad) ``` --- # Part I. Work out functionality ✅ Here is a function that will do some work... ```r library(stringr) ind_recode <- function(x){ cat_true <- deparse(substitute(x)) |> str_replace_all("_", " ") cat_false <- paste("not", cat_true) factor(x, labels = c(cat_false, cat_true)) } ``` --- ## Try it out ```r december_grad <- c(1,1,1,0) ind_recode(december_grad) ``` ``` [1] december grad december grad december grad not december grad Levels: not december grad december grad ```