remake icon indicating copy to clipboard operation
remake copied to clipboard

Auto detect file dependencies in latex or knitr docs

Open dfalster opened this issue 9 years ago • 3 comments

I use remake a lot, including to run knitr reports or compile latex documents. Often these documents require an external file, e.g. a figure. Currently, this requires that we list filenames twice, once in remake, and again within the knitr or latex document. That's entirely workable, but it does often happen that errors arise from forgetting to update names in two places.

An ideal situation would be if remake built a list of file dependencies from examining the document.

I know, this is asking a lot!

dfalster avatar Oct 20 '16 00:10 dfalster

Alternatively, could we somehow ask remake to depend on everything in a certain directory? So if any file in that directory is added or changed, it triggers a rebuild? That would save listing every file twice.

dfalster avatar Oct 20 '16 00:10 dfalster

I'm using the following helper:

knit_with_deps <- function(target_name, source_name, ..., envir = parent.frame()) {
  dir.create(dirname(target_name), recursive = TRUE, showWarnings = FALSE)

  dep_names <- as.character(unlist(substitute(list(...))[-1]))
  deps <- list(...)
  names(deps) <- dep_names
  deps <- deps[unique(names(deps))]

  dep_env <- as.environment(deps)

  parent.env(dep_env) <- envir

  rmarkdown::render(input = source_name, output_file = basename(target_name), envir = dep_env)
}

remake.yml usage:

  report.html:
    command: knit_with_deps(target_name,
      "report.Rmd", dep1, dep2, dep3, ...)

You could use this and then pass your .bib file as dependency:

  report.html:
    command: knit_with_deps(target_name,
      "report.Rmd", bib_file = "my.bib")

In the .Rmd:

---
bibliography: `r bib_file`
---

Not tested, but might work actually ;-)

krlmlr avatar Nov 23 '16 13:11 krlmlr

Thanks @krlmlr for the suggestion. I can see that could help with knitting Rmd files, less so with rendering latex. In anycase, for Rmd is your proposed solution different to doing something like:

  report.md:
    knitr:
      input: report.Rmd
    depends:
      - dep1
      - dep2
  report.html:
    command: render(report.md, I("html_document"), quiet=TRUE)

dfalster avatar Dec 01 '16 22:12 dfalster