Packages#
Notes from working through: https://r-pkgs.org/
Remember: Git commit after each change
Packages: set up#
Start in a fresh R session in the directory where you want to create the folder (e.g. Documents).
Environment:
library(devtools)
(if not already installed, will need to run install.packages(“devtools”)create_package("~/Documents/packagename")
, which will create a directory (if doesn’t already exist) and populate with .gitignore, .Rbuildignore, DESCRIPTION, NAMESPACE, R folder, and packagename.Rproj. RStudio will open a new window with Rproj activated/open. As it’s a fresh R session, then calllibrary(devtools)
again.renv::init()
to set up with renvinstall.packages(c("devtools", "roxygen2", "testthat", "knitr"))
thenrenv::snapshot()
library(devtools)
, or add to .Rprofile to always library() it:
if (interactive()) {
suppressMessages(require(devtools))
}
GitHub:
Make it a GitHub repository -
usethis::use_git()
Rename branch
git branch -m master main
Link with GitHub -
usethis::use_github()
. May get error about personal access token if not set. To see if it is set, rungh_token_help()
. To store, usegitcreds::gitcreds_set()
Description, license and readme:
Edit DESCRIPTION (title, author, description)
use_mit_license()
to create the license filesuse_readme_rmd()
to create basic README file, add some lines to .Rbuildignore, and creates a Git pre-commit hook to help you keep README.Rmd and README.md in sync. To update README runbuild_readme()
to create README.md from README/Rmd. The advantage of having a README.Rmd file is that you can include code chunks, embed plots, etc. You can also use GitHub Actions to re-render README.Rmd every time you push, example here: r-lib/actions. I have not tried that yet though.
Packages: adding functions and testing#
use_r("functionname")
to create or open script functionname.R in R/ directory. Add the function there (only that, not libraries etc.).
Docstring:
Open function R file, click cursor within function, then do Code > Insert Roxygen skelecton.
Edit the Rxoygen description. It will include @export. This tells Roxygen2 to add this function to the NAMESPACE file, so that it will be accessible to users. For your first R package, you’ll probably want to include @export for each of your functions.
Run
document()
to update documentation. It will convert the roxygen comment into man/functionname.Rd and write in NAMESPACEThe @example directive is used when you want to use an external file that contains the examples. If you’re including the example(s) directly in your roxygen documentation then use
@examples
. If you don’t want the examples to run (e.g. if providing with a fake file that doesn’t exist, and hence would fail check() as it tests examples work), then use@examplesIf interactive()
Can now preview helpfile by running
?functionname
Usage is derived from function specification. Can set manually with
@usage
and remove entirely with@usage NULL
Testing:
use_testthat()
. This initializes the unit testing machinery for your package. It adds Suggests: testthat to DESCRIPTION, creates the directory tests/testthat/, and adds the script tests/testthat.R.use_test("functionname")
to create matching testfile.library(testthat)
,load_all()
,test()
to run the test. Tests will also run whenevercheck()
packagerename_files("strsplit1", "str_split_one")
to rename the R file and will also rename testthat file (which we also edit with new function name), to fit with convention of filename matching function name
Packages: using other libraries#
Based on: https://kbroman.org/pkg_primer/pages/depends.html
Add libraries that are essential for package to run and that want R to install when install your package to Imports: section of DESCRIPTION FILE. Instead of manual change, can also run use_package(“readxl”) which adds it to Imports section of DESCRIPTION.
Add required imports to each function - ideally with specific functions - or just whole package - example:
#' @import tidyverse
#' @importFrom readxl read_excel
Run
check()
to see if issue is resolved
Packages: loading and checking#
load_all()
to simulate process of building, installing and attaching the package. You can then use functions from that package.check()
to check package is in working order. Read output - it’s easier to deal with these problems earlierinstall()
thenlibrary(packagename)
to install and use package in current environment
Packages - Vignettes:#
usethis::use_vignette("my-vignette")
- creates directory, modifies DESCRIPTION, drafts vignette Rmd, adds patterns to .gitignoreinstall()
,library(package_name)
then knit
If you rename vignette, change VignetteIndexEntry to match title (doesn’t need to match filename). When run, will create new html under docs/articles called newfilename.html. Delete old filename. Build site. Push.
Packages - Create GitHub pages website:#
Initial set-up:
First step is to ensure set up with git creds. When I first tried this, I had lots of issues with it not working, and realised this was because I hadn’t set it up with the Personal Access Token (PAT). Do this using
gitcreds::gitcreds_set()
. Check settings usingusethis::gh_token_help()
.Next step is to go to repository Settings > Actions > General > Workflow permissions and check “read and write permissions”
Creating site:OPTION 1.
usethis::use_pkgdown()
, thenpkgdown::build_site()
, then remove docs from .gitignore so you can commit them to GitHub, then push to mainOPTION 2:
usethis::use_pkgdown_github_pages()
To update website, rebuild locally using pkgdown::build_site()
then push to GitHub and push to main branch. GitHub pages will always based on files in docs/ folder for source code of website in specified branch (default: main).