Search code examples
r-exams

How to have parameters in the LaTeX template?


I have a LaTeX template, which I use with exam2pdf and where I would like to have the date of the exam as a parameter, whose value should be passed from R. Is that possible?


Solution

  • Yes, you can do this in two and a half ways:

    (1) Via the header argument

    You can set exams2pdf(..., header = ..., template = ...) where the content of the header is inserted into the template by replacing the %% \exinput{header} placeholder. Thus, when writing the template you can decide where exactly the header code ends up in the LaTeX code and you can make sure that the appropriate commands/packages are available. The header can then be specified in the following ways:

    • LaTeX code: You can include something like header = "\\command{value}". There could be more complex pieces of LaTeX code, involving multiple lines, etc.
    • List of commands and values: Instead of the full LaTeX code it might be more R-like to use a list specification like header = list(command = "value"). This is transformed internally to the LaTeX code mentioned above.
    • List of functions: Finally you can also have a specification like header = list(command = valuefun) where valuefun is a function(i) so that you return a different string for the i-th random version of the exam.
    • List of all of the above: A list consisting of unnamed character strings, named character string, and named functions can be used as well, combining all three specifications above.

    More details are provided in the vignette("exams", package = "exams") which explains the design of exams2pdf() and how it can be leveraged. It also includes some examples which you can also copy to your working directory via exams_skeleton(write = "exams2pdf", ...). You can look at the exam.tex LaTeX template that is shipped with the package to see how you can insert a date and an ID (depending on the i-th iteration) into the PDF. For example:

    exams2pdf("capitals.Rmd", template = "exam.tex",
      header = list(Date = "2022-02-22", ID = function(i) paste("\\#", i)))
    

    (2) Write a template generator

    For the purposes from your question strategy (1) should be sufficient, I guess. However, if you need more control over what is done in the LaTeX template, then my recommendation would be to write a dynamic template generator. This is how exams2nops() is set up. It takes a lot of arguments that can be set by the user and then proceeds as follows:

    • Depending on the user arguments a corresponding nops.tex template is written in a temporary directory.
    • Then exams2pdf(..., template = "/path/to/nops.tex") is called to use this custom temporary template.
    • Some details, especially the counter for the i-th ID is still handled through the header argument.