--- title: "About the `abusethis` package" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{About the `abusethis` package} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( prompt=TRUE, collapse = TRUE, comment = "#>" ) ``` # History In the old days people doing casual work tended to not write packages, and instead developed their own ways of working - often using `source` to read a file of function definitions into their working environment. To structure this a bit more, maybe they put functions into separate files and then wrote a "master" file that called `source` on everything else they needed. Make one tiny edit, then `source` everything. The alternative, putting your code into packages, meant you could have a well-structured folder of code and documentation, including dependency specification, compiled languages, vignettes and all that goodness. But the downside was you had to build and install the package after every change. Users eventually developed ways to create things more like Python modules that could be attached and detached. # Devtools The `devtools` package gave us an easier way to work with the package structure without needing to build and reinstall on every change. A simple `load_all` call would detach the old package, recompile any compiled code that needed going, and attach the new code. It took care of all the details and worked pretty well. I started using it and developed a discipline of putting all my code into a package structure. This meant sometimes I was working on multiple packages at once - for example I might be implementing a new statistical method and have a dataset for it. That method would have its own package, and the dataset would have another package for functions for loading and cleaning the data. That meant I would end up with a general package for a statistical method that could be shared, and a package for the specific project for manipulating the data and producing the project outputs. The `devtools` package also supplied a stack of `use_` functions which added functionality to your package. At first you could specify the package folder, so I could do `use_package("AA", "sp")` and `use_package("BB", "gam")` to add specific requirements to packages AA and BB respectively. # Splitters Then `devtools` split out the `use_` functions into the `usethis` package. And at some point the ability to specify a package folder went. I think at some point it was just a matter of changing the working directory with `setwd` before running them, so the above operations would have been: ```{r old1, eval=FALSE} setwd("A") use_package("sp") setwd("../B") use_package("gam") setwd("..") ``` That's quite clunky, and its easy to forget to go back to your original working directory. Luckily the `withr` package has some functions that do things within setups that are guaranteed to be reset after the code completes, and `with_dir` will help with the above, making it: ```{r old2, eval=FALSE} with_dir("./A", use_package("sp")) with_dir("./B", use_package("gam")) ``` But if this used to work, it doesn't now. Currently, `usethis` keeps a global idea of the current "project" in an environment. Use of the word "project" here, which is not an R concept, appears to relate to tighter integration with particular IDEs that support it. Again, there's a `withr` function that lets you apply code within the context of a new "project", resetting the current project back afterwards. For package development this is sufficient. So we now have: ```{r old3, eval=FALSE} with_project("./A", use_package("sp")) with_project("./B", use_package("gam")) ``` # Easier with A-B-Usage Can we make this any easier? That's what the `abusethis` package is all about. It lets you use the `use_` functions on any number of packages. First we need the `devtools` package and this package: ```{r setup} library(devtools) library(abusethis) ``` Next we'll make a couple of skeletal packages called A and B in R's temporary directory location. They could be anywhere in your filesystem, with any names. The extra options to `create_package` stop R setting the new package as the current project, and also to allow a single-character package name (which is valid in R, but CRAN doesn't like it): ```{r makeAB} A = file.path(tempdir(), "A") message("Package A is at ",A) B = file.path(tempdir(), "B") message("Package B is at ",B) create_package(A, open=FALSE, check=FALSE) create_package(B, open=FALSE, check=FALSE) ``` Now we have two packages that we'd like to use `usethis` on. We can use `attach_use` to create a set of wrapped `use_` functions from the `usethis` package and attach them to the search path. We do this once for package A and once for package B. See how they are added to the search path: ```{r Ause} print(search()) attach_use(A) attach_use(B) print(search()) ``` Looking at the first four functions in these environments you can see how they are prefixed versions of the corresponding `usethis` functions: ```{r ABusefuncs} ls("A_use")[1:4] ls("B_use")[1:4] ``` Then if I want to set package A to have the MIT license, and package B to have the GPL3 licence, I do: ```{r setlicense} A_use_mit_license() B_use_gpl3_license() ``` Arguments are the same as the corresponding `usethis` functions. So if package A uses the `grid` package, and package B uses the `stats` package, we do this: ```{r setpacks} A_use_package("grid") B_use_package("stats") ``` # More Details By default `abusethis` uses the basename of the package folder to create the environment and the functions. But what if I have two packages with the same name? In that case you can use the prefix argument to create wrapped functions with different names. For example, suppose you have two versions of a package, one for development and one for production? Let's set that up. ```{r twonames} devdir = file.path(tempdir(), "dev") prodir = file.path(tempdir(), "pro") dir.create(devdir) dir.create(prodir) create_package(file.path(devdir,"codez"), open=FALSE) create_package(file.path(prodir,"codez"), open=FALSE) ``` Now I can attach all the `usethis` functions with a development or production prefix: ```{r attachprefix} attach_use(file.path(devdir,"codez"), prefix="dev_") attach_use(file.path(prodir,"codez"), prefix="pro_") ``` and do stuff like this: ```{r devprostuff} dev_use_mit_license() pro_use_gpl3_license() ``` # Summary I wrote this because its useful. If you find it useful, use it. If you don't, then don't. If you've got an easier way to do this, use that. If you tell me about it and I like it I'll use it too.