Rapporter / pander

An R Pandoc Writer: Convert arbitrary R objects into markdown
http://rapporter.github.io/pander/
Open Software License 3.0
294 stars 65 forks source link

Make it possible to hook into the output #248

Open jankatins opened 8 years ago

jankatins commented 8 years ago

Currently it is not possible to get the output and display it as markdown without either using a wrapper function or setting some knitr options to get a knit_asis object. Unfortunately, the asis object doesn't work in the context of the Jupyter R kernel, as it lacks information what kind of content is in the asis object (html, latex, md,...)

To make it possible to consume the output of teh pander call in both knitr and irkernel, I propose to change the API of the pander call to return a structure and then implement three methods to print the markdown as appropriate in the current context.

Prototype:

library(pander)
# to make it work in the jupyter notebook...
panderOptions('table.style', 'rmarkdown')
panderOptions("table.split.table", Inf)

# This would be the new pander(...) function
pander <- function(x = NULL, ...){
    t = capture.output(UseMethod('pander', x))
    structure(paste(t, collapse="\n"), class = 'pander_output')
}

# output in knitr
knit_print.pander_output <- function(x, ...) {
    if (isTRUE(panderOptions('knitr.auto.asis')){
       return(knitr::asis_output(as.character(x)))
   } else {
       cat(as.character(x))
   }
}

# output in the jupyter notebook
repr_markdown.pander_output <- function(x,...){
    as.character(x)
}

# output when in a console
print.pander_output <- function(x) {
    cat(as.character(x))
}
# ---
# in a notebook, this will result in a displayed markdown = html table
# in the console, it will display the markdown code
# in knitr, it will return a knit_asis object, which knitr then displays
pander_new(df)

As far as I understand it, the only downside is that x = paste(capture.output(pander(...)), collapse="\n") wont work afterwards anymore, as the call itself won't cat anything. All such calls would have to be changed to as.character(pander(...)) -> breaking API change :-(.

If this is acceptable, a question is how deep you want to change this: the easiest implementation would just use capture.output(), but this issue/PR could also be used to change the calls further down to use string concatenation and return a string instead of using cat directly.

If you agree with this proposal, I can do a PR...

[This original issue for this was https://github.com/IRkernel/repr/issues/33 // cc: @flying-sheep]

daroczig commented 8 years ago

Thanks for this proposal, which makes a lot of sense, but I will have to make sure that it doesn't break many things in the reverse dependencies -- as eg brew / Pandoc.brew / rapport requires stuff written to stdout without printing. Based on that, it's not as simple as described above -- so it might not happen within a few days. Anyway, it's a great idea and I will spend some time on these checks.

jankatins commented 8 years ago

Ok, I never considered that there more packages which do document conversations...

If this becomes a problem, this could be solved the same was as the multiline vs. rmarkdown switch in the options:

pander_return <- function(...){...new version...}
pander_cat <- function(...){..old version...}
in_kernel = isTRUE(getOption('knitr.in.progress'))
in_knitr = isTRUE(getOption('jupyter.in_kernel', FALSE))
pander <- if(in_kernel | in_knitr){pander_return} else{pander_cat}
daroczig commented 8 years ago

@JanSchulz can you please have a look at the above PR and test with Jupyter? I am not sure if you need a character vector or concatenated string.

If it seems to work, then I will add some docs on this behavior and merge.

jankatins commented 8 years ago

This doesn't work :-( We need to have something which differentiates it from a plain character vector, so that we can treat it differently from such a vector:

structure(paste(t, collapse="\n"), class = 'pander_output')
daroczig commented 8 years ago

@JanSchulz please check the updated PR based on that.

jankatins commented 8 years ago

See the pr...