15.6 cat エンジンでチャンクをファイルに書き出す

コードチャンクの内容を外部ファイルに書き出し, 以降の他のコードチャンクで使用するのは時には有用である可能性があります. もちろん, writeLines() のような R の関数で行っても良いですが, 内容が比較的長かったり, 特殊な文字が含まれていたり, writeLines() に渡したい文字列がごちゃごちゃしたりしているかもしれません. 以下は 長い文字列を my-file.txt に書き出す例です.

writeLines("これは長い文字列です.
複数行にわたります. ダブルクオート \"\"
忘れずにエスケープしてください. 
ですが 'シングルクオート' は大丈夫です.
バックスラッシュがいくつ必要か考えるときにあなたが
正気を失わないでいられることを願います.
例えば, '\t' なのか `\\t` なのか '\\\\t' なのか?",
  con = "my-file.txt")

R 4.0.0 以降では r"()" 内での生の文字列 (?Quotes のヘルプ参照) がサポートされ始めたので, 特殊文字のルールを全て覚える必要はなくなり, この問題は大いに緩和されました. 生の文字列があってもなお, チャンク内で長い文字列を明示的にファイルに書き出すことは読者の注意力を少しばかり削ぐ可能性があります.

knitrcat エンジンは, 例えばバックスラッシュのリテラルが必要な時は, 二重バックスラッシュが必要といった, R の文字列ルールを一切考えることなく, コードチャンクの内容の表示かつ/または外部ファイルへの書き出しの方法を提供してくれます.

チャンクの内容をファイルに書き出すには, チャンクオプション engine.opts にファイルパスを指定してください. 例えば engine.opts = list(file = 'path/to/file') のように. この内部では, engine.opts で指定された値のリストが base::cat() に渡されます. そして filebase::cat() の引数の1つです.

次に, cat エンジンの使い方の詳しい説明のため3つの例を提示します.

15.6.1 CSS ファイルへ書き込む

7.3節でお見せしたように, 要素を CSS でスタイル設定するために css コードチャンクを Rmd 文書に埋め込むことができます. 別の方法として, カスタム CSS ファイルを, html_document のようないくつかの R Markdown 出力フォーマットで有効な css オプションを介して Pandoc に渡す方法もあります. cat エンジンはこの CSS ファイルを Rmd から書き込むのに使用できます.

以下の例は文書のチャンクから custom.css ファイルを生成し, そのファイルパスを html_document フォーマットの ccs オプションに渡す方法を示しています.

---
title: "コードチャンクから CSS ファイルを作成する"
output:
  html_document:
    css: custom.css
---

以下のチャンクは `custom.css` へ書き込まれ, ファイルは
Pandoc の変換時に使われます.

```{cat, engine.opts = list(file = "my_custom.css")}
h2 {
  color: blue;
}
```

## そしてこの見出しは青くなります

css コードチャンクのアプローチとこのアプローチの唯一の違いは, 前者が CSS コードをその場に書き込む, つまりコードチャンクのあるまさにその場所に書き込み, そしてそこは出力文書の <body> タグの内側ですが, 後者は CSS を出力文書の <head> の領域に書き込みます. 出力文書の見た目に実用上の違いは一切生じません.

15.6.2 LaTeX コードをプリアンブルに含める

6.1節では, LaTeX コードをプリアンブルに追加する方法を紹介しました. これには 外部の .tex ファイルが必要でした. このファイルもまた Rmd から生成することができます. これがその例です.

---
title: "チャンクから .tex ファイルを作成する"
author: "Jane Doe"
documentclass: ltjsarticle
classoption: twoside
output: 
  pdf_document:
    latex_engine: lualatex
    includes:
      in_header: preamble.tex
---

# どのように動作するか

出力する PDF のヘッダとフッタを定義するために
コードチャンクを `preamble.tex` に書き出しましょう.

```{cat, engine.opts=list(file = 'preamble.tex')}
\usepackage{fancyhdr}
\usepackage{lipsum}
\pagestyle{fancy}
\fancyhead[CO,CE]{これは fancy header}
\fancyfoot[CO,CE]{そしてこれは fancy footer}
\fancyfoot[LE,RO]{\thepage}
\fancypagestyle{plain}{\pagestyle{fancy}}
```

\lipsum[1-15]

# さらに適当なコンテンツ

\lipsum[16-30]

上記の cat コードチャンク内の LaTeX コードで, PDF 文書のヘッダとフッタを定義しました. フッタに著者名も表示したいなら, 別の cat コードチャンクにオプション engine.opts = list(file = 'preamble.tex', append = TRUE)code = sprintf('\\fancyfoot[LO,RE]{%s}', rmarkdown::metadata$author) を付けることで preamble.tex に著者情報を追加することができます. このチャンクの動作を理解するには, この節の最初の方で紹介した engine.optsbase::cat() に渡されるということを思い出してください. つまり append = TRUEcat() に渡されます. そして チャンクオプション code はこの後の16.2節を読めば理解できるでしょう.

15.6.3 YAML データをファイルに書き込みつつ表示する

cat コードチャンクの中身はデフォルトでは出力文書に表示されません. 中身を書き出した後で表示もしたいならば,チャンクオプション class.source に言語名を指定してください. 言語名はシンタックスハイライトに使われます. 以下の例では, 言語名を yaml に指定しています.

```{cat, engine.opts=list(file='demo.yml'), class.source='yaml'}
a:
  aa: "something"
  bb: 1
b:
  aa: "something else"
  bb: 2
```

その出力を以下に表示し, そしてファイル demo.yml としても生成します.

a:
  aa: "something"
  bb: 1
b:
  aa: "something else"
  bb: 2

ファイル demo.yml が実際に生成されたことを示すには, yaml パッケージ (Stephens et al. 2022) で読み込んでみることができます.

xfun::tree(yaml::read_yaml("demo.yml"))
## List of 2
##  |-a:List of 2
##  |  |-aa: chr "something"
##  |  |-bb: int 1
##  |-b:List of 2
##     |-aa: chr "something else"
##     |-bb: int 2

参考文献

Stephens, Jeremy, Kirill Simonov, Yihui Xie, Zhuoer Dong, Hadley Wickham, Jeffrey Horner, reikoch, et al. 2022. Yaml: Methods to Convert r Data to YAML and Back. https://github.com/vubiostat/r-yaml/.