ramnathv / slidify

Generate reproducible html5 slides from R markdown
http://www.slidify.org
844 stars 339 forks source link

spacing between input R code and its output #189

Closed rcastelo closed 11 years ago

rcastelo commented 11 years ago

hi,

is it possible to control (reduce) the spacing between input R code and its output?

3 lines of R code within backquotes, such as:

1:10 1:10 1:10

occupy an entire slide when the R output is appended. I'd like slidify to use less space between intput R code and its output, also removing the border. I guess it must be embarrasingly simple, I've googled around and searched for issues here, but could not find anything related.

thanks!! robert.

ramnathv commented 11 years ago

The issue about removing the border can be solved by switching hitheme in your YAML front matter. Try hitheme: zenburn to get a brownish background or hitheme: github.

The space issue is related to knitr and not slidify. One workaround is to use hooks. Include the following commands in a chunk in your Rmd file. It defines two document hooks. Hook2 removes empty lines between input and output. Hook 1 is more aggressive and collapses successive chunks into a single chunk, thereby leading to a more compact slide. You can experiment with both and choose what you prefer.

hook1 <- function(x){ gsub("```\n*```r*\n*", "", x) }
hook2 <- function(x){ gsub("```\n+```\n", "", x) }
knit_hooks$set(document = hook2)
rcastelo commented 11 years ago

thanks!! this is what i was looking for. i'm a newbie with knitr/slidify and i could not tell whether this was a knitr or a slidify issue. collapsing code and output actually brings another such issues because i'd like disable code coloring in R output and color in gray all R output to make it more distinguishable from input, without using the leading comment '##' or prompt '>' which knitr allows one to set.

i'd say it looks initially to me as a knitr issue but i guess tuning the coloring should depend on whether output is latex or html5 and, in the latter, for the purpose of using slidify, i guess i would have to tweak with some custom CSS file in 'assets/css'. do you have some hint about how could i do this?

thanks again!

ramnathv commented 11 years ago

Slidify uses highlight.js to do syntax highlighting by default. You might be able to play with the stylesheets in libraries/highlighters/highlight.js/css to color output in gray. Alternately, you can force knitr to render code chunks and their output as HTML, in which case the output will be inside a div element with a specific class and it would be straightforward to force everything in the output class to be colored gray.

I will post more details on this when I find time.

rcastelo commented 11 years ago

i'm using github as hitheme so i guess i should be looking to libraries/highlighters/highlight.js/css/github.css. However, i cannot identify what part of this CSS defines the color for the output code. Any hint is welcome!

Regarding the knitr approach, is this a knitr exclusive approach or should this be synchronized somehow with what slidify does?

ramnathv commented 11 years ago

Here is one approach which might work. Try including the following knitr chunk in your knitr document. It adds a no-highlight class to the output, which results in highlightjs not syntax highlighting it. Now you can style it using css and render in the color of your choice (see code below. include it in a custom css file or use style tags if you are using inline).

I tested it and it works.

knit_hooks$set(output = function(x, options) {
  if (knitr:::output_asis(x, options)){
   return(x)
  } 
  stringr::str_c('\n\n```no-highlight\n', x, '```\n\n')
})
code.no-highlight {
  color: #ccc;
}
ramnathv commented 11 years ago

Feel free to reopen the issue if the problem remains unresolved at your end.

rcastelo commented 11 years ago

Thanks for the code snippet. Indeed it works perfectly under the default behavior of knitr that separates each chunk of input/output R code. However, going back to my initial issue about reducing the space between consecutive chunks of i/o R code, this approach will not work when collapsing code chunks. From my current understanding of knitr and slidify i'm afraid these two features, space reduction and avoid highlighting output code, might be impossible to obtain simultaneously, so any further suggestion for this is very welcome!

In Sweave I could achieve these two goals by putting:

\definecolor{Soutput}{rgb}{0.32,0.32,0.32}

and by the fact that Sweave would not put as much as space between different i/o R chunks. The look and feel I'm trying to achieve would be something along the lines of the following slides of mine I produced last year for a BioC lab at http://www.bioconductor.org/help/course-materials/2012/BioC2012/qpgraphWorkshop.pdf

In my view it does not make sense to try to highlight R output using R rules since the output of an R function does not have to conform to any kind of R syntax and for this reason I find the highlighting of output a bit disturbing, at least for slides.

ramnathv commented 11 years ago

Try adding the following CSS snippet to your Rmd file. A negative bottom margin for the pre blocks should squeeze space between input and output chunks. You may want to experiment with the value of the margin to suit your requirements. Let me know if this solves your issue.

<style>
pre {
  margin-bottom: -10px;
}
</style>
rcastelo commented 11 years ago

Thanks again for the hint. It solves the issue partially because I want the inner chunks of R code and their output to stick together but I want some margin with the text that may come before or after. Throughout this discussion I've come to understand better how the interplay between slidify and knitr works and I came up with the following solution which is a combination of all your suggestions, just in case is useful for anyone. I guess it can be improved in a number of ways.

  1. Have an initial setup code in the Rmd file:

    myenv <- new.env(parent=emptyenv())
    myenv$initChunk <- TRUE
    
    opts_chunk$set(comment=NA)
    
    knit_hooks$set(output = function(x, options) {
     if (knitr:::output_asis(x, options)){
       return(x)
     }
     stringr::str_c('\n\n```no-highlight\n', x, '```\n\n')
    })
    
    hook_chunk <- knit_hooks$get('chunk')
    knit_hooks$set(chunk = function(x, options) {
     myenv$initChunk <- TRUE
     hook_chunk(x, options)
    })
    
    hook_source <- knit_hooks$get('source')
    knit_hooks$set(source = function(x, options) {  
     if (get("initChunk", env=myenv)) {
       myenv$initChunk <- FALSE
     } else
       x <- paste("innerCode", x, sep="\n")
     hook_source(x, options)
    })
    
    knit_hooks$set(document=function(x) gsub("```r\ninnerCode", "```{r innerCode}", x))
  2. Have the following CSS code at file in assets/css/custom.css:

    code.r.innerCode {
     margin-top: -51px;
    }
    
    code.no-highlight {
     color: #828282;
     margin-top: -50px;
     line-height: 1em;
    }

Now if I type in my Rmd file something like:

These are different ways of generating a vector in R:

```{r}
c(1, 2, 3, 4, 5)
1:5
seq(1, 5, by=1)


It will put all R code and output together (i.e., without spacing between input R code and its output) and preserving the syntax highlighting for the input R code. Thanks again for all your help! I would not have made it so far!
ramnathv commented 11 years ago

Glad you could make this work. Your code can be made more concise. I will post an update on how to make it concise when I find time. But since this works, thats terrific.

rcastelo commented 11 years ago

I was thinking that since slidify tries to ease the production of slides with knitr and markdown and space within a slide is limited, it could be a good idea that the default look and feel of slidify would collapse the lines of code within a code chunk in some way similar to what we have come up with above.

ramnathv commented 11 years ago

That is a great suggestion! I will try to figure out the least intrusive way to make this happen, based on the code you have provided in your comment.

begavett commented 11 years ago

Similarly, relatively common R output, such as the summary of a linear model, does not fit on one slide. Is there an easy way to reduce the font of highlighted code in order to get the output to fit on the slide without spilling over the bottom margin? Thanks!

ramnathv commented 11 years ago

Add CSS.

pre {
  font-size: 11px;
}

This would reduce the font size for code on all slides. If you want to reduce it only on some slides, you could add the following css

slide.smallcode pre {
  font-size: 11px;
}

and in your slide, you can add

--- .smallcode

## Slide with Small Code

....
begavett commented 11 years ago

Excellent! Thank you!