LukasKawerau
LukasKawerau

Reputation: 1071

Parameterize non-executed code block in Rmd

I am working on a .Rmd document where we show people how to use the command line. This includes bash-based code blocks like this:

```{bash}
echo "this is a test"
```

However, we would like to parameterize this, so have something like

---
params:
    testparam: "this would echo something else"
---

```{bash}
echo params$testparam
```

This doesn't work, however, because inside a bash code block the parameters don't exist. Is there a way to use parameters in such cases, in essence evaluating params$testparam before knitr considers the fact that it's inside a non-R code block?

Ideally, the solution would make the following possible:

```{bash}
echo params$testparam
```

turns into

<pre class="bash"><code>echo "this would echo something else"</code></pre>
<pre><code>## this would echo something else</code></pre>

Upvotes: 2

Views: 163

Answers (2)

Anders Ellern Bilgrau
Anders Ellern Bilgrau

Reputation: 10253

The following .Rmd may suffice? I use the system() within a R block:

---
output: html_document
params:
    testparam: "this would echo something else"
---

# Header

Some text.

```{bash}
echo "this is a test"
```

Some more text.

```{r}
cat(system(paste0("echo '", params$testparam, "'"), intern = TRUE), sep = "\n")
```

enter image description here

Strong inspiration from here. Of course, the bash command is not readily visible, but I suspect one can work around that.

EDIT:

With a bit of a work-around/hack, you can render the bash code in the following manner:

```{r bashCode, results="asis", echo=FALSE}
bash_code <- sprintf("echo '%s'", params$testparam)
cat("<pre class='bash'><code>",
    bash_code,
    "</code></pre>")
```

```{r bashOutput, echo=FALSE}
cat(system(bash_code, intern = TRUE), sep = "\n")
```

enter image description here

So we generate the bash code as a character and cat the bash code wrapped in appropriate html while telling knitr to interpret the result 'asis' (making the results appear as code). As we also suppress the R code itself (echo=FALSE), the results appear as code only. Next, in the subsequent chunk, we again suppress the printing of the code but get the output of the system command which is interpreted in the standard manner.

You can of course utilize the trick from @r2evans together with this as well.

Upvotes: 1

r2evans
r2evans

Reputation: 160952

As I hoped, this small hack works:

---
params:
    testparam: "this would echo something else"
---

```{r, echo = FALSE, include = FALSE}
if (length(params) > 0) do.call(Sys.setenv, params)
```

```{bash}
echo $testparam
```

Yielding

<pre class="bash"><code>echo $testparam</code></pre>
<pre><code>## this would echo something else</code></pre>

This will fail if you pass non-simple objects. I haven't tested vectors/lists/frames, though I suspect they will fail spectacularly ... but since you're using bash in that chunk, I'm assuming its parameters are less-complex.

If you have some params that are complex but never to be used in your bash chunks, you might consider a naming convention, something like:

---
params:
    bashtestparam: "this would be one thing"
    testparam: "this would echo something else"
---

```{r, echo = FALSE, include = FALSE}
p <- params[ grepl("^bash", names(params)) ]
names(p) <- gsub("^bash", "", names(p))
if (length(p) > 0) do.call(Sys.setenv, p)
```

```{bash}
echo $testparam
```

which yields

<pre class="bash"><code>echo $testparam</code></pre>
<pre><code>## this would be one thing</code></pre>

Upvotes: 2

Related Questions