1

I try to learn knitr.

knitr lets you nest snippets of "inline-code" written in the language R between \Sexpr{...}.

knitr lets you nest "code-chunks" written in the language R between

<< >>=
[chunk of R-code goes here]
@

. knitr does pre-process the input-file. Hereby all snippets of inline-code and all code-chunks are processed by the language R.
In what is fed to (La)TeX the snippets of inline-code and the code-chunks are replaced by the result of this processing.

I try to write an R-function which does a system-call, e.g., echo some phrase and captures the standard-output and delivers into the .tex-file created by knitr.

By now I have an R-function for doing this within R-code-chunks and another function for doing this within R-\Sexpr-inline-code-snippets.

The function to be used within R-code-chunks does not work out within R-\Sexpr-inline-code-snippets.

The function to be used within R-\Sexpr-inline-code-snippets does not work out within R-code-chunks.

The question is:

What should an R-function for knitr look like which works out both within R-\Sexpr-inline-code-snippets and within R-code-chunks?

Here is the file test.Rtex I have so far:

<<CallExternalFunctionsStuff, include=FALSE, cache=FALSE, echo=FALSE, results='asis'>>=
knitr::opts_template$set(
  CallExternalApp = list(include=TRUE, cache=FALSE, echo=FALSE, results='asis')
)
CallExternalAppInChunk <- function(A) {
  return(cat(paste(system(A, intern = TRUE),collapse="\n")))
}
CallExternalAppInSexpr <- function(A) {
  return(paste(capture.output(cat(system(A, intern = TRUE), sep="\n", fill=FALSE)), collapse="\n"))
}
@
\documentclass{article}

\begin{document}

\noindent Between ZZZ is what \verb|verbatim| does usually:\bigskip

ZZZZ
\begin{verbatim}
hello1
hello2
\end{verbatim}ZZZZ

\bigskip

\noindent \verb|CallExternalAppInChunk| works inside an R-code-chunk:\bigskip

ZZZZ
\begin{verbatim}
<<opts.label='CallExternalApp'>>= 
CallExternalAppInChunk("echo hello1&&echo hello2")
@
\end{verbatim}ZZZZ

\bigskip

\noindent \verb|CallExternalAppInSexpr| works inside knitR's \verb|\Sexpr|:\bigskip

ZZZZ
\begin{verbatim}
\Sexpr{CallExternalAppInSexpr("echo hello1&&echo hello2")}
\end{verbatim}ZZZZ

\bigskip

\noindent \verb|CallExternalAppInSexpr| does not work inside an R-code-chunk:\bigskip

ZZZZ
\begin{verbatim}
<<opts.label='CallExternalApp'>>= 
CallExternalAppInSexpr("echo hello1&&echo hello2")
@
\end{verbatim}ZZZZ

\bigskip

\noindent \verb|CallExternalAppInChunk| does not work inside knitR's \verb|\Sexpr|:\bigskip

ZZZZ
\begin{verbatim}
\Sexpr{CallExternalAppInChunk("echo hello1&&echo hello2")}
\end{verbatim}ZZZZ

\end{document}

Here is the output this produces

enter image description here

1 Answer 1

2

A short answer is that you return the character string but mark it with xfun::raw_string(), e.g.,

CallExternalApp <- function(A) {
  xfun::raw_string(paste(system(A, intern = TRUE), collapse = "\n"))
}

Under the hood, xfun::raw_string() will let R's print() function print a string with cat(), which makes it work in a code chunk, and also return the string itself (with a new class), which makes it work in an inline expression in \Sexpr{}.

In a code chunk, R objects are automatically printed (this is a subtle feature of R). In an inline R expression, knitr obtains its returned value and writes it out unless the value is marked as invisible().

Why doesn't CallExternalAppInChunk() work in \Sexpr{}? Because it doesn't return the character value, but returns what cat() returns (i.e., an invisible NULL).

Why doesn't CallExternalAppInSexpr() work in a code chunk? Because it returns a normal character string, and knitr will print it in the way that a character string is printed in a normal R console (i.e., with indices like [1] and double quotes).

2
  • 1
    When using CallExternalApp within a code chunk nested within a verbatim-environment, the verbatim-environment in the .tex-file produced by knitr contains an additional trailing empty line. This trailing empty file yields visible vertical space in the .pdf-file. I don't have this additional trailing empty line when in the code chunk using CallExternalAppInChunk. Please forgive me for lacking the experience in dealing with R to be able to track all this. May 25, 2022 at 9:50
  • 1
    One way to avoid the extra empty line is remove both the verbatim environment and the chunk option results='asis' and then add the chunk option comment=''. Then knitr will generate the verbatim environment for you. But I guess you won't like the default shaded environment. If that's the case, you can set the background to white via the chunk option background='white'. (No worries about your experience with R; I'm happy to help!)
    – Yihui Xie
    May 25, 2022 at 22:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .