New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

knitr should interact better with `system` (R) #1203

Closed
MichaelChirico opened this Issue Apr 28, 2016 · 8 comments

Comments

Projects
None yet
2 participants
@MichaelChirico
Copy link
Contributor

MichaelChirico commented Apr 28, 2016

As highlighted by this question, we sort of have to jump through hoops to get the output from a system call to print its output to HTML.

Consider the following simple .Rmd file:


---
output: html_document

---

```{r test, echo = TRUE}
system("ls")
```

The output of which is simply:

system("ls")

We can force the output to show up by hiding things from viewers:


---
output: html_document

---

```{r test, echo = TRUE, eval = FALSE}
system("ls")
```
```{r test_eval, echo = FALSE, eval = TRUE}
cat(system("ls", intern = TRUE), collapse = "\n")
```

Which produces the output one would expect from simply running the first chunk.

But this seems like a sub-optimal solution and I think runs antithetical to the spirit of knitr.

I'm not 100% sure this is a knitr problem (as opposed to an rmarkdown problem); please advise if so.

@yihui

This comment has been minimized.

Copy link
Owner

yihui commented Apr 29, 2016

I'm aware of this issue but I don't know a good answer. I posted a question on SO http://stackoverflow.com/q/36928322/559676

@MichaelChirico

This comment has been minimized.

Copy link
Contributor Author

MichaelChirico commented Apr 29, 2016

Great! A strange issue indeed. Seems capture.output is not doing exactly what we think it is.

@MichaelChirico

This comment has been minimized.

Copy link
Contributor Author

MichaelChirico commented Apr 29, 2016

Could knitr perhaps overload system so that a call to system within a knitr chunk gets sent to knitr::system which is a wrap to the cat(system(..., intern = TRUE), collapse = "\n") approach?

My instincts tell me that's a terrible idea, but worth a suggestion.

@yihui

This comment has been minimized.

Copy link
Owner

yihui commented Apr 29, 2016

That is a natural thing to think about, but as you said, I'd not do it if we can find another way.

@MichaelChirico

This comment has been minimized.

Copy link
Contributor Author

MichaelChirico commented Apr 29, 2016

It's just so strange how system behaves. If we get an error code returned when intern = FALSE, why should it also print the output to the console (but apparently not to stdout)?

Hopefully there's a better way.

@yihui yihui added this to the v1.15 milestone Oct 7, 2016

@yihui

This comment has been minimized.

Copy link
Owner

yihui commented Oct 7, 2016

You can install the development version of evaluate via

devtools::install_github('hadley/evaluate')

Then you can use this hack:

evaluate::inject_funs(
  system = function(...) cat(base::system(..., intern = TRUE), sep = "\n")
)

and knitr will be able to capture the output of system(). Remember it is a hack. It basically replaced system in the global environment, so if you want the real system, you have to add the qualifier base::.

@MichaelChirico

This comment has been minimized.

Copy link
Contributor Author

MichaelChirico commented Oct 9, 2016

Neat trick. What's the benefit of using inject_funs over just writing system = function(...) cat(base::system(..., intern = TRUE), sep = "\n")?

@yihui

This comment has been minimized.

Copy link
Owner

yihui commented Oct 10, 2016

@MichaelChirico Well, no obvious advantages :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment