Using subdirectories with quarto and RStudio - r

Please consider the following.
I like to structure my R projects with different subdirectories. Using bookdown or quarto seems to make this quite difficult since both like to have their source files (.Rmd or .qmd) in the project directory. I was hoping that this will get easier with quarto but this does not seem the case, although it should be possible according to this post.
Problem description (replicable example)
Start a new quarto book project in RStudio: File > New Project > New Directory > Quarto Book.
This will create several .qmd files in the R project directory. Now create new subdirectories. Starting from the R project directory: scripts/qmd.
If we put all .qmd files from the R project directory into scripts/qmd, we also need adapt their path in the _quarto.yml (e.g., from index.qmd to / scripts/qmd/index.qmd).
After doing so and pressing the Render button, we receive the ERROR: Book contents must include a home page (e.g. index.md).
Putting only the index.qmd file back into the R Project directory (and adapt the _quarto.yml), the book can be rendered.
Question
How can we put all .qmd files into a dedicated subdirectory?
Edit (ignore below)
Originally the below question was also asked but is now answered: quarto does not seem to have a "merge-knit" option like bookdown (see here). This unfortunately makes quarto useless for my use case.
If this is not possible, how can we make sure that object created in the R project directory are accessible for the .qmd files in the subdirectories? (setting execute-dir: project as suggested here did not work for me.

I'm assuming your purpose is just a specific personal preference for file organization.
You can have a large portion of your content in subdirectories (and that's my understanding of what Alison's blog post refers to), but you still need to have your index.qmd in the root. For example, you can have a subdirectory for projects, another one for posts, another one for tutorials, like Alison does.
In any case, one way of achieving what you want is by using pre- and post-render scripts.
You could move all the files from the scripts/qmd directory before rendering and then move them all back afterwards.
pre-render: mv scripts/qmd/*.qmd .
post-render: mv *.qmd scripts/qmd
Incidentally, that doesn't match my own personal preference ;-)

#Lucas A. Meyer, I tested the pre-render and post render options you suggested above, however, it throws an error after moving the file from my subdirectory to the project root:
ERROR: NotFound: The system cannot find the file specified. (os error 2)
Then, it fails to render the file and move it back to the original subdirectory location.
I then set execute-dir: project in my .yml file thinking it was trying to execute in the wrong folder, but it did not change anything.
P.S. I would have added as a comment, but my reputation is not high enough, yet. :(
UPDATE1:
I thinking I found a workaround for the time being. I've include the following project options beneath the project: header:
output-dir: subdir1/subdir2 Moves the html file, only.
post-render: xcopy *_files subdir1/subdir2 /E Copies the supporting files over.
The mv shell command can't be used for directories or you get the Directory Not Empty error.`

Related

How can I parse subdirectories in an R package? [duplicate]

When developing packages in R all R source files are put in the subdirectory R/, and all compiled code is put in the subdirectory src/.
I would like to add some organisation to files within these folders, rather than have everything dumped at the top level. For example, lets say I'm hypothetically developing a client-server application. Logically, I would like to organise all my client R source files in R/client/ and all my server R source files in R/server/.
Is it possible to organise code in subfolders when developing a package, and if so, how? The Writing R Extensions manual doesn't offer any guidance, nor does R CMD build detect files stored in subfolders under R/.
You can't use subfolders without additional setup (like defining a custom makefile). The best you can do is to use prefixes: client-a.r, client-b.r, server-a.r, server-b.r, etc.
Expanding the comment to Hadley's IMHO incorrect answer:
Look at the Matrix package (written by R Core members) which has five folders below src/, and two of these contain other subfolders. Other example is the Rsymphony packages (co-)written and maintained by an R Core member.
Doing this is not for the faint of heart. R strongly prefers a src/Makevars fragment over a full src/Makefile in order to be able to construct its own Makefile versions for the different subarchitectures. But if you know a little make and are willing to put the effort in, this is entirely doable -- and being done.
That still does not make it recommended though.
I argued with R core team Allow for sub-folders in "package/R/" directory . They seem not really want improve it. So my workflow is as follows.
1) Create an R project same as other packages but allow sub-directories in folder R/ such as
R/mcmc/a.R
R/mcmc/b.R
R/prediction/p1.R
R/predection/p2.R
2) When I need to pack them, I convert all files under R/ as
R/mcmc_a.R
R/mcmc_b.R
R/prediction_p1.R
R/predection_p2.R
...
with my package.flatten() function
3) Then I install the flattened version to R.
I wrote a simple script for Linux to do everything
https://github.com/feng-li/flutils/blob/master/inst/bin/install.HS
Recognizing the thread is a bit old, I just thought I'd throw in my solution to this problem. Note that my issue is similar, but I am only concerned with preserving folder hierarchies in development.
In development, I organize my script files in subfolders to my heart's content, but rather than fight R's flat hierarchy in production, I added my own "compile-time constant", so to speak.
That is, in every file located in a subfolder (not in top-level scripts/), I add the following:
if (!exists("script.debug"))
script.debug = FALSE
Then, I load whatever other dependencies are required as follows:
source.list <- c(
"script_1.R",
"script_2.R",
"script_3.R",
"script_4.R"
)
if (script.debug)
source.list <- paste("./script_subfolder/", source.list, sep="")
lapply(source.list, source)
The default assumption is that the code is in production, (source.debug = FALSE), so when in development, just ensure that source.debug = TRUE and the project's script/ folder is set as the working directory before loading any script files.
Of course, this example's a bit simple - it assumes that all script file dependencies exist in the same folder, but it seems a simple issue to devise a system that would suit more complicated development folder hierarchies.

A "clean"(er) bookdown install

The wonderful bookdown example drops all its bits and pieces into the project root directory (for an Rstudio project), and leaves a variety of files there. I know I can move the Rmd files to subfolders, and I know I can direct the output elsewhere, but there are still several .css files, .sh files (these look entirely optional) the (essential) _bookdown.yml file.
Ideally I'd want to "just" have a "report" folder in the project root, and leave the Rmd files, the outputs, and all the subsidiary files somewhere lower down in the folder structure within a project.
How far can I do in this pursuit? Recommendations? I'd welcome suggestions. Thanks,

address project root in Rstudio

When you open or create a project in RStudio, the working directory is automatically changed to that of the project. However, if you are saving files or doing work in other subdirectories, it's often convenient to change the working directory then. It can get to be a pain to manage this in every script.
Is there a variable that always points to the project root (that is also readable by the session forked by the "Knit HTML" button) that can be used to make this easier?
The "Knit HTML" button appears to set the working directory to that of the R Markdown file. For example, if you have a variable called project.root in your ./Rprofile, and you click "Knit HTML" with this script opened,
```{r}
getwd()
source('./Rprofile')
setwd(project.root)
getwd()
```
the first and last result will be the script directory and the rest will throw errors.
To recap, as you inferred, you can set R's working directory at the command line like so:
setwd("~/NateProjects")
You can also use RStudio's Files pane to navigate to a directory and then set it as working directory from the menu: Session --> Set Working Directory --> To Files Pane Location. (You'll see even more options there). Or within the Files pane, choose More and Set As Working Directory.
But, you can do better & set up an environment like a professional programmer. To do this, you can choose to keep all the files associated with a project (a project being loosely defined as I have all my personal code under one project) organized together -- input data, R scripts, analytical results, figures. In fact, RStudio has built-in support for this. There is an excellent tutorial here that you can have a look at which explains how to walk through in step by step detail:
http://www.rstudio.com/ide/docs/using/projects
Essentially, taking from the documents, you need to do the following:
Create a new project use the Create Project command (available on the Projects menu and on the global toolbar). This can be the place that you put all future sub projects and sub-folders in
Then, once you create this new project in RStudio, the following actions happen:
You create a project file (with an .Rproj extension) within the project directory. This file contains various project options (discussed below) and can also be used as a shortcut for opening the project directly from the filesystem.
You create a hidden directory (named .Rproj.user) where project-specific temporary files (e.g. auto-saved source documents, window-state, etc.) are stored. This directory is also automatically added to .Rbuildignore, .gitignore, etc. if required.
You load the project into RStudio and display its name in the Projects toolbar (which is located on the far right side of the main toolbar)

Code organisation in R package development

When developing packages in R all R source files are put in the subdirectory R/, and all compiled code is put in the subdirectory src/.
I would like to add some organisation to files within these folders, rather than have everything dumped at the top level. For example, lets say I'm hypothetically developing a client-server application. Logically, I would like to organise all my client R source files in R/client/ and all my server R source files in R/server/.
Is it possible to organise code in subfolders when developing a package, and if so, how? The Writing R Extensions manual doesn't offer any guidance, nor does R CMD build detect files stored in subfolders under R/.
You can't use subfolders without additional setup (like defining a custom makefile). The best you can do is to use prefixes: client-a.r, client-b.r, server-a.r, server-b.r, etc.
Expanding the comment to Hadley's IMHO incorrect answer:
Look at the Matrix package (written by R Core members) which has five folders below src/, and two of these contain other subfolders. Other example is the Rsymphony packages (co-)written and maintained by an R Core member.
Doing this is not for the faint of heart. R strongly prefers a src/Makevars fragment over a full src/Makefile in order to be able to construct its own Makefile versions for the different subarchitectures. But if you know a little make and are willing to put the effort in, this is entirely doable -- and being done.
That still does not make it recommended though.
I argued with R core team Allow for sub-folders in "package/R/" directory . They seem not really want improve it. So my workflow is as follows.
1) Create an R project same as other packages but allow sub-directories in folder R/ such as
R/mcmc/a.R
R/mcmc/b.R
R/prediction/p1.R
R/predection/p2.R
2) When I need to pack them, I convert all files under R/ as
R/mcmc_a.R
R/mcmc_b.R
R/prediction_p1.R
R/predection_p2.R
...
with my package.flatten() function
3) Then I install the flattened version to R.
I wrote a simple script for Linux to do everything
https://github.com/feng-li/flutils/blob/master/inst/bin/install.HS
Recognizing the thread is a bit old, I just thought I'd throw in my solution to this problem. Note that my issue is similar, but I am only concerned with preserving folder hierarchies in development.
In development, I organize my script files in subfolders to my heart's content, but rather than fight R's flat hierarchy in production, I added my own "compile-time constant", so to speak.
That is, in every file located in a subfolder (not in top-level scripts/), I add the following:
if (!exists("script.debug"))
script.debug = FALSE
Then, I load whatever other dependencies are required as follows:
source.list <- c(
"script_1.R",
"script_2.R",
"script_3.R",
"script_4.R"
)
if (script.debug)
source.list <- paste("./script_subfolder/", source.list, sep="")
lapply(source.list, source)
The default assumption is that the code is in production, (source.debug = FALSE), so when in development, just ensure that source.debug = TRUE and the project's script/ folder is set as the working directory before loading any script files.
Of course, this example's a bit simple - it assumes that all script file dependencies exist in the same folder, but it seems a simple issue to devise a system that would suit more complicated development folder hierarchies.

Opening a chm file containing merged files in a Qt application

In my Qt application we can open a help file (chm) by doing the following:
QDesktopServices::openUrl(QUrl::fromLocalFile(_PathToTheCHMFile));
This seems to be the suggested way of doing things. And it has worked up until now.
However, the documentation team has now changed how the chm files work. Now we are referencing a "master" file which only contains references to other chm files. The directory structure of the chm files is as follows:
master.chm
SUBDIR/
-> child1.chm
-> child2.chm
...
If open the master.chm file with hh.exe (the default tool in windows), everything looks perfect. However, from my Qt application, the help file opens, but there are no sub topics, just the root node.
I assume this is a search path issue, and it can't resolve the relative paths. There doesn't seem to be any way to configure the openURL call to run from a certain directory, or anything like that.
Thanks in advance
If you need to be able to access those elements properly, then you may need to change your applications current directory on the fly.
http://qt-project.org/doc/qt-4.8/qdir.html#details
http://qt-project.org/doc/qt-4.8/qdir.html#setCurrent
If that doesn't work, you may want to look into using QProcess::startDetached
http://qt-project.org/doc/qt-4.8/qprocess.html#startDetached
and specifying the working directory to be exactly where your master.chm is located.
You may want to specify some command-line arguments, too.
http://www.help-info.de/en/Help_Info_HTMLHelp/hh_command.htm
Hope that helps.

Resources