here v1.0.2
Just a small note that here v1.0.2 adding support for detecting Quarto and other project types is probably a bigger change than is signaled with the patch release version bump.
I have a repo with a Quarto website in a subfolder. With v1.0.2, calling here::here() inside the Quarto website points to /website where elsewhere in the repo it points to the repo root.
It's not a big deal and after updating paths I feel like it's a net positive; but it did take a minute to discover.
Thanks for the heads-up!
This change actually broke a bunch of my team's Quarto documents (we've reverted to 1.0.1). If I run the code chunks manually it works fine but I can't render them because it can't find the files I point to with here::here(). One of the benefits of using here for me was that it pointed to the same file no matter where in a project I ran the code (R script or Qmd file anywhere within my project).
Is there a way to not detect Quarto projects?
Thanks. For now, please use here v1.0.1 or the lower-level rprojroot package for custom criteria.
@jennybc: How do you feel about detecting Quarto projects?
I keep bumping into this and would really love for a way to disable the Quarto project detection
I guess I still feel like it makes sense to detect a folder containing _quarto.yml as a project, at least by default. So are the folks weighing in here saying that they have quarto projects (folders with a _quarto.yml file) nested inside a parent folder AND they want to refer to files outside the quarto projects from inside the projects? I think we could really benefit from some concrete scenarios here. I'm struggling to "get it".
But on a more general level, it does also feel possible that here should offer a way to configure the root-finding criteria. I do something similar in gargle, but there it's about an internal registry of auth methods to try. 99% of folks accept the defaults but every now and then it truly is useful to nuke one of the methods in a specific setting. And to pre-empt one possible response: one could refer folks to a lower-level tool like rprojroot, but there's such a big gap in user-friendliness and UX between here and rprojroot that I'm not sure that's a reasonable solution.
An option that allows for a character vector that defines the active criteria? Or alternatively a list of criterion objects?
Yeah, in my case, I frequently have a quarto website that isn't at the repo root, something like a monorepo with a Quarto website for documentation:
├── pkg-r
├── pkg-py
└── docs
or a workshop repo with the workshop's website in a sub-folder
├── _exercises
├── _solutions
└── website
Prior to this change, I could use here::here() inside website/ and docs/ without having to worry about how and where quarto render is executed. I could, for example:
- Have code in
_solutionsthat I inline and evaluate in the website prose - Have text in the website that runs or finds code in a parent directory
- Use
here::here()insidedocs/andwebsite/and not worry about whether I callquarto render docsor(cd docs && quarto render .).
GitHub Actions tooling tends to naturally run quarto render docs or quarto render website, which means that the working directory for R code being evaluated in the process is the repo root. But locally, previewing the website in Positron runs quarto render from within docs/ or website/, and it becomes difficult to write code using here::here() that gracefully accounts for the change in working directory.
This isn't as much of a problem for code in pkg-r because the R package development workflow generally requires that I move into pkg-r/ for all normal operations.
In my cases, I'd be happy to set an envvar like HERE_DETECT_QUARTO_ROOT=false and opt out of this behavior (in part because I mostly run into this problem when moving between CI and local dev, which is the kind of bump I'm wanting to avoid by using here in the first place). I recognize an envvar might not be everyone's favorite solution.
My team has a consistent (and enforced) folder structure between all our projects (which are all R projects), something like: ├── data ├── scripts ├── intermediate files └── outputs
The scripts folder contains all R and (if there are any) Quarto files. The R scripts often create intermediate files that other R/Quarto files load. The here() function previously ensured that all file references would work in both R files and Quarto files wherever they were in the project but that is no longer the case when using a _quarto.yml file.
For my team, it's not a "Quarto project", it's an R project where one of the steps is to put results into a Quarto file. The Quarto piece may be a level or two deep so we want file references relative to the overall project.
I agree that it makes sense to use Quarto projects by default, but a simple/consistent way to disable that would be nice. I would be in favour of an environment variable as @gadenbuie suggested. That way we could turn it off globally (.Renviron) but also enable it for a specific project if needed.
Thanks for adding color, folks!
@wmattbrown It feels like if you just have quarto documents (Quarto files, as you say), the project root should remain as it was before (whatever folder is the parent of data, scripts, intermediate files, outputs). So you can have .qmd files below scripts/ and they can refer to things in intermediate files/. Is there some reason that you also have _quarto.yml in scripts/? I think this is what I'm not understanding.
Thanks for adding color, folks!
@wmattbrown It feels like if you just have quarto documents (Quarto files, as you say), the project root should remain as it was before (whatever folder is the parent of data, scripts, intermediate files, outputs). So you can have
.qmdfiles belowscripts/and they can refer to things inintermediate files/. Is there some reason that you also have_quarto.ymlinscripts/? I think this is what I'm not understanding.
We don't always have a _quarto.yml but when we do, it's because we're pulling in multiple quarto documents into a single output or creating outputs in multiple formats. We sometimes also set the output-dir so the rendered files go directly into the output folder.
Another idea that I like would be to have here() variants for different root criteria. I've done this with rprojroot, but it's honestly a bit tedious (as in, I end up consulting the help docs and writing a wrapper function).
It could be nice to have a small set of here variants, e.g.
-
here_r_pkg() -
here_quarto() -
here_git()(orhere_vcs()to include SVN repos) -
here_rproj() -
here_vscode() -
here_here()
Or possibly, a variant here_from(root_file, ...) that covers the cases where a single file determines the here root, which would leave
-
here_r_pkg() -
here_git() -
here_proj()(RStudio + VS Code project) -
here_from(), e.g.here_from("_quarto.yml", ...)orhere_from(".here", ...)
I really like the idea of being able to choose which strategy is applied. I also like being able to call here() from inside a subfolder of a particular project type and know that I'm targeting the actual root as determined by a different criteria.
Maybe that could also manifest as a new argument, e.g. here(..., criteria = c("git", "project")).
Another detail on the Quarto website in a subfolder angle: I frequently use renv in these scenarios as well, in which case it's important that renv exist at the project root and that the website be rendered with the git repo root as the working directory.
Otherwise you need to do some frustrating gymnastics beyond what I described above to get renv + quarto + GHA to all play and work nicely together – if you're trying to solve the problem by controlling the working directory.
I came up with this relatively easier solution by adding website/.Rprofile that sets here's root directory if website/ is used for the R process:
# website/.Rprofile
if (basename(getwd()) == "website") {
withr::with_dir("..", here::i_am(".Rprofile"))
}
This works but feels a bit like swimming upstream.
Edit: Actually, I've been fighting CI on this all day and I still don't have it working. I'm giving up and removing here from this particular project.
To clarify a little bit, my experience is that _quarto.yml doesn't carry the same weight of execution context that the other criteria do. quarto render will happily run from anywhere and will make use of _quarto.yml, but it doesn't guarantee "a project or execution root" in the same way that a .git or a DESCRIPTION file do.
It'd be quite a bit more complex than the current solution (and therefore maybe not desirable), but I'd be happy with a solution that uses _quarto.yml to find the root location in the absence of other signals.
My mind is elsewhere at this moment, but I feel like this discussion has been super helpful at generating much more detailed and actionable ideas. I think the recent expansion of default project root criteria is a real net win, but it's obviously caused some pain, which kinda makes sense. It totally stands to reason that growing that list basically comes with a greater need (the first need, really) to offer easier ways to explicitly customize or control here.
I would be happy to join in (or even take the lead) on implementing something based on the above soon. I've just had a very trying month of computer chaos and am getting settled back in to my newly repaired mac 😅 .
Same situation here with documentation for a project generated from a docs subfolder. A few comments on the discussion.
I am not sure about the "Is there some reason that you also have _quarto.yml in [subfolder] ?" question, does not make sense to me to put the _quarto.yaml elsewhere. I just checked, it does work at the root level, but in combination with output_dir: public it creates a nested docs inside public that I do not know how to get rid of. So not sure how to handle without guidance.
I actually would have expected the .here file to take precedence over all other ways to determine root directory, as it is the only file that is set up on purpose by the user to signal directory "rootness".
And as said in the other discussion, at the moment it does not seem like _quarto.yaml (with an A in yaml) is detected.
I actually would have expected the
.herefile to take precedence
Project-root-finding proceeds upwards from current working directory and stops the first time a root criterion is satisfied. So practically speaking, there's no hierarchy of criteria, i.e. where one would take precedence over another.
I understand the current logic but talking like a user here :) And as a user, when I set up a .here file I expect it to take precedence.