{"id":18612407,"url":"https://github.com/winvector/examplerpackage","last_synced_at":"2025-10-13T01:23:17.783Z","repository":{"id":142726351,"uuid":"305187957","full_name":"WinVector/ExampleRPackage","owner":"WinVector","description":"Example of how to build a simple R package","archived":false,"fork":false,"pushed_at":"2020-11-27T19:43:19.000Z","size":372,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-12-27T02:14:03.042Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WinVector.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-18T20:14:42.000Z","updated_at":"2023-07-25T14:40:07.000Z","dependencies_parsed_at":"2023-04-09T13:49:58.192Z","dependency_job_id":null,"html_url":"https://github.com/WinVector/ExampleRPackage","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WinVector%2FExampleRPackage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WinVector%2FExampleRPackage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WinVector%2FExampleRPackage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WinVector%2FExampleRPackage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WinVector","download_url":"https://codeload.github.com/WinVector/ExampleRPackage/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239402814,"owners_count":19632459,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T03:17:01.464Z","updated_at":"2025-10-13T01:23:12.762Z","avatar_url":"https://github.com/WinVector.png","language":"R","readme":"---\ntitle: \"README\"\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit the .Rmd file, not the .md file. --\u003e\n\n[ExampleRPackage](https://github.com/WinVector/ExampleRPackage) package README.\n\nWhat you will need for this lesson is:\n\n * A working `R` of version at least as new as `3.6`, with `4.*` preferred.\n * A network connection.\n * To install the `R` packages listed in the next subsection.\n * A text editor or IDE (integrated development environment) for editing `R` files.\n * For the source-control steps a `git` client (either command line or graphical).\n * Some ability to delete files/directories.\n * A command-line shell able to run `R CMD` steps.\n\n## Configuring your machine\n\nInstructions on how to configure a machine are given here\n\n * [How to configure Linux for R work](https://github.com/WinVector/ExampleRPackage/blob/main/extras/setting_up_a_Linux_machine.md).\n * [How to configure OSX for R work](https://github.com/WinVector/ExampleRPackage/blob/main/extras/setting_up_a_MacOS_machine.md).\n * [How to configure Windows for R work](https://github.com/WinVector/ExampleRPackage/blob/main/extras/setting_up_a_Windows_machine.md).\n \nThese steps require some knowledge of working with your computer, network access, disk space, and admin rights. We strongly advise you take the steps in this section before class. We also strongly advise taking the trouble to run these steps. Having full control of a package-enabled R environment is very powerful. Please reach out for help if you are stuck on steps.\n\nOnce you have your machine configured start up `R` and install the packages we will be using.\n\n## A word of warning\n\nThere are many systems and tutorials that sit on top of higher order R tools. These can be useful, but, one must remember in R [\"Writing R Extensions\"](https://cran.r-project.org/doc/manuals/R-exts.html) is the primary source for how to develop R packges.\n\n## Packages we assume you have installed\n\nWe assume your machine has a current working R, command-shell (bash / zsh), and text editor (emacs, vim, or other).\n\nStart R and run the following.\n\n```{r, eval=FALSE}\ninstall.packages(c(\n   \"tinytest\",   # for running tests\n   \"roxygen2\",   # to generate manuals from comments\n   \"knitr\",      # to generate vignettes from markdown\n   \"rmarkdown\",  # to convert markdown formats, may not need this\n   \"wrapr\"       # example for argument list checking\n   ))\n```\n\n## The file structure of this project\n\n```\nDESCRIPTION    # the main project control file\n\nR              # project source code directory\n /example_function.R  # our example function\n /package_help.R      # package documentation\n \nREADME.Rmd     # package documentation source\nREADME.md      # package documentation, produced from README.Rmd\n\ninst           # installed items distributed with package\n    /tinytest  # package test directory\n    /tinytest/test_ExampleRPackage.R  # the one test we have now\n\nvignettes      # where we place longer documents\n         /Example_Vignette.Rmd  # Example markdown document\n\ntests             # test trigger, do not edit\n     /tinytest.R  # test trigger, do not edit\n\n.Rbuildignore  # file that tells the builder what files to ignore\n\n.gitignore     # file that tells version control what files to skip\n\nNAMESPACE      # project imports/exports, produced by roxygen2\n\nman            # roxygen2 generated documentation\n   /ExampleRPackage.Rd   # generated package documentation\n   /example_function.Rd  # generated function documentation\n\nExampleRPackage.Rproj   # (optional) config file for RStudio\n```\n\n## How to copy this project\n\n\n### From GitHub\n\nPoint browser to [https://github.com/WinVector/ExampleRPackage](https://github.com/WinVector/ExampleRPackage) and press \"Fork\" in the upper right portion of the page.\n\n### Copying the project at the command line (`base`/`zsh` for Linux, MacOS, or Windows with Windows Subsystem for Linux)\n\nFrom a `bash`/`zsh` command line:\n\n```\n# get a copy of the repository\ngit clone https://github.com/WinVector/ExampleRPackage.git\n\n# remove the .git directory to sever it from the original repository\ncd ExampleRPackage\nrm -rf .git\n\n# start up a new git repository\ngit init .\ngit add -A .\ngit commit -m\"example package\"\n```\n\nThen associate the package with your own repository by creating an new empty repository on GitHub and following their \"preexisting project\" instructions (adding a remote).\n\n\n\n## Procedures for working with packages.\n\n\nFor all of these steps we are assuming your current directory is the top-level of the package you\nare working with. This can be accomplished with the `setwd()` command. Alternately one can use an `RStudio`\nproject, which largely keeps track of the working directory.\n\n\n\n\n### Build Package\n\nWe will run this with our working directory inside our package (please see `getwd()`/`setwd()` for how to navigate between directories in R). This will produce the file `ExampleRPackage_0.1.0.tar.gz`.\n\n\n```{r}\nlibrary(wrapr)\n\n# assumes our current directory is our package\n# see setwd()/getwd() for how to change directories\nrebuild_current_package_and_attach \u003c- function(\n   ...,  # not used, force later arguments to bind by name\n   package_dir = getwd(),  # default to package is current directory.\n   lib = .libPaths()[[1]]  # where to attach package\n   ) {\n   wrapr::stop_if_dot_args(substitute(list(...)), \"rebuild_current_package\")\n   start_time \u003c- date()\n   message(paste(\"rebuild_current_package working in directory\", package_dir))\n   message(paste(\"rebuild_current_package working in lib\", lib))\n   # get package name from current directory\n   pkg_name \u003c- tail(strsplit(package_dir, .Platform$file.sep)[[1]], n = 1)\n   message(paste(\"rebuild_current_package working on package\", pkg_name))\n   # get into a clean state with no package installed/attached\n   detach_str \u003c- paste0('package:', pkg_name)\n   res \u003c- tryCatch(do.call(detach, list(detach_str)), error = function(e) e)\n   if(pkg_name %in% rownames(installed.packages())) {\n      remove.packages(pkg_name, lib = lib)\n   }\n   # regenerate man/.Rd files from roxygen comments\n   res_text \u003c- capture.output(suppressMessages(roxygen2::roxygenize(package.dir = package_dir)))\n   # rebuild a source distribution of package\n   res \u003c- system(paste(\"R CMD build\", package_dir), \n                 intern = TRUE)\n   # find the tar name\n   matches \u003c- res[grepl(pkg_name, res)]\n   pkg_pattern \u003c- paste0(pkg_name, '[_.0-9]+', '.tar.gz')\n   matches \u003c- matches[grepl(pkg_pattern, matches)]\n   if(length(matches) != 1) {\n      stop(\"having trouble finding package tar name from R CMD build output\")\n   }\n   str_span \u003c- regexpr(pkg_pattern, matches)\n   tar_name \u003c- substr(matches, str_span, str_span + attr(str_span, 'match.length') - 1)\n   # install the package from the source distribution\n   res_text \u003c- capture.output(install.packages(tar_name, repos = NULL, verbose = FALSE, quiet = TRUE))\n   # attach package for use\n   res_text \u003c- capture.output(library(pkg_name, character.only = TRUE))\n   end_time \u003c- date()\n   return(list(\n      pkg_name = pkg_name,\n      tar_name = tar_name,\n      package_dir = package_dir,\n      package_dir = package_dir,\n      lib = lib,\n      start_time = start_time,\n      end_time = end_time\n   ))\n}\n```\n\n```{r, eval=FALSE}\n# re-document, re-build, re-install, and re-attach package\n# write only name of package and tar file name into current work-space\n(unpack[pkg_name, tar_name] := rebuild_current_package_and_attach())\n\n# rebuild_current_package working in directory /Users/johnmount/Documents/work/ExampleRPackage\n# rebuild_current_package working in lib /Users/johnmount/Library/R/4.0/library\n# rebuild_current_package working on package ExampleRPackage\n# \n# $pkg_name\n# [1] \"ExampleRPackage\"\n# \n# $tar_name\n# [1] \"ExampleRPackage_0.1.0.tar.gz\"\n# \n# $package_dir\n# [1] \"/Users/johnmount/Documents/work/ExampleRPackage\"\n# \n# $package_dir\n# [1] \"/Users/johnmount/Documents/work/ExampleRPackage\"\n# \n# $lib\n# [1] \"/Users/johnmount/Library/R/4.0/library\"\n# \n# $start_time\n# [1] \"Fri Nov 27 11:13:31 2020\"\n# \n# $end_time\n# [1] \"Fri Nov 27 11:13:35 2020\"\n```\n\n```{r, echo=FALSE}\n# get into state as if last block had been run\nlibrary(ExampleRPackage)\npkg_name \u003c- \"ExampleRPackage\"\ntar_name \u003c- \"ExampleRPackage_0.1.0.tar.gz\"\n```\n\n```{r}\nls()\n\nprint(pkg_name)\n\nprint(tar_name)\n```\n\nProbably want to restart `R` at this point and re-attach the package with `library(ExampleRPackage)`.\n\n### Build `README.md` from `README.Rmd`\n\n```{r, eval=FALSE}\nknitr::knit(\"README.Rmd\")\n```\n\nSome time after rebuilding `README.md` you may want to rebuild the package again to make sure the new copy is included in the package tar.\n\n### Run tests\n\nThis package is already setup to use `tinytest`. Existing packages can be configured to work with `tinytest` by running `tinytest::setup_tinytest('.')`.\n\n\n\n```{r}\n# test directory of tests\ndir \u003c- system.file('tinytest', \n                   package = 'ExampleRPackage', \n                   mustWork = TRUE)\nprint(dir)\n\ntest_text \u003c- capture.output(tinytest::run_test_dir(\n   dir,\n   verbose = TRUE,\n   color = FALSE))\ncat(paste(test_text, collapse = '\\n'))\n```\n\n\n\n### Check package\n\n```{r}\ncheck_text \u003c- system(paste(\"R CMD check\", tar_name),\n       intern = TRUE)\ncat(paste(check_text, collapse = '\\n'))\n```\n\n\n## Example code\n\n\n```{r}\nexample_function(3)\n```\n\n## Sharing packages\n\n### Install from file\n\n```{r, eval=FALSE}\ninstall.packages(tar_name, repos = NULL)\n```\n\n\n### Install from tar on github\n\n```{r, eval=FALSE}\n# get this path by copying Github's download link\nurl \u003c- \"https://github.com/WinVector/ExampleRPackage/raw/main/ExampleRPackage_0.1.0.tar.gz\"\ninstall.packages(url, repos = NULL)\n```\n\n\n### Install package from github\n\n```{r, eval=FALSE}\nremotes::install_github(\"https://github.com/WinVector/ExampleRPackage\")\n```\n\n## Submitting to CRAN\n\nSubmitting to CRAN is a specialized step. First your package must pass all checks and all CRAN rules (most of which are listed in [\"Writing R Extensions\"](https://cran.r-project.org/doc/manuals/R-exts.html)). It is important to note the following:\n\n * The purpose of CRAN, as stated by some members, is a reliable experience for users electing to take packages from CRAN. CRAN considers unreliability in single extension packages as reputation risk for R/CRAN itself. Note this is different purpose than serving package authors.\n * CRAN is *not* a test system, the assumption is you are only submitting packages that should pass all requirements to CRAN- not using CRAN to confirm the package meets requirements.\n * All initial package submissions to CRAN are hand-checked with a emphasis on the package purpose and description.\n * Minimizing dependencies (and not having non-CRAN dependencies) is a must. I believe CRAN currently checks if packages import more than 20 non-default dependencies and raises on issue.\n * Do not get \"lawyerly\" with CRAN. CRAN feedback tends to have a purpose. It may appear to the non-cognoscenti that some packages have variances or are allowed around the rules. Either this is not the case, or it is a point of strong negative contention. In either case it is *not* a good idea to attempt to copy bad practices from other packages.\n * CRAN packages must be testable in isolation and free of file-system side-effects.\n\nFor now I am going to leave CRAN submissions as a \"to be covered later\" topic.\n\n\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwinvector%2Fexamplerpackage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwinvector%2Fexamplerpackage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwinvector%2Fexamplerpackage/lists"}