I'm looking for ways to add variables (or LaTeX macros) to the YAML header or soon after such that they can be used in external .tex
files that are a part of my (modularised) report.
My .rmd
file
---
output:
pdf_document:
latex_engine: xelatex
includes:
before_body: some.tex
params:
cat: "Felix"
numb: 14
---
# chapter
Oh my \textbf{`r params$cat`}.
$x = `r 2*params$numb`^2$
<!-- Trying again to get the parameter -->
\input{some.tex}
My some.tex
file:
`r params\$cat`
Output
Hoped-for output
I want to be able to somehow pass the variables from the YAML header (or even just below it) to be used by LaTeX so that all important and regularly updated parameters can be viewed and changed in one place.
If you are looking for something which perhaps is most in keeping with the R Markdown workflow, you can customise the template which is used to build the LaTeX output and add all the extra LaTeX code directly to this.
1. Copying Template
Firstly, we must make a copy of the template used by R Markdown. The following code will create this in your current working directory:
file.copy(system.file("rmd/latex/default-1.17.0.2.tex",
package = "rmarkdown"), "template.tex")
2. Adding Variables
With our copy, we can define our own pandoc variables which will be inserted into the output document. This allows us to specify parameters in the YAML section of the document and they will be updated in the output format. It is exactly the same mechanism which allows us to add title
, author
, date
and for them to be added to the output format.
I have added some code to the front matter of the document at lines 253-255. The exact location doesn't matter, but I also tend to put my customisations before the \begin{document}
argument:
\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhead[LO, LE]{$params.value$}
\fancyhead[RO, RE]{$yourParam$}
3. Calling Template from R Markdown
We can reference the custom template to our R Markdown document as explained here. Here is my minimal example:
---
output:
pdf_document:
template: template.tex
params:
value: Text
yourParam: "`r Sys.Date()`"
---
`r params$value`
The two parameters will be added to the output replacing the $params.value$
and $yourParam$
, and result in the output below:
The example highlights how the YAML parameters don't have to be nested within the params
argument, as specified in your original question. Having them specified within the parameters mainly has benefits if you want to build a parameterized report
Note: the approach of replacing variables using the pandoc notation
$variable$
is only possible for the main template file defined under thetemplate
option. It won't work for any of theincludes
arguments or any other external LaTeX files. See here for more details.
This comes only half-way. Still no file as header-input...
Maybe this answer will give someone else an idea to build on..
---
output:
pdf_document:
latex_engine: xelatex
params:
cat: "Felix"
numb: 14
header-includes:
- \usepackage{fancyhdr}
- \pagestyle{fancy}
- \fancyhead[CO,CE]{`r params$cat`}
---
# CHAPTER 1
Oh my \textbf{`r params$cat`}.
$x = `r 2*params$numb`^2$
```{r child = 'some.tex'}
```
screenshot pdf
I'm sure you can code something together using lua-filters.
First come up with your own include-mechanism (since this needs to happen before variable-substitution, so you cannot use latex's \input
), but e.g. this filter:
function Para (elem)
if #elem.content == 1 and elem.content[1].t == "Image" then
local img = elem.content[1]
if img.classes[1] == "markdown" then
local f = io.open(img.src, 'r')
local blocks = pandoc.read(f:read('*a')).blocks
f:close()
return blocks
end
end
end
Then do the variable substitution with e.g. this filter:
local vars = {}
function get_vars (meta)
for k, v in pairs(meta) do
if v.t == 'MetaInlines' then
vars["$" .. k .. "$"] = {table.unpack(v)}
end
end
end
function replace (el)
if vars[el.text] then
return pandoc.Span(vars[el.text])
else
return el
end
end
return {{Meta = get_vars}, {Str = replace}}
This should then work like:
---
output:
pdf_document:
latex_engine: xelatex
pandoc_args:
- '--lua-filter=include.lua'
- '--lua-filter=substitution.lua'
name: Samuel
---
Look, I can include files:
![](include.md){.markdown}
And in include.md
:
Look, I can use variables: \$name\$
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With