Доступ к параметрам YAML как макросам во внешних файлах LaTeX - PullRequest
0 голосов
/ 08 октября 2018

Я ищу способы добавления переменных (или макросов LaTeX) в заголовок YAML или вскоре после этого, чтобы их можно было использовать во внешних .tex файлах, которые являются частью моего (модульного) отчета.

Мой .rmd файл

---
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}

Мой some.tex файл:

`r params\$cat`

Выход

enter image description here

Hoped-for output

Я хочу иметь возможность каким-то образом передавать переменные изЗаголовок YAML (или даже чуть ниже), который будет использоваться LaTeX, чтобы все важные и регулярно обновляемые параметры можно было просматривать и изменять в одном месте.

Ответы [ 5 ]

0 голосов
/ 15 октября 2018

Позвольте мне перефразировать вопрос: цель состоит в том, чтобы написать параметризованный отчет.В этом отчете для встраивания файла TEX используется \input (например, some.tex).Вы ищете способ доступа к параметрам YAML в some.tex.

Один из способов сделать это - определить макросы LaTeX в соответствии с параметрами YAML, например, параметр YAML cat: "Felix" становится \newcommand{\cat}{Felix}.Эти макросы TEX могут затем использоваться по всему документу.(В основном файле r params$cat также будет работать, но поскольку some.tex не связан, здесь работает только \cat.)

Во-первых, оценивается код R.Он считывает все параметры YAML и записывает соответствующие макросы в myparams.tex. 1 Через header-includes сгенерированный файл myparams.tex включается в промежуточный файл TEX, который в итоге компилируется в PDF.

Основной файл RMD :

---
output: pdf_document
header-includes: "\\input{myparams.tex}"
params:
  cat: "Felix"
  numb: 14
---

```{r, include = FALSE}
if (file.exists("myparams.tex")) {
  file.remove("myparams.tex") # CAUTION: this will DELETE any existing file "myparams.tex"
}
for (param in names(params)) {
  cat(sprintf("\\newcommand{\\%s}{%s}\n", param, params[param]), file = "myparams.tex", append = TRUE)
}
```

Oh my \cat. 
$x = 2 \cdot \numb^2$

Or alternatively: Oh my `r params$cat`. 

\input{some.tex}

some.tex:

Oh my \cat. % Here, `r params$cat` won't work.

Вывод :

О, мой Феликс.x = 2 · 14²

Или, альтернативно: О, мой Феликс.

О, мой Феликс, снова.

Содержимое myparams.tex (динамическисгенерировано):

\newcommand{\cat}{Felix}
\newcommand{\numb}{14}

1 Возможно, было бы неплохо использовать уникальный префикс для всех новых макросов LaTeX, чтобы избежать конфликтов между встроенными командами LaTeX и параметрами YAMLс тем же именем.

0 голосов
/ 12 октября 2018

Если вы ищете что-то, что, возможно, наиболее соответствует рабочему процессу R Markdown, вы можете настроить шаблон, который используется для создания вывода LaTeX, и добавить весь дополнительный код LaTeX непосредственно к этому.

1.Копирование шаблона

Во-первых, мы должны сделать копию шаблона , используемого R Markdown .Следующий код создаст это в вашем текущем рабочем каталоге:

file.copy(system.file("rmd/latex/default-1.17.0.2.tex",
          package = "rmarkdown"), "template.tex")

2.Добавление переменных

С нашей копией мы можем определить наши собственные переменные pandoc , которые будут вставлены в выходной документ.Это позволяет нам указать параметры в разделе YAML документа, и они будут обновлены в выходном формате.Это точно такой же механизм, который позволяет нам добавлять title, author, date и добавлять их в выходной формат.

Я добавил некоторый код в начало статьидокумент в строки 253-255 .Точное местоположение не имеет значения, но я также склоняюсь к настройке перед аргументом \begin{document}:

\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhead[LO, LE]{$params.value$}
\fancyhead[RO, RE]{$yourParam$}

3.Вызов шаблона из R Markdown

Мы можем ссылаться на пользовательский шаблон в нашем документе R Markdown , как описано здесь .Вот мой минимальный пример:

---
output:
  pdf_document:
    template: template.tex
params:
  value: Text
yourParam: "`r Sys.Date()`"
---

`r params$value`

Два параметра будут добавлены к выходу, заменив $params.value$ и $yourParam$, и приведем к выводу ниже:

enter image description here

В этом примере показано, как необязательно вкладывать параметры YAML в аргумент params, как указано в исходном вопросе.Их указание в параметрах в основном имеет преимущества, если вы хотите создать параметризованный отчет

Примечание: подход замены переменных с использованием нотации pandoc $variable$ возможно только для основного файла шаблона, определенного в опции template.Он не будет работать ни с одним из аргументов includes или с любыми другими внешними файлами LaTeX.См. здесь для более подробной информации.

0 голосов
/ 11 октября 2018

Это идет только наполовину.По-прежнему нет файла для ввода заголовка ...

Возможно, этот ответ даст кому-то еще идею для построения ..

---
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'}
```

снимок экрана pdf

enter image description here

0 голосов
/ 11 октября 2018

Вы можете создать макрос TeX или LaTeX в заголовке YAML и использовать его в своем файле some.tex.

Например, поместите его в основной файл:

---
output:
  pdf_document:
    latex_engine: xelatex
      includes:
        before_body: some.tex
header-includes:
- \def\thecat{`r params$cat`}
params:
  cat: "Felix"
  numb: 14
---


# chapter
Oh my \textbf{`r params$cat`}. 
$x = `r 2*params$numb`^2$

\input{some.tex}

и поместите это в some.tex:

\thecat

, и все будет отображаться так, как вы хотите.

enter image description here

0 голосов
/ 11 октября 2018

Я уверен, что вы можете что-то кодировать вместе, используя lua-фильтры.

Сначала придумайте свой собственный механизм включения (так как это должно произойти до замены переменных, поэтому вы не можете использовать латекс * 1003).*), но, например, этот фильтр :

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

Затем выполните подстановку переменной, например, этот фильтр :

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}}

Это должнотогда работай как:

---
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}

И в include.md:

Look, I can use variables: \$name\$
...