here/0000755000176200001440000000000013765341372011210 5ustar liggesusershere/NAMESPACE0000644000176200001440000000017313754236603012426 0ustar liggesusers# Generated by roxygen2: do not edit by hand export(dr_here) export(here) export(i_am) export(set_here) import(rprojroot) here/LICENSE0000644000176200001440000000005213754142277012213 0ustar liggesusersYEAR: 2020 COPYRIGHT HOLDER: here authors here/README.md0000644000176200001440000000707713754151765012505 0ustar liggesusers # here [![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://www.tidyverse.org/lifecycle/#stable) [![rcc](https://github.com/r-lib/here/workflows/rcc/badge.svg)](https://github.com/r-lib/here/actions) [![CRAN status](https://www.r-pkg.org/badges/version/here)](https://CRAN.R-project.org/package=here) [![Codecov test coverage](https://codecov.io/gh/r-lib/here/branch/master/graph/badge.svg)](https://codecov.io/gh/r-lib/here?branch=master) The goal of the here package is to enable easy file referencing in [project-oriented workflows](https://rstats.wtf/project-oriented-workflow.html). In contrast to using [`setwd()`](https://rdrr.io/r/base/getwd.html), which is fragile and dependent on the way you organize your files, here uses the top-level directory of a project to easily build paths to files. ## Installation Install the released version of here from CRAN:
install.packages("here")
## Usage The here package creates paths relative to the top-level directory. The package displays the top-level of the current project on load or any time you call `here()`:
here::i_am("README.Rmd")
#> here() starts at /home/kirill/git/R/here
here()
#> [1] "/home/kirill/git/R/here"
You can build a path relative to the top-level directory in order to read or write a file:
here("inst", "demo-project", "data", "penguins.csv")
#> [1] "/home/kirill/git/R/here/inst/demo-project/data/penguins.csv"
readr::write_csv(palmerpenguins::penguins, here("inst", "demo-project", "data", "penguins.csv"))
These relative paths work regardless of where the associated source file lives inside your project, like analysis projects with data and reports in different subdirectories. See the included [demo project](https://github.com/r-lib/here/tree/master/inst/demo-project) for an example. ![](https://raw.githubusercontent.com/allisonhorst/stats-illustrations/master/rstats-artwork/here.png) *Illustration by [Allison Horst](https://github.com/allisonhorst)* ------------------------------------------------------------------------ ## Code of Conduct Please note that the here project is released with a [Contributor Code of Conduct](https://here.r-lib.org/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. here/man/0000755000176200001440000000000013754151372011760 5ustar liggesusershere/man/dr_here.Rd0000644000176200001440000000103013754151372013651 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/dr_here.R \name{dr_here} \alias{dr_here} \title{Situation report} \usage{ dr_here(show_reason = TRUE) } \arguments{ \item{show_reason}{\verb{[logical(1)]}\cr Include reason in output of \code{dr_here()}, defaults to \code{TRUE}.} } \description{ \code{dr_here()} shows a message that by default also includes the reason why \code{here()} is set to a particular directory. Use this function if \code{here()} gives unexpected results. } \examples{ dr_here() } here/man/here.Rd0000644000176200001440000000441513754151372013176 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/here.R \name{here} \alias{here} \title{Find your files} \usage{ here(...) } \arguments{ \item{...}{\verb{[character]}\cr Path components below the project root, can be empty. Each argument should be a string containing one or more path components separated by a forward slash \code{"/"}.} } \description{ \code{here()} uses a reasonable heuristics to find your project's files, based on the current working directory at the time when the package is loaded. Use it as a drop-in replacement for \code{\link[=file.path]{file.path()}}, it will always locate the files relative to your project root. } \details{ This package is intended for interactive use only. Use \code{\link[rprojroot:root_criterion]{rprojroot::has_file()}} or the other functions in the \pkg{rprojroot} package for more control, or for package development. If \code{here()} raises an error or otherwise behaves unexpectedly, you may have attached \pkg{plyr} or another package after \pkg{here}. Correct this using \href{https://conflicted.r-lib.org/}{the \pkg{conflicted} package}, or use \code{here::here("data", "df.rda")}. } \examples{ here() \dontrun{ here("some", "path", "below", "your", "project", "root.txt") here("some/path/below/your/project/root.txt") } } \section{Project root}{ The project root is established with a call to \verb{here::}\code{\link[=i_am]{i_am()}}. Although not recommended, it can be changed by calling \code{here::i_am()} again. In the absence of such a call (e.g. for a new project), starting with the current working directory during package load time, the directory hierarchy is walked upwards until a directory with at least one of the following conditions is found: \itemize{ \item contains a file \code{.here} \item contains a file matching \verb{[.]Rproj$} with contents matching \verb{^Version: } in the first line \item contains a file \code{DESCRIPTION} with contents matching \verb{^Package: } \item contains a file \code{remake.yml} \item contains a file \code{.projectile} \item contains a directory \code{.git} \item contains a file \code{.git} with contents matching \verb{^gitdir: } \item contains a directory \code{.svn} } In either case, \code{here()} appends its arguments as path components to the root directory. } here/man/set_here.Rd0000644000176200001440000000224713754150007014044 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/set_here.R \name{set_here} \alias{set_here} \title{Add a marker file to a project} \usage{ set_here(path = ".", verbose = TRUE) } \arguments{ \item{path}{\verb{[character(1)]}\cr Directory where to create \code{.here} file, defaults to the current directory.} \item{verbose}{\verb{[logical(1)]}\cr Verbose output, defaults to \code{TRUE}.} } \description{ \ifelse{html}{\out{Superseded lifecycle}}{\strong{Superseded}} } \details{ \code{set_here()} creates an empty file named \code{.here}, by default in the current directory. When here encounters such a file, it uses the directory that contains this file as root. This is useful if none of the default criteria apply. You need to restart the R session so that \code{here()} picks up the newly created file. } \section{Life cycle}{ \code{set_here()} should no longer be necessary if all scripts and reports in a project call \code{\link[=i_am]{i_am()}}, which is now the recommended workflow for declaring the project root. } \keyword{internal} here/man/i_am.Rd0000644000176200001440000000430413754150007013147 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/i_am.R \name{i_am} \alias{i_am} \title{Declare location of current script or report} \usage{ i_am(path, ..., uuid = NULL) } \arguments{ \item{path}{\verb{[character(1)]}\cr The path to the current script or report, relative to the project root. Passing an absolute path raises an error.} \item{...}{Must be empty, reserved for future use.} \item{uuid}{\verb{[character(1)]}\cr \ifelse{html}{\out{Experimental lifecycle}}{\strong{Experimental}})` If not \code{NULL}, a unique string that is matched against the first 100 lines of the file. Use \code{\link[uuid:UUIDgenerate]{uuid::UUIDgenerate()}} to create a unique string that can be used as a \code{uuid} argument.} } \value{ This function is called for its side effects. } \description{ Add a call to \code{here::i_am(".")} at the top of your R script or in the first chunk of your rmarkdown document. This ensures that the project root is set up correctly: subsequent calls to \code{here()} will refer to the implied project root. If the current working directory is outside of the project where the script or report is intended to run, it will fail with a descriptive message. } \details{ Relying on the project root determined with a project file, the default for versions prior to 1.0.0, only weakly protects against running a script from an arbitrary directory outside the intended project. The \code{i_am()} function offers a stronger way to define the project root: it will ensure that the project root actually contains a file in that location, optionally checking for file contents that uniquely identify the file via the \code{nonce} argument. This function will fail if the script or report is moved within the project. Update the \code{i_am()} call to reflect the new location. If you use the \code{nonce} argument for extra safety, be sure to change it when you save an existing script or report under a new name. } \examples{ \dontrun{ here::i_am("prepare/penguins.R") here::i_am("analysis/report.Rmd", uuid = "f9e884084b84794d762a535f3facec85") } } here/man/figures/0000755000176200001440000000000013754151372013424 5ustar liggesusershere/man/figures/lifecycle-defunct.svg0000644000176200001440000000170413754151372017534 0ustar liggesuserslifecyclelifecycledefunctdefunct here/man/figures/lifecycle-maturing.svg0000644000176200001440000000170613754151372017734 0ustar liggesuserslifecyclelifecyclematuringmaturing here/man/figures/lifecycle-archived.svg0000644000176200001440000000170713754151372017674 0ustar liggesusers lifecyclelifecyclearchivedarchived here/man/figures/lifecycle-soft-deprecated.svg0000644000176200001440000000172613754151372021161 0ustar liggesuserslifecyclelifecyclesoft-deprecatedsoft-deprecated here/man/figures/lifecycle-questioning.svg0000644000176200001440000000171413754151372020452 0ustar liggesuserslifecyclelifecyclequestioningquestioning here/man/figures/lifecycle-superseded.svg0000644000176200001440000000171313754151372020247 0ustar liggesusers lifecyclelifecyclesupersededsuperseded here/man/figures/lifecycle-stable.svg0000644000176200001440000000167413754151372017364 0ustar liggesuserslifecyclelifecyclestablestable here/man/figures/lifecycle-experimental.svg0000644000176200001440000000171613754151372020604 0ustar liggesuserslifecyclelifecycleexperimentalexperimental here/man/figures/lifecycle-deprecated.svg0000644000176200001440000000171213754151372020203 0ustar liggesuserslifecyclelifecycledeprecateddeprecated here/DESCRIPTION0000644000176200001440000000267613765341372012731 0ustar liggesusersPackage: here Title: A Simpler Way to Find Your Files Version: 1.0.1 Date: 2020-12-13 Authors@R: c(person(given = "Kirill", family = "M\u00fcller", role = c("aut", "cre"), email = "krlmlr+r@mailbox.org", comment = c(ORCID = "0000-0002-1416-3412")), person(given = "Jennifer", family = "Bryan", role = "ctb", email = "jenny@rstudio.com", comment = c(ORCID = "0000-0002-6983-2759"))) Description: Constructs paths to your project's files. Declare the relative path of a file within your project with 'i_am()'. Use the 'here()' function as a drop-in replacement for 'file.path()', it will always locate the files relative to your project root. License: MIT + file LICENSE URL: https://here.r-lib.org/, https://github.com/r-lib/here BugReports: https://github.com/r-lib/here/issues Imports: rprojroot (>= 2.0.2) Suggests: conflicted, covr, fs, knitr, palmerpenguins, plyr, readr, rlang, rmarkdown, testthat, uuid, withr VignetteBuilder: knitr Encoding: UTF-8 LazyData: true RoxygenNote: 7.1.1.9000 Config/testthat/edition: 3 NeedsCompilation: no Packaged: 2020-12-13 06:59:33 UTC; kirill Author: Kirill Müller [aut, cre] (), Jennifer Bryan [ctb] () Maintainer: Kirill Müller Repository: CRAN Date/Publication: 2020-12-13 07:30:02 UTC here/build/0000755000176200001440000000000013765335725012314 5ustar liggesusershere/build/vignette.rds0000644000176200001440000000034113765335725014651 0ustar liggesusersuP0,O1/+/h⵱ULixZݙvg{B&L J+)ރ(0J=9۝XKc",M^?!P7grw0fb` 4x SbFkuҼ9\:&* mf-I@߲<^X :gm6KGڑ&}5_٭here/tests/0000755000176200001440000000000013754142277012353 5ustar liggesusershere/tests/testthat/0000755000176200001440000000000013765341372014212 5ustar liggesusershere/tests/testthat/test-i_am.R0000644000176200001440000000117513765311001016205 0ustar liggesuserslocal_project() test_that("i_am() sets the project root", { # To reset later on local_here(here()) withr::local_dir(here()) expect_message( here::i_am("prepare/penguins.R", uuid = "115147ca-fedd-42ca-8650-2cb3dad0aebc"), "starts at" ) dr <- format_dr_here(show_reason = TRUE) dr <- gsub(here(), "", dr, fixed = TRUE) expect_snapshot(writeLines(dr)) }) test_that("i_am() fails with useful message", { # To reset later on local_here(here()) withr::local_dir(tempdir()) expect_snapshot_with_error( here::i_am("prepare/penguins.R", uuid = "115147ca-fedd-42ca-8650-2cb3dad0aebc") ) }) here/tests/testthat/setup.R0000644000176200001440000000023013754177052015470 0ustar liggesusersif (basename(getwd()) == "testthat" && basename(dirname(getwd())) == "tests") { withr::defer(testthat::snapshot_accept(path = "."), teardown_env()) } here/tests/testthat/test-dr_here.R0000644000176200001440000000145413754177052016726 0ustar liggesuserslocal_project() test_that("dr_here() shows message", { expect_message(dr_here(), "starts at") }) test_that("format_dr_here(show_reason = TRUE)", { dr <- format_dr_here(show_reason = TRUE) dr <- gsub(here(), "", dr, fixed = TRUE) dr <- gsub(getwd(), "", dr, fixed = TRUE) expect_snapshot(writeLines(dr)) }) test_that("format_dr_here(show_reason = FALSE)", { dr <- format_dr_here(show_reason = FALSE) dr <- gsub(here(), "", dr, fixed = TRUE) expect_snapshot(writeLines(dr)) }) test_that("format_dr_here() without root", { local_here(tempdir()) dr <- format_dr_here(show_reason = TRUE) dr <- gsub(here(), "", dr, fixed = TRUE) dr <- gsub(getwd(), "", dr, fixed = TRUE) expect_snapshot(writeLines(dr)) }) here/tests/testthat/helper-local.R0000644000176200001440000000106713754142277016711 0ustar liggesuserslocal_project <- function(..., .env = parent.frame()) { skip_if_not_installed("withr") path <- tempfile() dir.create(path) demo_path <- system.file("demo-project", package = "here") demo_files <- dir(demo_path, full.names = TRUE) file.copy(demo_files, path, recursive = TRUE) local_here(path, .env = .env) withr::defer(unlink(path, recursive = TRUE), .env) path } local_here <- function(path, ..., .env = parent.frame()) { old_root <- .root_env do_refresh_here(path) withr::defer(.root_env$root <- old_root, envir = .env) invisible() } here/tests/testthat/_snaps/0000755000176200001440000000000013765311003015461 5ustar liggesusershere/tests/testthat/_snaps/dr_here.md0000644000176200001440000000243313765311021017415 0ustar liggesusers# format_dr_here(show_reason = TRUE) Code writeLines(dr) Output here() starts at . - This directory contains a file matching "[.]Rproj$" with contents matching "^Version: " in the first line - Initial working directory: - Current working directory: # format_dr_here(show_reason = FALSE) Code writeLines(dr) Output here() starts at # format_dr_here() without root Code writeLines(dr) Output here() starts at . - This directory and its parents do not satisfy any of the following criteria: - contains a file ".here" - contains a file matching "[.]Rproj$" with contents matching "^Version: " in the first line - contains a file "DESCRIPTION" with contents matching "^Package: " - contains a file "remake.yml" - contains a file ".projectile" - contains a directory ".git" - contains a file ".git" with contents matching "^gitdir: " - contains a directory ".svn" ! Call `here::i_am()` in your scripts and reports, or use `set_here()` to create a `.here` file - Initial working directory: - Current working directory: here/tests/testthat/_snaps/i_am.md0000644000176200001440000000147113765311021016713 0ustar liggesusers# i_am() sets the project root Code writeLines(dr) Output here() starts at . - This directory contains a file "prepare/penguins.R" with contents "115147ca-fedd-42ca-8650-2cb3dad0aebc" in the first 100 lines - Initial working directory: - Current working directory: # i_am() fails with useful message Code here::i_am("prepare/penguins.R", uuid = "115147ca-fedd-42ca-8650-2cb3dad0aebc") Error Could not find associated project in working directory or any parent directory. - Path in project: prepare/penguins.R - File must contain: 115147ca-fedd-42ca-8650-2cb3dad0aebc - Current working directory: Please open the project associated with this file and try again. here/tests/testthat/test-here.R0000644000176200001440000000015613754142277016240 0ustar liggesuserslocal_project() test_that("here() finds files", { expect_true(file.exists(here("analysis/report.Rmd"))) }) here/tests/testthat/helper-expect.R0000644000176200001440000000041713765310726017103 0ustar liggesusersexpect_snapshot_with_error <- function(code) { code <- rlang::enexpr(code) if (packageVersion("testthat") > "3.0.0") { rlang::eval_tidy(rlang::quo(expect_snapshot(!!code, error = TRUE))) } else { rlang::eval_tidy(rlang::quo(expect_snapshot(!!code))) } } here/tests/testthat/test-set_here.R0000644000176200001440000000034013754142277017106 0ustar liggesuserstest_that("set_here() creates file", { local_project() expect_message(set_here(path = here()), "[Cc]reated file") expect_true(file.exists(here(".here"))) expect_message(set_here(path = here()), "already exists") }) here/tests/testthat.R0000644000176200001440000000006413754142277014336 0ustar liggesuserslibrary(testthat) library(here) test_check("here") here/vignettes/0000755000176200001440000000000013765335725013225 5ustar liggesusershere/vignettes/rmarkdown.Rmd0000644000176200001440000000442313754366712015676 0ustar liggesusers--- title: "Using here with rmarkdown" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Using here with rmarkdown} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", error = !identical(Sys.getenv("IN_PKGDOWN"), "true") ) project_path <- system.file("demo-project", package = "here") ``` The here package enables easy file referencing by using the top-level directory of a file project to easily build file paths. This article demonstrates the case where the working directory is set to a subdirectory of the project root, for instance when rendering an R Markdown document that lives in a subdirectory. See `vignette("here")` for a more general introduction. ## rmarkdown starts in a subdirectory For demonstration, this article uses a data analysis project that lives in `` `r project_path` `` on my machine. This is the *project root*. The path will most likely be different on your machine, the here package helps deal with this situation. The project has the following structure: ```{r echo = FALSE} fs::dir_tree(project_path) ``` When `report.Rmd` is rendered, the working directory is internally set to `/analysis` by rmarkdown: ```{r eval = FALSE} setwd(file.path(project_path, "analysis")) ``` ```{r include = FALSE} knitr::opts_knit$set(root.dir = file.path(project_path, "analysis")) ``` ```{r} getwd() ``` However, `penguins.csv` still lives in the `data/` subdirectory. The report requires the `penguins.csv` file to work. ## here always uses project-relative paths To render `report.Rmd`, you would have to ensure the path to `penguins.csv` is relative to the `analysis/` directory - i.e., `../data/penguins.csv`. The chunks would knit properly, but could not be run in the console since the working directory in the console *isn't* `analysis/`. The here package circumvents this issue by always referring to the project root: ```{r} here::i_am("analysis/report.Rmd") ``` All files accessed by `report.Rmd` should be referred to using `here()`: ```{r} library(here) here("data", "penguins.csv") here("data/penguins.csv") ``` This ensures that `penguins.csv` can be read both when the report is knit and when the code is run interactively in the console. here/vignettes/here.Rmd0000644000176200001440000002323313754366712014615 0ustar liggesusers--- title: "here" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{here} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", error = !identical(Sys.getenv("IN_PKGDOWN"), "true") ) project_path <- system.file("demo-project", package = "here") ``` The here package enables easy file referencing by using the top-level directory of a file project to easily build file paths. This is in contrast to using `setwd()`, which is fragile and dependent on the way you order your files on your computer. Read more about project-oriented workflows: - What They Forgot to Teach You About R: ["Project-oriented workflow"](https://rstats.wtf/project-oriented-workflow.html) chapter by Jenny Bryan and Jim Hester - ["Project-oriented workflow"](https://www.tidyverse.org/blog/2017/12/workflow-vs-script/) blog post by Jenny Bryan - R for data science: ["Workflow: projects"](https://r4ds.had.co.nz/workflow-projects.html) chapter by Hadley Wickham ## Basic functionality For demonstration, this article uses a data analysis project that lives in `` `r project_path` `` on my machine. This is the *project root*. The path will most likely be different on your machine, the here package helps deal with this situation. The project has the following structure: ```{r echo = FALSE} fs::dir_tree(project_path) ``` You can review the project on [GitHub](https://github.com/r-lib/here/tree/master/inst/demo-project) and also download a copy. To start working on this project in RStudio, open the `demo-project.Rproj` file. This ensures that the [working directory](https://en.wikipedia.org/wiki/Working_directory) is set to `` `r project_path` ``, the project root. Opening only the `.R` or the `.Rmd` file may be insufficient! Other development environments may have a different notion of a project. Either way, it is important that the working directory is set to the project root or a subdirectory of that path. You can check with: ```{r eval = FALSE} setwd(project_path) ``` ```{r include = FALSE} knitr::opts_knit$set(root.dir = project_path) ``` ```{r} getwd() ``` (See `vignette("rmarkdown")` for an example where the working directory is set to a subdirectory on start.) ### Declare the location of the current script The intended use is to add a call to `here::i_am()` at the beginning of your script or in the first chunk of your rmarkdown report.[^legacy] This achieves the following: [^legacy]: Prior to version 1.0.0, it was recommended to attach the here package via `library(here)`. This still works, but is no longer the recommended approach. - The location of the current script or report within the project is declared - The project root is initialized, consistent with the location of the current script or report - An informative message is emitted.[^print] [^print]: `library(here)` no longer emits an informative message if `here::i_am()` has been called before. The first argument to `here::i_am()` should be the path to the current file, relative to the project root. The `penguins.R` script uses: ```{r} here::i_am("prepare/penguins.R") ``` `here::i_am()` displays the top-level directory of the current project. Because the project has a `prepare/` directory in its root that contains `penguins.R`, it is correctly inferred as the project root. After `here::i_am()`, insert `library(here)` to make the `here()` function available:[^why-not-first] [^why-not-first]: `library(here)` emits a message that may be confusing if followed by the message from `here::i_am()`. ```{r} library(here) ``` The top-level directory is also returned from the `here()` function: ```{r} here() ``` One important distinction from the working directory is that this remains stable even if the working directory is changed: ```{r} setwd("analysis") getwd() here() setwd("..") ``` (I suggest to steer clear from ever changing the working directory. This may not always be feasible, in particular if the working directory is changed by code that you do not control.) ### Use project-relative paths You can build a path relative to the top-level directory in order to build the full path to a file: ```{r} here("data", "penguins.csv") readr::read_csv( here("data", "penguins.csv"), col_types = list(.default = readr::col_guess()), n_max = 3 ) ``` This works regardless of where the associated source file lives inside your project. With `here()`, the path will always be relative to the top-level project directory. `here()` works very similarly to `file.path()` or `fs::path()`, you can pass path components or entire subpaths: ```{r} here("data/penguins.csv") ``` As seen above, `here()` returns absolute paths (starting with `/`, `:\` or `\\`). This makes it safe to pass these paths to other functions, even if the working directory is changed along the way. As of version 1.0.0, absolute paths passed to `here()` are returned unchanged. This means that you can safely use both absolute and project-relative paths in `here()`. ```{r} data_path <- here("data") here(data_path) here(data_path, "penguins.csv") ``` ### Situation report The `dr_here()` function explains the reasoning behind choosing the project root: ```{r} dr_here() ``` The `show_reason` argument can be set to `FALSE` to reduce the output to one line: ```{r} dr_here(show_reason = FALSE) ``` ### What if the working directory is wrong? The declaration of the active file via `here::i_am()` also protects against accidentally running the script from a working directory outside of your project. The example below calls `here::i_am()` from the temporary directory, which is clearly outside our project: ```{r error = TRUE} withr::with_dir(tempdir(), { print(getwd()) here::i_am("prepare/penguins.R") }) ``` This can also happen when a file has been renamed or moved without updating the `here::i_am()` call. In the future, a helper function will assist with installing and updating suitably formatted `here::i_am()` calls in your scripts and reports. ## Extra safety ### Conflicts with other packages Other packages also export a `here()` function. Loading these packages after loading here masks our `here()` function: ```{r error = TRUE} library(plyr) here() ``` One way to work around this problem is to use `here::here()`: ```{r} here::here() ``` The conflicted package offers an alternative: it detects that `here()` is exported from more than one package and allows you to use neither until you indicate a preference. ```{r error = TRUE} library(conflicted) here() conflicted::conflict_prefer("here", "here") here() ``` ### Specify a unique identifier To eliminate potential confusion, `here::i_am()` accepts a `uuid` argument. The idea is that each script and report calls `here::i_am()` very early (in the first 100 lines) with a universally unique identifier. Even if a file location is reused across projects (e.g. two projects contain a "prepare/data.R" file), the files can be identified correctly if the `uuid` argument in the `here::i_am()` call is different. If a `uuid` argument is passed to `here::i_am()`: - a project root that contains a file at the specified file path is searched - the first 100 lines of that file are read - for the correct file, the `here::i_am()` call that passes this very `uuid` is among those 100 lines, and will be matched - for the wrong file, `uuid` is not found in the text Use `uuid::UUIDgenerate()` to create universally unique identifiers: ```{r} uuid::UUIDgenerate() ``` Ensure that the `uuid` arguments are actually unique across your files! In the future, a helper function will assist with installing and updating suitably formatted `here::i_am()` calls in your scripts and reports. ## Beyond here ### Change project root It is advisable to [start a fresh R session](https://rstats.wtf/save-source.html) as often as possible, especially before focusing on another project. There still may be legitimate cases when it is desirable to reset the project root. To start, let's create a temporary project for demonstration: ```{r} temp_project_path <- tempfile() dir.create(temp_project_path) scripts_path <- file.path(temp_project_path, "scripts") dir.create(scripts_path) script_path <- file.path(scripts_path, "script.R") writeLines( c( 'here::i_am("scripts/script.R")', 'print("Hello, world!")' ), script_path ) fs::dir_tree(temp_project_path) writeLines(readLines(script_path)) ``` The `script.R` file contains a call to `here::i_am()` to declare its location. Running it from the current working directory will fail: ```{r error = TRUE} source(script_path, echo = TRUE) ``` To reset the project root mid-session, change the working directory with `setwd()`. Now, the subsequent call to `here::i_am()` from within `script.R` works: ```{r eval = FALSE} setwd(temp_project_path) ``` ```{r include = FALSE} knitr::opts_knit$set(root.dir = temp_project_path) ``` ```{r} source(script_path, echo = TRUE) ``` To reiterate: a fresh session is almost always the better, cleaner, safer, and more robust solution. Use this approach only as a last resort. ### Under the hood: rprojroot The here package has a very simple and restricted interface, by design. The underlying logic is provided by the much more powerful rprojroot package. If the default behavior of here does not suit your workflow for one reason or another, the rprojroot package may be a better alternative. It is also recommended to import rprojroot and not here from other packages. The following example shows how to find an RStudio project starting from a directory: ```{r} library(rprojroot) find_root(is_rstudio_project, file.path(project_path, "analysis")) ``` Arbitrary criteria can be defined. See `vignette("rprojroot", package = "rprojroot")` for an introduction. here/R/0000755000176200001440000000000013754177052011411 5ustar liggesusershere/R/i_am.R0000644000176200001440000000545313754150007012437 0ustar liggesusers#' Declare location of current script or report #' #' Add a call to `here::i_am(".")` #' at the top of your R script or in the first chunk of your rmarkdown document. #' This ensures that the project root is set up correctly: #' subsequent calls to `here()` will refer to the implied project root. #' If the current working directory is outside of the project #' where the script or report is intended to run, it will fail #' with a descriptive message. #' #' Relying on the project root determined with a project file, #' the default for versions prior to 1.0.0, #' only weakly protects against running a script from an arbitrary directory #' outside the intended project. #' The `i_am()` function offers a stronger way to define the project root: #' it will ensure that the project root actually contains a file in that location, #' optionally checking for file contents that uniquely identify the file #' via the `nonce` argument. #' #' This function will fail if the script or report is moved within the project. #' Update the `i_am()` call to reflect the new location. #' If you use the `nonce` argument for extra safety, be sure to change it #' when you save an existing script or report under a new name. #' #' @param path `[character(1)]`\cr #' The path to the current script or report, relative to the project root. #' Passing an absolute path raises an error. #' @param ... Must be empty, reserved for future use. #' @param uuid `[character(1)]`\cr #' `r lifecycle::badge("experimental")` #' #' If not `NULL`, a unique string that is matched #' against the first 100 lines of the file. #' Use [uuid::UUIDgenerate()] to create a unique string #' that can be used as a `uuid` argument. #' #' @return This function is called for its side effects. #' @export #' @examples #' \dontrun{ #' here::i_am("prepare/penguins.R") #' here::i_am("analysis/report.Rmd", uuid = "f9e884084b84794d762a535f3facec85") #' } i_am <- function(path, ..., uuid = NULL) { stopifnot(length(list(...)) == 0) criterion <- has_file(path, contents = uuid, n = 100, fixed = TRUE) tryCatch( root_fun <- criterion$make_fix_file(), error = function(e) { stop( "Could not find associated project in working directory or any parent directory.\n", "- Path in project: ", path, "\n", if (!is.null(uuid)) { paste0("- File must contain: ", uuid, "\n") }, "- Current working directory: ", mockable_getwd(), "\n", "Please open the project associated with this file and try again.", call. = FALSE ) } ) set_root_crit(criterion) set_fix_fun(root_fun, i_am = TRUE) dr_here(show_reason = FALSE) invisible() } mockable_getwd <- function() { if (identical(Sys.getenv("TESTTHAT"), "true")) { "" } else { getwd() } } here/R/zzz.R0000644000176200001440000000057513754150007012367 0ustar liggesusers# nocov start #' @import rprojroot .onLoad <- function(libname, pkgname) { set_root_crit(is_here | is_rstudio_project | is_r_package | is_remake_project | is_projectile_project | is_vcs_root) do_refresh_here(".") } # nocov end .onAttach <- function(libname, pkgname) { if (!isTRUE(.root_env$root$i_am)) { packageStartupMessage(format_dr_here(show_reason = FALSE)) } } here/R/set_here.R0000644000176200001440000000252013754150007013320 0ustar liggesusers#' Add a marker file to a project #' #' `r lifecycle::badge("superseded")` #' #' `set_here()` creates an empty file named `.here`, by default #' in the current directory. #' When here encounters such a file, it uses the #' directory that contains this file as root. #' This is useful if none of the default criteria apply. #' You need to restart the R session so that `here()` #' picks up the newly created file. #' #' @section Life cycle: #' `set_here()` should no longer be necessary #' if all scripts and reports in a project call [here::i_am()], #' which is now the recommended workflow for declaring the project root. #' #' @keywords internal #' #' @param path `[character(1)]`\cr #' Directory where to create `.here` file, defaults to the current directory. #' @param verbose `[logical(1)]`\cr #' Verbose output, defaults to `TRUE`. #' @export set_here <- function(path = ".", verbose = TRUE) { path <- normalizePath(path) file_path <- file.path(path, ".here") if (file.exists(file_path)) { if (verbose) { message("File .here already exists in ", path) } } else { writeLines(character(), file_path) if (verbose) { message( "Created file .here in ", path, " . ", "Please start a new R session in the new project directory." ) } } invisible(file_path) } is_here <- has_file(".here") here/R/aaa.R0000644000176200001440000000164213754177052012261 0ustar liggesusers# nocov start format_root_section <- function() { paste( "\\section{Project root}{", "The project root is established with a call to `here::`[here::i_am()].", "Although not recommended, it can be changed by calling `here::i_am()` again.", "", "In the absence of such a call (e.g. for a new project),", "starting with the current working directory during package load time,", "the directory hierarchy is walked upwards ", "until a directory with at least one of the following conditions is found:", gsub('"([^"]+)"', "`\\1`", format_root_criteria_items()), "", "In either case, `here()` appends its arguments as path components ", "to the root directory.", "}", sep = "\n" ) } # nocov end format_root_criteria_items <- function(indent = 0) { format <- format(.root_env$root$crit)[-1L] format <- paste0(strrep(" ", indent), format) paste(format, collapse = "\n") } here/R/dr_here.R0000644000176200001440000000233213754177052013144 0ustar liggesusers#' Situation report #' #' `dr_here()` shows a message that by default also includes the #' reason why `here()` is set to a particular directory. #' Use this function if `here()` gives unexpected results. #' @param show_reason `[logical(1)]`\cr #' Include reason in output of `dr_here()`, defaults to `TRUE`. #' @export #' @examples #' dr_here() dr_here <- function(show_reason = TRUE) { message(format_dr_here(show_reason = show_reason)) } format_dr_here <- function(show_reason) { paste0( "here() starts at ", here(), if (show_reason) { paste0( ".", "\n- This directory ", format_reason(), "\n- Initial working directory: ", .root_env$root$wd, "\n- Current working directory: ", getwd(), NULL ) } ) } format_reason <- function() { root <- .root_env$root$f() if (any(vapply(.root_env$root$crit$testfun, function(f) f(root), logical(1L)))) { get_root_desc(.root_env$root$crit, .root_env$root$f()) } else { paste0( "and its parents do not satisfy any of the following criteria:\n", format_root_criteria_items(indent = 2), "\n", "! Call `here::i_am()` in your scripts and reports, or use `set_here()` to create a `.here` file" ) } } here/R/here.R0000644000176200001440000000332513754177052012462 0ustar liggesusers#' Find your files #' #' `here()` uses a reasonable heuristics to find your project's files, based on #' the current working directory at the time when the package is loaded. #' Use it as a drop-in replacement for [file.path()], it will always locate the #' files relative to your project root. #' #' This package is intended for interactive use only. #' Use [rprojroot::has_file()] or the other functions in #' the \pkg{rprojroot} package for more control, #' or for package development. #' #' If `here()` raises an error or otherwise behaves unexpectedly, #' you may have attached \pkg{plyr} or another package #' after \pkg{here}. #' Correct this using #' [the \pkg{conflicted} package](https://conflicted.r-lib.org/), #' or use `here::here("data", "df.rda")`. #' #' @evalRd roxygen2:::markdown(format_root_section()) #' #' @param ... `[character]`\cr #' Path components below the project root, can be empty. #' Each argument should be a string containing one or more #' path components separated by a forward slash `"/"`. #' @export #' @examples #' here() #' \dontrun{ #' here("some", "path", "below", "your", "project", "root.txt") #' here("some/path/below/your/project/root.txt") #' } here <- function(...) { .root_env$root$f(...) } .root_env <- new.env(parent = emptyenv()) set_root_crit <- function(criterion) { .root_env$root$crit <- criterion } do_refresh_here <- function(path) { tryCatch( set_fix_fun(.root_env$root$crit$make_fix_file(path = path), i_am = FALSE), error = function(e) { set_fix_fun(from_wd$make_fix_file(path = path), i_am = FALSE) } ) } set_fix_fun <- function(f, i_am) { force(f) force(i_am) .root_env$root$f <- f .root_env$root$wd <- getwd() .root_env$root$i_am <- i_am } here/NEWS.md0000644000176200001440000000312713765333741012312 0ustar liggesusers# here 1.0.1 (2020-12-13) - Adapt to testthat 3.0.1. # here 1.0.0 (2020-11-15) ## Features - New `here::i_am()` offers a new recommended way to declare the project root. Instead of relying on special files or directories that indicate the project root, each script and report now can declare its own location relative to the project root (#27). - `dr_here()` shows the initial and current working directory (#18, #55). ## Documentation - Improve readme and add "Getting started" vignette (#44, @sharlagelfand). Extend "Getting started" vignette with a detailed description of the behavior and use cases (#55). - Update `?here` to address conflict with `lubridate::here()` (#37, @nzgwynn). - New "rmarkdown" vignette (#55). - `set_here()` is superseded in favor of `here::i_am()` (#61). - More explicit documentation for the `...` argument to `here()` (#7). ## Internal - Add testthat tests (#57). - Use GitHub Actions for checks (#52). - Requires rprojroot >= 2.0.1. - Re-license as MIT (#50). - Added Jennifer Bryan as contributor (#32). # here 0.1 (2017-01-25) Initial CRAN release. - Main function `here()` - Uses a fixed root that contains a `.here` file or can be either an RStudio project, an R package, a `remake` project, a Projectile project, or a VCS repository. - The root is established at package loading time, and shown with a message. - The current working directory is used as a fallback. - The `set_here()` function creates a `.here` file so that a directory is recognized as root by `here()`. - The `dr_here()` function explains the reasoning of `here()` for the current session. here/MD50000644000176200001440000000527413765341372011530 0ustar liggesusers1b1db23b38394a0aac52a6f6f8f03444 *DESCRIPTION 93f110026220b05597cb3940ecbfe868 *LICENSE 5b2f2c6434205793ec20fbe7baf512a9 *NAMESPACE bafe0601cc5498da94d3d18c8ed6cee6 *NEWS.md 4cc1335cbea7bb5e307e5689ce21e72f *R/aaa.R a521ceb1bbdb803feb7404c45f8a245b *R/dr_here.R 9df5560100bc1ec088e8078a61af6681 *R/here.R 9ae87370f123e7ab04e215ad29c3bf49 *R/i_am.R cf3551541b701c07ab5f41ea6102a897 *R/set_here.R 10991e6728eb3e8f09eacbf3296c1532 *R/zzz.R 9394d19a2f460f539bf3ff370c92d4a1 *README.md 3aa9742f7421ea81e7b7e543930b0b86 *build/vignette.rds b721fca7668df666ae8ac753dd3e41b5 *inst/WORDLIST b296305f09e63870fa941b6b0d9076c6 *inst/demo-project/analysis/report.Rmd a06a0210251465a86fb970018292304d *inst/demo-project/data/penguins.csv 3936ed002c1dd1fa5dc7a13d99d5df86 *inst/demo-project/demo-project.Rproj 5d0a38962f43a5b84b2d406559bd3356 *inst/demo-project/prepare/penguins.R 95519daa5c358e5917141af423fb51f6 *inst/doc/here.R 84b9dd71253d5d3fb7974588ba4233fd *inst/doc/here.Rmd df8488f2a1be229413162d31d5f5a6c4 *inst/doc/here.html 54359b28b572320694303359d7119c99 *inst/doc/rmarkdown.R 255dc679ef919db654e7aced1a451f5b *inst/doc/rmarkdown.Rmd ce8e71fd52949054fa029b0aef3b9718 *inst/doc/rmarkdown.html 350274d28873b0a5abd94476fc487f59 *man/dr_here.Rd cb1e46f469cfbbbde29c8b5113e1d789 *man/figures/lifecycle-archived.svg c0d2e5a54f1fa4ff02bf9533079dd1f7 *man/figures/lifecycle-defunct.svg a1b8c987c676c16af790f563f96cbb1f *man/figures/lifecycle-deprecated.svg c3978703d8f40f2679795335715e98f4 *man/figures/lifecycle-experimental.svg 952b59dc07b171b97d5d982924244f61 *man/figures/lifecycle-maturing.svg 27b879bf3677ea76e3991d56ab324081 *man/figures/lifecycle-questioning.svg 6902bbfaf963fbc4ed98b86bda80caa2 *man/figures/lifecycle-soft-deprecated.svg 53b3f893324260b737b3c46ed2a0e643 *man/figures/lifecycle-stable.svg 1c1fe7a759b86dc6dbcbe7797ab8246c *man/figures/lifecycle-superseded.svg 7633203d21049845349cd352c13ad250 *man/here.Rd 5c9cf0465bded15f778a271c24787549 *man/i_am.Rd f226f75f898be3d2771df39616653b0b *man/set_here.Rd e6a18e8e7670512834be1f8b4403e05f *tests/testthat.R 9d93a86c4f7238c660106e55db4375e5 *tests/testthat/_snaps/dr_here.md eff2e1be7e04f87e61d3df3c9e281a9d *tests/testthat/_snaps/i_am.md 923b5820fbbd090b63de0cc21afcf7ad *tests/testthat/helper-expect.R ef7d5b1e0204b277a9f3301454d00715 *tests/testthat/helper-local.R 64f7ae5ce41985b8793165a23a146dc6 *tests/testthat/setup.R 131d197e51f962a26b368057bb396045 *tests/testthat/test-dr_here.R be418bf164890e06ce1bf7247b36d6ba *tests/testthat/test-here.R cb933152859f22e42605fc9807394abb *tests/testthat/test-i_am.R c129dbeafb921a052217dd91a28813b4 *tests/testthat/test-set_here.R 84b9dd71253d5d3fb7974588ba4233fd *vignettes/here.Rmd 255dc679ef919db654e7aced1a451f5b *vignettes/rmarkdown.Rmd here/inst/0000755000176200001440000000000013765335725012172 5ustar liggesusershere/inst/doc/0000755000176200001440000000000013765335725012737 5ustar liggesusershere/inst/doc/rmarkdown.html0000644000176200001440000003142413765335725015635 0ustar liggesusers Using here with rmarkdown

Using here with rmarkdown

The here package enables easy file referencing by using the top-level directory of a file project to easily build file paths. This article demonstrates the case where the working directory is set to a subdirectory of the project root, for instance when rendering an R Markdown document that lives in a subdirectory. See vignette("here") for a more general introduction.

rmarkdown starts in a subdirectory

For demonstration, this article uses a data analysis project that lives in /tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project on my machine. This is the project root. The path will most likely be different on your machine, the here package helps deal with this situation.

The project has the following structure:

#> /tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project
#> ├── analysis
#> │   └── report.Rmd
#> ├── data
#> │   └── penguins.csv
#> ├── demo-project.Rproj
#> └── prepare
#>     └── penguins.R

When report.Rmd is rendered, the working directory is internally set to <project root>/analysis by rmarkdown:

setwd(file.path(project_path, "analysis"))
getwd()
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project/analysis"

However, penguins.csv still lives in the data/ subdirectory. The report requires the penguins.csv file to work.

here always uses project-relative paths

To render report.Rmd, you would have to ensure the path to penguins.csv is relative to the analysis/ directory - i.e., ../data/penguins.csv. The chunks would knit properly, but could not be run in the console since the working directory in the console isn’t analysis/.

The here package circumvents this issue by always referring to the project root:

here::i_am("analysis/report.Rmd")
#> here() starts at /tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project

All files accessed by report.Rmd should be referred to using here():

library(here)
here("data", "penguins.csv")
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project/data/penguins.csv"
here("data/penguins.csv")
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project/data/penguins.csv"

This ensures that penguins.csv can be read both when the report is knit and when the code is run interactively in the console.

here/inst/doc/rmarkdown.R0000644000176200001440000000175713765335724015077 0ustar liggesusers## ---- include = FALSE--------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", error = !identical(Sys.getenv("IN_PKGDOWN"), "true") ) project_path <- system.file("demo-project", package = "here") ## ----echo = FALSE------------------------------------------------------------- fs::dir_tree(project_path) ## ----eval = FALSE------------------------------------------------------------- # setwd(file.path(project_path, "analysis")) ## ----include = FALSE---------------------------------------------------------- knitr::opts_knit$set(root.dir = file.path(project_path, "analysis")) ## ----------------------------------------------------------------------------- getwd() ## ----------------------------------------------------------------------------- here::i_am("analysis/report.Rmd") ## ----------------------------------------------------------------------------- library(here) here("data", "penguins.csv") here("data/penguins.csv") here/inst/doc/rmarkdown.Rmd0000644000176200001440000000442313754366712015410 0ustar liggesusers--- title: "Using here with rmarkdown" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Using here with rmarkdown} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", error = !identical(Sys.getenv("IN_PKGDOWN"), "true") ) project_path <- system.file("demo-project", package = "here") ``` The here package enables easy file referencing by using the top-level directory of a file project to easily build file paths. This article demonstrates the case where the working directory is set to a subdirectory of the project root, for instance when rendering an R Markdown document that lives in a subdirectory. See `vignette("here")` for a more general introduction. ## rmarkdown starts in a subdirectory For demonstration, this article uses a data analysis project that lives in `` `r project_path` `` on my machine. This is the *project root*. The path will most likely be different on your machine, the here package helps deal with this situation. The project has the following structure: ```{r echo = FALSE} fs::dir_tree(project_path) ``` When `report.Rmd` is rendered, the working directory is internally set to `/analysis` by rmarkdown: ```{r eval = FALSE} setwd(file.path(project_path, "analysis")) ``` ```{r include = FALSE} knitr::opts_knit$set(root.dir = file.path(project_path, "analysis")) ``` ```{r} getwd() ``` However, `penguins.csv` still lives in the `data/` subdirectory. The report requires the `penguins.csv` file to work. ## here always uses project-relative paths To render `report.Rmd`, you would have to ensure the path to `penguins.csv` is relative to the `analysis/` directory - i.e., `../data/penguins.csv`. The chunks would knit properly, but could not be run in the console since the working directory in the console *isn't* `analysis/`. The here package circumvents this issue by always referring to the project root: ```{r} here::i_am("analysis/report.Rmd") ``` All files accessed by `report.Rmd` should be referred to using `here()`: ```{r} library(here) here("data", "penguins.csv") here("data/penguins.csv") ``` This ensures that `penguins.csv` can be read both when the report is knit and when the code is run interactively in the console. here/inst/doc/here.html0000644000176200001440000011410213765335724014546 0ustar liggesusers here

here

The here package enables easy file referencing by using the top-level directory of a file project to easily build file paths. This is in contrast to using setwd(), which is fragile and dependent on the way you order your files on your computer. Read more about project-oriented workflows:

Basic functionality

For demonstration, this article uses a data analysis project that lives in /tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project on my machine. This is the project root. The path will most likely be different on your machine, the here package helps deal with this situation.

The project has the following structure:

#> /tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project
#> ├── analysis
#> │   └── report.Rmd
#> ├── data
#> │   └── penguins.csv
#> ├── demo-project.Rproj
#> └── prepare
#>     └── penguins.R

You can review the project on GitHub and also download a copy.

To start working on this project in RStudio, open the demo-project.Rproj file. This ensures that the working directory is set to /tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project, the project root. Opening only the .R or the .Rmd file may be insufficient!

Other development environments may have a different notion of a project. Either way, it is important that the working directory is set to the project root or a subdirectory of that path. You can check with:

setwd(project_path)
getwd()
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project"

(See vignette("rmarkdown") for an example where the working directory is set to a subdirectory on start.)

Declare the location of the current script

The intended use is to add a call to here::i_am() at the beginning of your script or in the first chunk of your rmarkdown report.1 This achieves the following:

  • The location of the current script or report within the project is declared
  • The project root is initialized, consistent with the location of the current script or report
  • An informative message is emitted.2

The first argument to here::i_am() should be the path to the current file, relative to the project root. The penguins.R script uses:

here::i_am("prepare/penguins.R")
#> here() starts at /tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project

here::i_am() displays the top-level directory of the current project. Because the project has a prepare/ directory in its root that contains penguins.R, it is correctly inferred as the project root.

After here::i_am(), insert library(here) to make the here() function available:3

library(here)

The top-level directory is also returned from the here() function:

here()
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project"

One important distinction from the working directory is that this remains stable even if the working directory is changed:

setwd("analysis")
getwd()
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project/analysis"
here()
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project"
setwd("..")

(I suggest to steer clear from ever changing the working directory. This may not always be feasible, in particular if the working directory is changed by code that you do not control.)

Use project-relative paths

You can build a path relative to the top-level directory in order to build the full path to a file:

here("data", "penguins.csv")
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project/data/penguins.csv"
readr::read_csv(
  here("data", "penguins.csv"),
  col_types = list(.default = readr::col_guess()),
  n_max = 3
)
#> # A tibble: 3 x 8
#>   species island bill_length_mm bill_depth_mm flipper_length_… body_mass_g sex  
#>   <chr>   <chr>           <dbl>         <dbl>            <dbl>       <dbl> <chr>
#> 1 Adelie  Torge…           39.1          18.7              181        3750 male 
#> 2 Adelie  Torge…           39.5          17.4              186        3800 fema…
#> 3 Adelie  Torge…           40.3          18                195        3250 fema…
#> # … with 1 more variable: year <dbl>

This works regardless of where the associated source file lives inside your project. With here(), the path will always be relative to the top-level project directory.

here() works very similarly to file.path() or fs::path(), you can pass path components or entire subpaths:

here("data/penguins.csv")
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project/data/penguins.csv"

As seen above, here() returns absolute paths (starting with /, <drive letter>:\ or \\). This makes it safe to pass these paths to other functions, even if the working directory is changed along the way.

As of version 1.0.0, absolute paths passed to here() are returned unchanged. This means that you can safely use both absolute and project-relative paths in here().

data_path <- here("data")
here(data_path)
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project/data"
here(data_path, "penguins.csv")
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project/data/penguins.csv"

Situation report

The dr_here() function explains the reasoning behind choosing the project root:

dr_here()
#> here() starts at /tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project.
#> - This directory contains a file "prepare/penguins.R"
#> - Initial working directory: /tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project
#> - Current working directory: /tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project

The show_reason argument can be set to FALSE to reduce the output to one line:

dr_here(show_reason = FALSE)
#> here() starts at /tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project

What if the working directory is wrong?

The declaration of the active file via here::i_am() also protects against accidentally running the script from a working directory outside of your project. The example below calls here::i_am() from the temporary directory, which is clearly outside our project:

withr::with_dir(tempdir(), {
  print(getwd())
  here::i_am("prepare/penguins.R")
})
#> [1] "/tmp/RtmpHuFWzz"
#> Error: Could not find associated project in working directory or any parent directory.
#> - Path in project: prepare/penguins.R
#> - Current working directory: /tmp/RtmpHuFWzz
#> Please open the project associated with this file and try again.

This can also happen when a file has been renamed or moved without updating the here::i_am() call. In the future, a helper function will assist with installing and updating suitably formatted here::i_am() calls in your scripts and reports.

Extra safety

Conflicts with other packages

Other packages also export a here() function. Loading these packages after loading here masks our here() function:

library(plyr)
#> 
#> Attaching package: 'plyr'
#> The following object is masked from 'package:here':
#> 
#>     here
here()
#> Error in here(): argument "f" is missing, with no default

One way to work around this problem is to use here::here():

here::here()
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project"

The conflicted package offers an alternative: it detects that here() is exported from more than one package and allows you to use neither until you indicate a preference.

library(conflicted)
here()
#> Error: [conflicted] `here` found in 2 packages.
#> Either pick the one you want with `::` 
#> * plyr::here
#> * here::here
#> Or declare a preference with `conflict_prefer()`
#> * conflict_prefer("here", "plyr")
#> * conflict_prefer("here", "here")

conflicted::conflict_prefer("here", "here")
#> [conflicted] Will prefer here::here over any other package
here()
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project"

Specify a unique identifier

To eliminate potential confusion, here::i_am() accepts a uuid argument. The idea is that each script and report calls here::i_am() very early (in the first 100 lines) with a universally unique identifier. Even if a file location is reused across projects (e.g. two projects contain a “prepare/data.R” file), the files can be identified correctly if the uuid argument in the here::i_am() call is different.

If a uuid argument is passed to here::i_am():

  • a project root that contains a file at the specified file path is searched
  • the first 100 lines of that file are read
  • for the correct file, the here::i_am() call that passes this very uuid is among those 100 lines, and will be matched
  • for the wrong file, uuid is not found in the text

Use uuid::UUIDgenerate() to create universally unique identifiers:

uuid::UUIDgenerate()
#> [1] "36f421ac-2d53-46d4-bfad-a0ac96491443"

Ensure that the uuid arguments are actually unique across your files! In the future, a helper function will assist with installing and updating suitably formatted here::i_am() calls in your scripts and reports.

Beyond here

Change project root

It is advisable to start a fresh R session as often as possible, especially before focusing on another project. There still may be legitimate cases when it is desirable to reset the project root.

To start, let’s create a temporary project for demonstration:

temp_project_path <- tempfile()
dir.create(temp_project_path)
scripts_path <- file.path(temp_project_path, "scripts")
dir.create(scripts_path)
script_path <- file.path(scripts_path, "script.R")
writeLines(
  c(
    'here::i_am("scripts/script.R")',
    'print("Hello, world!")'
  ),
  script_path
)
fs::dir_tree(temp_project_path)
#> /tmp/RtmpHuFWzz/file30547d5e00ca
#> └── scripts
#>     └── script.R
writeLines(readLines(script_path))
#> here::i_am("scripts/script.R")
#> print("Hello, world!")

The script.R file contains a call to here::i_am() to declare its location. Running it from the current working directory will fail:

source(script_path, echo = TRUE)
#> 
#> > here::i_am("scripts/script.R")
#> Error: Could not find associated project in working directory or any parent directory.
#> - Path in project: scripts/script.R
#> - Current working directory: /tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project
#> Please open the project associated with this file and try again.

To reset the project root mid-session, change the working directory with setwd(). Now, the subsequent call to here::i_am() from within script.R works:

setwd(temp_project_path)
source(script_path, echo = TRUE)
#> 
#> > here::i_am("scripts/script.R")
#> here() starts at /tmp/RtmpHuFWzz/file30547d5e00ca
#> 
#> > print("Hello, world!")
#> [1] "Hello, world!"

To reiterate: a fresh session is almost always the better, cleaner, safer, and more robust solution. Use this approach only as a last resort.

Under the hood: rprojroot

The here package has a very simple and restricted interface, by design. The underlying logic is provided by the much more powerful rprojroot package. If the default behavior of here does not suit your workflow for one reason or another, the rprojroot package may be a better alternative. It is also recommended to import rprojroot and not here from other packages.

The following example shows how to find an RStudio project starting from a directory:

library(rprojroot)
find_root(is_rstudio_project, file.path(project_path, "analysis"))
#> [1] "/tmp/RtmpnoXhd8/Rinst301434451937/here/demo-project"

Arbitrary criteria can be defined. See vignette("rprojroot", package = "rprojroot") for an introduction.


  1. Prior to version 1.0.0, it was recommended to attach the here package via library(here). This still works, but is no longer the recommended approach.↩︎

  2. library(here) no longer emits an informative message if here::i_am() has been called before.↩︎

  3. library(here) emits a message that may be confusing if followed by the message from here::i_am().↩︎

here/inst/doc/here.Rmd0000644000176200001440000002323313754366712014327 0ustar liggesusers--- title: "here" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{here} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", error = !identical(Sys.getenv("IN_PKGDOWN"), "true") ) project_path <- system.file("demo-project", package = "here") ``` The here package enables easy file referencing by using the top-level directory of a file project to easily build file paths. This is in contrast to using `setwd()`, which is fragile and dependent on the way you order your files on your computer. Read more about project-oriented workflows: - What They Forgot to Teach You About R: ["Project-oriented workflow"](https://rstats.wtf/project-oriented-workflow.html) chapter by Jenny Bryan and Jim Hester - ["Project-oriented workflow"](https://www.tidyverse.org/blog/2017/12/workflow-vs-script/) blog post by Jenny Bryan - R for data science: ["Workflow: projects"](https://r4ds.had.co.nz/workflow-projects.html) chapter by Hadley Wickham ## Basic functionality For demonstration, this article uses a data analysis project that lives in `` `r project_path` `` on my machine. This is the *project root*. The path will most likely be different on your machine, the here package helps deal with this situation. The project has the following structure: ```{r echo = FALSE} fs::dir_tree(project_path) ``` You can review the project on [GitHub](https://github.com/r-lib/here/tree/master/inst/demo-project) and also download a copy. To start working on this project in RStudio, open the `demo-project.Rproj` file. This ensures that the [working directory](https://en.wikipedia.org/wiki/Working_directory) is set to `` `r project_path` ``, the project root. Opening only the `.R` or the `.Rmd` file may be insufficient! Other development environments may have a different notion of a project. Either way, it is important that the working directory is set to the project root or a subdirectory of that path. You can check with: ```{r eval = FALSE} setwd(project_path) ``` ```{r include = FALSE} knitr::opts_knit$set(root.dir = project_path) ``` ```{r} getwd() ``` (See `vignette("rmarkdown")` for an example where the working directory is set to a subdirectory on start.) ### Declare the location of the current script The intended use is to add a call to `here::i_am()` at the beginning of your script or in the first chunk of your rmarkdown report.[^legacy] This achieves the following: [^legacy]: Prior to version 1.0.0, it was recommended to attach the here package via `library(here)`. This still works, but is no longer the recommended approach. - The location of the current script or report within the project is declared - The project root is initialized, consistent with the location of the current script or report - An informative message is emitted.[^print] [^print]: `library(here)` no longer emits an informative message if `here::i_am()` has been called before. The first argument to `here::i_am()` should be the path to the current file, relative to the project root. The `penguins.R` script uses: ```{r} here::i_am("prepare/penguins.R") ``` `here::i_am()` displays the top-level directory of the current project. Because the project has a `prepare/` directory in its root that contains `penguins.R`, it is correctly inferred as the project root. After `here::i_am()`, insert `library(here)` to make the `here()` function available:[^why-not-first] [^why-not-first]: `library(here)` emits a message that may be confusing if followed by the message from `here::i_am()`. ```{r} library(here) ``` The top-level directory is also returned from the `here()` function: ```{r} here() ``` One important distinction from the working directory is that this remains stable even if the working directory is changed: ```{r} setwd("analysis") getwd() here() setwd("..") ``` (I suggest to steer clear from ever changing the working directory. This may not always be feasible, in particular if the working directory is changed by code that you do not control.) ### Use project-relative paths You can build a path relative to the top-level directory in order to build the full path to a file: ```{r} here("data", "penguins.csv") readr::read_csv( here("data", "penguins.csv"), col_types = list(.default = readr::col_guess()), n_max = 3 ) ``` This works regardless of where the associated source file lives inside your project. With `here()`, the path will always be relative to the top-level project directory. `here()` works very similarly to `file.path()` or `fs::path()`, you can pass path components or entire subpaths: ```{r} here("data/penguins.csv") ``` As seen above, `here()` returns absolute paths (starting with `/`, `:\` or `\\`). This makes it safe to pass these paths to other functions, even if the working directory is changed along the way. As of version 1.0.0, absolute paths passed to `here()` are returned unchanged. This means that you can safely use both absolute and project-relative paths in `here()`. ```{r} data_path <- here("data") here(data_path) here(data_path, "penguins.csv") ``` ### Situation report The `dr_here()` function explains the reasoning behind choosing the project root: ```{r} dr_here() ``` The `show_reason` argument can be set to `FALSE` to reduce the output to one line: ```{r} dr_here(show_reason = FALSE) ``` ### What if the working directory is wrong? The declaration of the active file via `here::i_am()` also protects against accidentally running the script from a working directory outside of your project. The example below calls `here::i_am()` from the temporary directory, which is clearly outside our project: ```{r error = TRUE} withr::with_dir(tempdir(), { print(getwd()) here::i_am("prepare/penguins.R") }) ``` This can also happen when a file has been renamed or moved without updating the `here::i_am()` call. In the future, a helper function will assist with installing and updating suitably formatted `here::i_am()` calls in your scripts and reports. ## Extra safety ### Conflicts with other packages Other packages also export a `here()` function. Loading these packages after loading here masks our `here()` function: ```{r error = TRUE} library(plyr) here() ``` One way to work around this problem is to use `here::here()`: ```{r} here::here() ``` The conflicted package offers an alternative: it detects that `here()` is exported from more than one package and allows you to use neither until you indicate a preference. ```{r error = TRUE} library(conflicted) here() conflicted::conflict_prefer("here", "here") here() ``` ### Specify a unique identifier To eliminate potential confusion, `here::i_am()` accepts a `uuid` argument. The idea is that each script and report calls `here::i_am()` very early (in the first 100 lines) with a universally unique identifier. Even if a file location is reused across projects (e.g. two projects contain a "prepare/data.R" file), the files can be identified correctly if the `uuid` argument in the `here::i_am()` call is different. If a `uuid` argument is passed to `here::i_am()`: - a project root that contains a file at the specified file path is searched - the first 100 lines of that file are read - for the correct file, the `here::i_am()` call that passes this very `uuid` is among those 100 lines, and will be matched - for the wrong file, `uuid` is not found in the text Use `uuid::UUIDgenerate()` to create universally unique identifiers: ```{r} uuid::UUIDgenerate() ``` Ensure that the `uuid` arguments are actually unique across your files! In the future, a helper function will assist with installing and updating suitably formatted `here::i_am()` calls in your scripts and reports. ## Beyond here ### Change project root It is advisable to [start a fresh R session](https://rstats.wtf/save-source.html) as often as possible, especially before focusing on another project. There still may be legitimate cases when it is desirable to reset the project root. To start, let's create a temporary project for demonstration: ```{r} temp_project_path <- tempfile() dir.create(temp_project_path) scripts_path <- file.path(temp_project_path, "scripts") dir.create(scripts_path) script_path <- file.path(scripts_path, "script.R") writeLines( c( 'here::i_am("scripts/script.R")', 'print("Hello, world!")' ), script_path ) fs::dir_tree(temp_project_path) writeLines(readLines(script_path)) ``` The `script.R` file contains a call to `here::i_am()` to declare its location. Running it from the current working directory will fail: ```{r error = TRUE} source(script_path, echo = TRUE) ``` To reset the project root mid-session, change the working directory with `setwd()`. Now, the subsequent call to `here::i_am()` from within `script.R` works: ```{r eval = FALSE} setwd(temp_project_path) ``` ```{r include = FALSE} knitr::opts_knit$set(root.dir = temp_project_path) ``` ```{r} source(script_path, echo = TRUE) ``` To reiterate: a fresh session is almost always the better, cleaner, safer, and more robust solution. Use this approach only as a last resort. ### Under the hood: rprojroot The here package has a very simple and restricted interface, by design. The underlying logic is provided by the much more powerful rprojroot package. If the default behavior of here does not suit your workflow for one reason or another, the rprojroot package may be a better alternative. It is also recommended to import rprojroot and not here from other packages. The following example shows how to find an RStudio project starting from a directory: ```{r} library(rprojroot) find_root(is_rstudio_project, file.path(project_path, "analysis")) ``` Arbitrary criteria can be defined. See `vignette("rprojroot", package = "rprojroot")` for an introduction. here/inst/doc/here.R0000644000176200001440000000671213765335724014012 0ustar liggesusers## ---- include = FALSE--------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", error = !identical(Sys.getenv("IN_PKGDOWN"), "true") ) project_path <- system.file("demo-project", package = "here") ## ----echo = FALSE------------------------------------------------------------- fs::dir_tree(project_path) ## ----eval = FALSE------------------------------------------------------------- # setwd(project_path) ## ----include = FALSE---------------------------------------------------------- knitr::opts_knit$set(root.dir = project_path) ## ----------------------------------------------------------------------------- getwd() ## ----------------------------------------------------------------------------- here::i_am("prepare/penguins.R") ## ----------------------------------------------------------------------------- library(here) ## ----------------------------------------------------------------------------- here() ## ----------------------------------------------------------------------------- setwd("analysis") getwd() here() setwd("..") ## ----------------------------------------------------------------------------- here("data", "penguins.csv") readr::read_csv( here("data", "penguins.csv"), col_types = list(.default = readr::col_guess()), n_max = 3 ) ## ----------------------------------------------------------------------------- here("data/penguins.csv") ## ----------------------------------------------------------------------------- data_path <- here("data") here(data_path) here(data_path, "penguins.csv") ## ----------------------------------------------------------------------------- dr_here() ## ----------------------------------------------------------------------------- dr_here(show_reason = FALSE) ## ----error = TRUE------------------------------------------------------------- withr::with_dir(tempdir(), { print(getwd()) here::i_am("prepare/penguins.R") }) ## ----error = TRUE------------------------------------------------------------- library(plyr) here() ## ----------------------------------------------------------------------------- here::here() ## ----error = TRUE------------------------------------------------------------- library(conflicted) here() conflicted::conflict_prefer("here", "here") here() ## ----------------------------------------------------------------------------- uuid::UUIDgenerate() ## ----------------------------------------------------------------------------- temp_project_path <- tempfile() dir.create(temp_project_path) scripts_path <- file.path(temp_project_path, "scripts") dir.create(scripts_path) script_path <- file.path(scripts_path, "script.R") writeLines( c( 'here::i_am("scripts/script.R")', 'print("Hello, world!")' ), script_path ) fs::dir_tree(temp_project_path) writeLines(readLines(script_path)) ## ----error = TRUE------------------------------------------------------------- source(script_path, echo = TRUE) ## ----eval = FALSE------------------------------------------------------------- # setwd(temp_project_path) ## ----include = FALSE---------------------------------------------------------- knitr::opts_knit$set(root.dir = temp_project_path) ## ----------------------------------------------------------------------------- source(script_path, echo = TRUE) ## ----------------------------------------------------------------------------- library(rprojroot) find_root(is_rstudio_project, file.path(project_path, "analysis")) here/inst/demo-project/0000755000176200001440000000000013765335725014562 5ustar liggesusershere/inst/demo-project/prepare/0000755000176200001440000000000013754142277016214 5ustar liggesusershere/inst/demo-project/prepare/penguins.R0000644000176200001440000000024513754142277020170 0ustar liggesusershere::i_am("prepare/penguins.R", uuid = "115147ca-fedd-42ca-8650-2cb3dad0aebc") library(here) readr::write_csv(palmerpenguins::penguins, here("data/penguins.csv")) here/inst/demo-project/data/0000755000176200001440000000000013754142277015467 5ustar liggesusershere/inst/demo-project/data/penguins.csv0000644000176200001440000003561113754151765020044 0ustar liggesusersspecies,island,bill_length_mm,bill_depth_mm,flipper_length_mm,body_mass_g,sex,year Adelie,Torgersen,39.1,18.7,181,3750,male,2007 Adelie,Torgersen,39.5,17.4,186,3800,female,2007 Adelie,Torgersen,40.3,18,195,3250,female,2007 Adelie,Torgersen,NA,NA,NA,NA,NA,2007 Adelie,Torgersen,36.7,19.3,193,3450,female,2007 Adelie,Torgersen,39.3,20.6,190,3650,male,2007 Adelie,Torgersen,38.9,17.8,181,3625,female,2007 Adelie,Torgersen,39.2,19.6,195,4675,male,2007 Adelie,Torgersen,34.1,18.1,193,3475,NA,2007 Adelie,Torgersen,42,20.2,190,4250,NA,2007 Adelie,Torgersen,37.8,17.1,186,3300,NA,2007 Adelie,Torgersen,37.8,17.3,180,3700,NA,2007 Adelie,Torgersen,41.1,17.6,182,3200,female,2007 Adelie,Torgersen,38.6,21.2,191,3800,male,2007 Adelie,Torgersen,34.6,21.1,198,4400,male,2007 Adelie,Torgersen,36.6,17.8,185,3700,female,2007 Adelie,Torgersen,38.7,19,195,3450,female,2007 Adelie,Torgersen,42.5,20.7,197,4500,male,2007 Adelie,Torgersen,34.4,18.4,184,3325,female,2007 Adelie,Torgersen,46,21.5,194,4200,male,2007 Adelie,Biscoe,37.8,18.3,174,3400,female,2007 Adelie,Biscoe,37.7,18.7,180,3600,male,2007 Adelie,Biscoe,35.9,19.2,189,3800,female,2007 Adelie,Biscoe,38.2,18.1,185,3950,male,2007 Adelie,Biscoe,38.8,17.2,180,3800,male,2007 Adelie,Biscoe,35.3,18.9,187,3800,female,2007 Adelie,Biscoe,40.6,18.6,183,3550,male,2007 Adelie,Biscoe,40.5,17.9,187,3200,female,2007 Adelie,Biscoe,37.9,18.6,172,3150,female,2007 Adelie,Biscoe,40.5,18.9,180,3950,male,2007 Adelie,Dream,39.5,16.7,178,3250,female,2007 Adelie,Dream,37.2,18.1,178,3900,male,2007 Adelie,Dream,39.5,17.8,188,3300,female,2007 Adelie,Dream,40.9,18.9,184,3900,male,2007 Adelie,Dream,36.4,17,195,3325,female,2007 Adelie,Dream,39.2,21.1,196,4150,male,2007 Adelie,Dream,38.8,20,190,3950,male,2007 Adelie,Dream,42.2,18.5,180,3550,female,2007 Adelie,Dream,37.6,19.3,181,3300,female,2007 Adelie,Dream,39.8,19.1,184,4650,male,2007 Adelie,Dream,36.5,18,182,3150,female,2007 Adelie,Dream,40.8,18.4,195,3900,male,2007 Adelie,Dream,36,18.5,186,3100,female,2007 Adelie,Dream,44.1,19.7,196,4400,male,2007 Adelie,Dream,37,16.9,185,3000,female,2007 Adelie,Dream,39.6,18.8,190,4600,male,2007 Adelie,Dream,41.1,19,182,3425,male,2007 Adelie,Dream,37.5,18.9,179,2975,NA,2007 Adelie,Dream,36,17.9,190,3450,female,2007 Adelie,Dream,42.3,21.2,191,4150,male,2007 Adelie,Biscoe,39.6,17.7,186,3500,female,2008 Adelie,Biscoe,40.1,18.9,188,4300,male,2008 Adelie,Biscoe,35,17.9,190,3450,female,2008 Adelie,Biscoe,42,19.5,200,4050,male,2008 Adelie,Biscoe,34.5,18.1,187,2900,female,2008 Adelie,Biscoe,41.4,18.6,191,3700,male,2008 Adelie,Biscoe,39,17.5,186,3550,female,2008 Adelie,Biscoe,40.6,18.8,193,3800,male,2008 Adelie,Biscoe,36.5,16.6,181,2850,female,2008 Adelie,Biscoe,37.6,19.1,194,3750,male,2008 Adelie,Biscoe,35.7,16.9,185,3150,female,2008 Adelie,Biscoe,41.3,21.1,195,4400,male,2008 Adelie,Biscoe,37.6,17,185,3600,female,2008 Adelie,Biscoe,41.1,18.2,192,4050,male,2008 Adelie,Biscoe,36.4,17.1,184,2850,female,2008 Adelie,Biscoe,41.6,18,192,3950,male,2008 Adelie,Biscoe,35.5,16.2,195,3350,female,2008 Adelie,Biscoe,41.1,19.1,188,4100,male,2008 Adelie,Torgersen,35.9,16.6,190,3050,female,2008 Adelie,Torgersen,41.8,19.4,198,4450,male,2008 Adelie,Torgersen,33.5,19,190,3600,female,2008 Adelie,Torgersen,39.7,18.4,190,3900,male,2008 Adelie,Torgersen,39.6,17.2,196,3550,female,2008 Adelie,Torgersen,45.8,18.9,197,4150,male,2008 Adelie,Torgersen,35.5,17.5,190,3700,female,2008 Adelie,Torgersen,42.8,18.5,195,4250,male,2008 Adelie,Torgersen,40.9,16.8,191,3700,female,2008 Adelie,Torgersen,37.2,19.4,184,3900,male,2008 Adelie,Torgersen,36.2,16.1,187,3550,female,2008 Adelie,Torgersen,42.1,19.1,195,4000,male,2008 Adelie,Torgersen,34.6,17.2,189,3200,female,2008 Adelie,Torgersen,42.9,17.6,196,4700,male,2008 Adelie,Torgersen,36.7,18.8,187,3800,female,2008 Adelie,Torgersen,35.1,19.4,193,4200,male,2008 Adelie,Dream,37.3,17.8,191,3350,female,2008 Adelie,Dream,41.3,20.3,194,3550,male,2008 Adelie,Dream,36.3,19.5,190,3800,male,2008 Adelie,Dream,36.9,18.6,189,3500,female,2008 Adelie,Dream,38.3,19.2,189,3950,male,2008 Adelie,Dream,38.9,18.8,190,3600,female,2008 Adelie,Dream,35.7,18,202,3550,female,2008 Adelie,Dream,41.1,18.1,205,4300,male,2008 Adelie,Dream,34,17.1,185,3400,female,2008 Adelie,Dream,39.6,18.1,186,4450,male,2008 Adelie,Dream,36.2,17.3,187,3300,female,2008 Adelie,Dream,40.8,18.9,208,4300,male,2008 Adelie,Dream,38.1,18.6,190,3700,female,2008 Adelie,Dream,40.3,18.5,196,4350,male,2008 Adelie,Dream,33.1,16.1,178,2900,female,2008 Adelie,Dream,43.2,18.5,192,4100,male,2008 Adelie,Biscoe,35,17.9,192,3725,female,2009 Adelie,Biscoe,41,20,203,4725,male,2009 Adelie,Biscoe,37.7,16,183,3075,female,2009 Adelie,Biscoe,37.8,20,190,4250,male,2009 Adelie,Biscoe,37.9,18.6,193,2925,female,2009 Adelie,Biscoe,39.7,18.9,184,3550,male,2009 Adelie,Biscoe,38.6,17.2,199,3750,female,2009 Adelie,Biscoe,38.2,20,190,3900,male,2009 Adelie,Biscoe,38.1,17,181,3175,female,2009 Adelie,Biscoe,43.2,19,197,4775,male,2009 Adelie,Biscoe,38.1,16.5,198,3825,female,2009 Adelie,Biscoe,45.6,20.3,191,4600,male,2009 Adelie,Biscoe,39.7,17.7,193,3200,female,2009 Adelie,Biscoe,42.2,19.5,197,4275,male,2009 Adelie,Biscoe,39.6,20.7,191,3900,female,2009 Adelie,Biscoe,42.7,18.3,196,4075,male,2009 Adelie,Torgersen,38.6,17,188,2900,female,2009 Adelie,Torgersen,37.3,20.5,199,3775,male,2009 Adelie,Torgersen,35.7,17,189,3350,female,2009 Adelie,Torgersen,41.1,18.6,189,3325,male,2009 Adelie,Torgersen,36.2,17.2,187,3150,female,2009 Adelie,Torgersen,37.7,19.8,198,3500,male,2009 Adelie,Torgersen,40.2,17,176,3450,female,2009 Adelie,Torgersen,41.4,18.5,202,3875,male,2009 Adelie,Torgersen,35.2,15.9,186,3050,female,2009 Adelie,Torgersen,40.6,19,199,4000,male,2009 Adelie,Torgersen,38.8,17.6,191,3275,female,2009 Adelie,Torgersen,41.5,18.3,195,4300,male,2009 Adelie,Torgersen,39,17.1,191,3050,female,2009 Adelie,Torgersen,44.1,18,210,4000,male,2009 Adelie,Torgersen,38.5,17.9,190,3325,female,2009 Adelie,Torgersen,43.1,19.2,197,3500,male,2009 Adelie,Dream,36.8,18.5,193,3500,female,2009 Adelie,Dream,37.5,18.5,199,4475,male,2009 Adelie,Dream,38.1,17.6,187,3425,female,2009 Adelie,Dream,41.1,17.5,190,3900,male,2009 Adelie,Dream,35.6,17.5,191,3175,female,2009 Adelie,Dream,40.2,20.1,200,3975,male,2009 Adelie,Dream,37,16.5,185,3400,female,2009 Adelie,Dream,39.7,17.9,193,4250,male,2009 Adelie,Dream,40.2,17.1,193,3400,female,2009 Adelie,Dream,40.6,17.2,187,3475,male,2009 Adelie,Dream,32.1,15.5,188,3050,female,2009 Adelie,Dream,40.7,17,190,3725,male,2009 Adelie,Dream,37.3,16.8,192,3000,female,2009 Adelie,Dream,39,18.7,185,3650,male,2009 Adelie,Dream,39.2,18.6,190,4250,male,2009 Adelie,Dream,36.6,18.4,184,3475,female,2009 Adelie,Dream,36,17.8,195,3450,female,2009 Adelie,Dream,37.8,18.1,193,3750,male,2009 Adelie,Dream,36,17.1,187,3700,female,2009 Adelie,Dream,41.5,18.5,201,4000,male,2009 Gentoo,Biscoe,46.1,13.2,211,4500,female,2007 Gentoo,Biscoe,50,16.3,230,5700,male,2007 Gentoo,Biscoe,48.7,14.1,210,4450,female,2007 Gentoo,Biscoe,50,15.2,218,5700,male,2007 Gentoo,Biscoe,47.6,14.5,215,5400,male,2007 Gentoo,Biscoe,46.5,13.5,210,4550,female,2007 Gentoo,Biscoe,45.4,14.6,211,4800,female,2007 Gentoo,Biscoe,46.7,15.3,219,5200,male,2007 Gentoo,Biscoe,43.3,13.4,209,4400,female,2007 Gentoo,Biscoe,46.8,15.4,215,5150,male,2007 Gentoo,Biscoe,40.9,13.7,214,4650,female,2007 Gentoo,Biscoe,49,16.1,216,5550,male,2007 Gentoo,Biscoe,45.5,13.7,214,4650,female,2007 Gentoo,Biscoe,48.4,14.6,213,5850,male,2007 Gentoo,Biscoe,45.8,14.6,210,4200,female,2007 Gentoo,Biscoe,49.3,15.7,217,5850,male,2007 Gentoo,Biscoe,42,13.5,210,4150,female,2007 Gentoo,Biscoe,49.2,15.2,221,6300,male,2007 Gentoo,Biscoe,46.2,14.5,209,4800,female,2007 Gentoo,Biscoe,48.7,15.1,222,5350,male,2007 Gentoo,Biscoe,50.2,14.3,218,5700,male,2007 Gentoo,Biscoe,45.1,14.5,215,5000,female,2007 Gentoo,Biscoe,46.5,14.5,213,4400,female,2007 Gentoo,Biscoe,46.3,15.8,215,5050,male,2007 Gentoo,Biscoe,42.9,13.1,215,5000,female,2007 Gentoo,Biscoe,46.1,15.1,215,5100,male,2007 Gentoo,Biscoe,44.5,14.3,216,4100,NA,2007 Gentoo,Biscoe,47.8,15,215,5650,male,2007 Gentoo,Biscoe,48.2,14.3,210,4600,female,2007 Gentoo,Biscoe,50,15.3,220,5550,male,2007 Gentoo,Biscoe,47.3,15.3,222,5250,male,2007 Gentoo,Biscoe,42.8,14.2,209,4700,female,2007 Gentoo,Biscoe,45.1,14.5,207,5050,female,2007 Gentoo,Biscoe,59.6,17,230,6050,male,2007 Gentoo,Biscoe,49.1,14.8,220,5150,female,2008 Gentoo,Biscoe,48.4,16.3,220,5400,male,2008 Gentoo,Biscoe,42.6,13.7,213,4950,female,2008 Gentoo,Biscoe,44.4,17.3,219,5250,male,2008 Gentoo,Biscoe,44,13.6,208,4350,female,2008 Gentoo,Biscoe,48.7,15.7,208,5350,male,2008 Gentoo,Biscoe,42.7,13.7,208,3950,female,2008 Gentoo,Biscoe,49.6,16,225,5700,male,2008 Gentoo,Biscoe,45.3,13.7,210,4300,female,2008 Gentoo,Biscoe,49.6,15,216,4750,male,2008 Gentoo,Biscoe,50.5,15.9,222,5550,male,2008 Gentoo,Biscoe,43.6,13.9,217,4900,female,2008 Gentoo,Biscoe,45.5,13.9,210,4200,female,2008 Gentoo,Biscoe,50.5,15.9,225,5400,male,2008 Gentoo,Biscoe,44.9,13.3,213,5100,female,2008 Gentoo,Biscoe,45.2,15.8,215,5300,male,2008 Gentoo,Biscoe,46.6,14.2,210,4850,female,2008 Gentoo,Biscoe,48.5,14.1,220,5300,male,2008 Gentoo,Biscoe,45.1,14.4,210,4400,female,2008 Gentoo,Biscoe,50.1,15,225,5000,male,2008 Gentoo,Biscoe,46.5,14.4,217,4900,female,2008 Gentoo,Biscoe,45,15.4,220,5050,male,2008 Gentoo,Biscoe,43.8,13.9,208,4300,female,2008 Gentoo,Biscoe,45.5,15,220,5000,male,2008 Gentoo,Biscoe,43.2,14.5,208,4450,female,2008 Gentoo,Biscoe,50.4,15.3,224,5550,male,2008 Gentoo,Biscoe,45.3,13.8,208,4200,female,2008 Gentoo,Biscoe,46.2,14.9,221,5300,male,2008 Gentoo,Biscoe,45.7,13.9,214,4400,female,2008 Gentoo,Biscoe,54.3,15.7,231,5650,male,2008 Gentoo,Biscoe,45.8,14.2,219,4700,female,2008 Gentoo,Biscoe,49.8,16.8,230,5700,male,2008 Gentoo,Biscoe,46.2,14.4,214,4650,NA,2008 Gentoo,Biscoe,49.5,16.2,229,5800,male,2008 Gentoo,Biscoe,43.5,14.2,220,4700,female,2008 Gentoo,Biscoe,50.7,15,223,5550,male,2008 Gentoo,Biscoe,47.7,15,216,4750,female,2008 Gentoo,Biscoe,46.4,15.6,221,5000,male,2008 Gentoo,Biscoe,48.2,15.6,221,5100,male,2008 Gentoo,Biscoe,46.5,14.8,217,5200,female,2008 Gentoo,Biscoe,46.4,15,216,4700,female,2008 Gentoo,Biscoe,48.6,16,230,5800,male,2008 Gentoo,Biscoe,47.5,14.2,209,4600,female,2008 Gentoo,Biscoe,51.1,16.3,220,6000,male,2008 Gentoo,Biscoe,45.2,13.8,215,4750,female,2008 Gentoo,Biscoe,45.2,16.4,223,5950,male,2008 Gentoo,Biscoe,49.1,14.5,212,4625,female,2009 Gentoo,Biscoe,52.5,15.6,221,5450,male,2009 Gentoo,Biscoe,47.4,14.6,212,4725,female,2009 Gentoo,Biscoe,50,15.9,224,5350,male,2009 Gentoo,Biscoe,44.9,13.8,212,4750,female,2009 Gentoo,Biscoe,50.8,17.3,228,5600,male,2009 Gentoo,Biscoe,43.4,14.4,218,4600,female,2009 Gentoo,Biscoe,51.3,14.2,218,5300,male,2009 Gentoo,Biscoe,47.5,14,212,4875,female,2009 Gentoo,Biscoe,52.1,17,230,5550,male,2009 Gentoo,Biscoe,47.5,15,218,4950,female,2009 Gentoo,Biscoe,52.2,17.1,228,5400,male,2009 Gentoo,Biscoe,45.5,14.5,212,4750,female,2009 Gentoo,Biscoe,49.5,16.1,224,5650,male,2009 Gentoo,Biscoe,44.5,14.7,214,4850,female,2009 Gentoo,Biscoe,50.8,15.7,226,5200,male,2009 Gentoo,Biscoe,49.4,15.8,216,4925,male,2009 Gentoo,Biscoe,46.9,14.6,222,4875,female,2009 Gentoo,Biscoe,48.4,14.4,203,4625,female,2009 Gentoo,Biscoe,51.1,16.5,225,5250,male,2009 Gentoo,Biscoe,48.5,15,219,4850,female,2009 Gentoo,Biscoe,55.9,17,228,5600,male,2009 Gentoo,Biscoe,47.2,15.5,215,4975,female,2009 Gentoo,Biscoe,49.1,15,228,5500,male,2009 Gentoo,Biscoe,47.3,13.8,216,4725,NA,2009 Gentoo,Biscoe,46.8,16.1,215,5500,male,2009 Gentoo,Biscoe,41.7,14.7,210,4700,female,2009 Gentoo,Biscoe,53.4,15.8,219,5500,male,2009 Gentoo,Biscoe,43.3,14,208,4575,female,2009 Gentoo,Biscoe,48.1,15.1,209,5500,male,2009 Gentoo,Biscoe,50.5,15.2,216,5000,female,2009 Gentoo,Biscoe,49.8,15.9,229,5950,male,2009 Gentoo,Biscoe,43.5,15.2,213,4650,female,2009 Gentoo,Biscoe,51.5,16.3,230,5500,male,2009 Gentoo,Biscoe,46.2,14.1,217,4375,female,2009 Gentoo,Biscoe,55.1,16,230,5850,male,2009 Gentoo,Biscoe,44.5,15.7,217,4875,NA,2009 Gentoo,Biscoe,48.8,16.2,222,6000,male,2009 Gentoo,Biscoe,47.2,13.7,214,4925,female,2009 Gentoo,Biscoe,NA,NA,NA,NA,NA,2009 Gentoo,Biscoe,46.8,14.3,215,4850,female,2009 Gentoo,Biscoe,50.4,15.7,222,5750,male,2009 Gentoo,Biscoe,45.2,14.8,212,5200,female,2009 Gentoo,Biscoe,49.9,16.1,213,5400,male,2009 Chinstrap,Dream,46.5,17.9,192,3500,female,2007 Chinstrap,Dream,50,19.5,196,3900,male,2007 Chinstrap,Dream,51.3,19.2,193,3650,male,2007 Chinstrap,Dream,45.4,18.7,188,3525,female,2007 Chinstrap,Dream,52.7,19.8,197,3725,male,2007 Chinstrap,Dream,45.2,17.8,198,3950,female,2007 Chinstrap,Dream,46.1,18.2,178,3250,female,2007 Chinstrap,Dream,51.3,18.2,197,3750,male,2007 Chinstrap,Dream,46,18.9,195,4150,female,2007 Chinstrap,Dream,51.3,19.9,198,3700,male,2007 Chinstrap,Dream,46.6,17.8,193,3800,female,2007 Chinstrap,Dream,51.7,20.3,194,3775,male,2007 Chinstrap,Dream,47,17.3,185,3700,female,2007 Chinstrap,Dream,52,18.1,201,4050,male,2007 Chinstrap,Dream,45.9,17.1,190,3575,female,2007 Chinstrap,Dream,50.5,19.6,201,4050,male,2007 Chinstrap,Dream,50.3,20,197,3300,male,2007 Chinstrap,Dream,58,17.8,181,3700,female,2007 Chinstrap,Dream,46.4,18.6,190,3450,female,2007 Chinstrap,Dream,49.2,18.2,195,4400,male,2007 Chinstrap,Dream,42.4,17.3,181,3600,female,2007 Chinstrap,Dream,48.5,17.5,191,3400,male,2007 Chinstrap,Dream,43.2,16.6,187,2900,female,2007 Chinstrap,Dream,50.6,19.4,193,3800,male,2007 Chinstrap,Dream,46.7,17.9,195,3300,female,2007 Chinstrap,Dream,52,19,197,4150,male,2007 Chinstrap,Dream,50.5,18.4,200,3400,female,2008 Chinstrap,Dream,49.5,19,200,3800,male,2008 Chinstrap,Dream,46.4,17.8,191,3700,female,2008 Chinstrap,Dream,52.8,20,205,4550,male,2008 Chinstrap,Dream,40.9,16.6,187,3200,female,2008 Chinstrap,Dream,54.2,20.8,201,4300,male,2008 Chinstrap,Dream,42.5,16.7,187,3350,female,2008 Chinstrap,Dream,51,18.8,203,4100,male,2008 Chinstrap,Dream,49.7,18.6,195,3600,male,2008 Chinstrap,Dream,47.5,16.8,199,3900,female,2008 Chinstrap,Dream,47.6,18.3,195,3850,female,2008 Chinstrap,Dream,52,20.7,210,4800,male,2008 Chinstrap,Dream,46.9,16.6,192,2700,female,2008 Chinstrap,Dream,53.5,19.9,205,4500,male,2008 Chinstrap,Dream,49,19.5,210,3950,male,2008 Chinstrap,Dream,46.2,17.5,187,3650,female,2008 Chinstrap,Dream,50.9,19.1,196,3550,male,2008 Chinstrap,Dream,45.5,17,196,3500,female,2008 Chinstrap,Dream,50.9,17.9,196,3675,female,2009 Chinstrap,Dream,50.8,18.5,201,4450,male,2009 Chinstrap,Dream,50.1,17.9,190,3400,female,2009 Chinstrap,Dream,49,19.6,212,4300,male,2009 Chinstrap,Dream,51.5,18.7,187,3250,male,2009 Chinstrap,Dream,49.8,17.3,198,3675,female,2009 Chinstrap,Dream,48.1,16.4,199,3325,female,2009 Chinstrap,Dream,51.4,19,201,3950,male,2009 Chinstrap,Dream,45.7,17.3,193,3600,female,2009 Chinstrap,Dream,50.7,19.7,203,4050,male,2009 Chinstrap,Dream,42.5,17.3,187,3350,female,2009 Chinstrap,Dream,52.2,18.8,197,3450,male,2009 Chinstrap,Dream,45.2,16.6,191,3250,female,2009 Chinstrap,Dream,49.3,19.9,203,4050,male,2009 Chinstrap,Dream,50.2,18.8,202,3800,male,2009 Chinstrap,Dream,45.6,19.4,194,3525,female,2009 Chinstrap,Dream,51.9,19.5,206,3950,male,2009 Chinstrap,Dream,46.8,16.5,189,3650,female,2009 Chinstrap,Dream,45.7,17,195,3650,female,2009 Chinstrap,Dream,55.8,19.8,207,4000,male,2009 Chinstrap,Dream,43.5,18.1,202,3400,female,2009 Chinstrap,Dream,49.6,18.2,193,3775,male,2009 Chinstrap,Dream,50.8,19,210,4100,male,2009 Chinstrap,Dream,50.2,18.7,198,3775,female,2009 here/inst/demo-project/analysis/0000755000176200001440000000000013754142277016401 5ustar liggesusershere/inst/demo-project/analysis/report.Rmd0000644000176200001440000000062413754142277020362 0ustar liggesusers--- title: "Palmer penguins" author: "Kirill Müller" date: "11/12/2020" output: html_document --- ```{r setup, include=FALSE} here::i_am("analysis/report.Rmd", uuid = "50208352-4ee9-4401-bb40-9f7ec81050da") library(here) knitr::opts_chunk$set(echo = TRUE) penguins <- readr::read_csv(here("data/penguins.csv")) ``` ## Linear model ```{r} lm(flipper_length_mm ~ body_mass_g + species, penguins) ``` here/inst/demo-project/demo-project.Rproj0000644000176200001440000000060113754142277020161 0ustar liggesusersVersion: 1.0 RestoreWorkspace: No SaveWorkspace: No AlwaysSaveHistory: Default EnableCodeIndexing: Yes UseSpacesForTab: Yes NumSpacesForTab: 2 Encoding: UTF-8 RnwWeave: knitr LaTeX: pdfLaTeX AutoAppendNewline: Yes StripTrailingWhitespace: Yes BuildType: Package PackageUseDevtools: Yes PackageInstallArgs: --no-multiarch --with-keep.source PackageRoxygenize: rd,collate,namespace here/inst/WORDLIST0000644000176200001440000000016213754142277013357 0ustar liggesusersCodecov Hadley Horst Lifecycle RStudio VCS Wickham rcc readme rmarkdown rprojroot subpaths subsequential testthat