Conditional highlighting of output - r-markdown

I suppose I'm missing something obvious here, but I've been stumped for a while on this. I have my .Rmd file setup, and almost everything knits fine to Markdown_strict and latex_fragment (with a little preprocessing on that one), but nevermind for now.
Here's a sample.Rmd file that I have as input. I couldn't figure how to nest backticks, so for now it's pseudo-escaped.
---
title: "Sample"
output:
md_document:
preserve_yaml: yes
variant: markdown_strict+raw_html+all_symbols_escapable
latex_fragment: default
knit: (function(inputFile, encoding) {
rmarkdown::render(inputFile, encoding = encoding,
output_dir = ".", output_format = "all") })
---
\`\`\`{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
sqlcode <- function(sql, code = "") {
if (knitr::is_latex_output()) {
return(paste0('\n```{=sql}\n',sql,'\n```\n'))
} else if (!knitr::is_html_output(excludes = "markdown")) {
if (length(code)>0) {
code = paste0(" ", code," ")
} else {
code = " "
}
pre <- paste0("{{< sql",code,">}}\n")
post <- "\n{{< /sql >}}"
return(knitr::raw_html(paste0(pre,sql,post)))
}
}
\`\`\`
This is a sample.
\`\`\`{r echo=FALSE}
sqlcode("SELECT *
FROM TABLE", "sample")
\`\`\`
The LaTeX fragment I want is:
This is a sample.
\begin{Shaded}
\begin{Highlighting}[]
\KeywordTok{SELECT} \OperatorTok{*}
\KeywordTok{FROM}\NormalTok{ TABLE}
\end{Highlighting}
\end{Shaded}
What I get is:
This is a sample.
\begin{verbatim}
## [1] "\n```{=sql}\nSELECT *\nFROM TABLE\n```\n"
\end{verbatim}
And on the MD side, I do get what I want, that is:
---
title: "Sample"
output:
md_document:
preserve_yaml: yes
variant: markdown_strict+raw_html+all_symbols_escapable
latex_fragment: default
knit: (function(inputFile, encoding) {
rmarkdown::render(inputFile, encoding = encoding,
output_dir = ".", output_format = "all") })
---
This is a sample.
{{< sql sample >}}
SELECT *
FROM TABLE
{{< /sql >}}
For those familiar with Hugo, these are custom shortcodes I use for a Hugo-generated site. The lack of ident of the SQL code is on purpose, it's then highlighted through hugo.
At any rate, how do I get sqlcode(...) to output a fenced block that pandoc will correctly highlight in LaTeX, or alternatively, what part of pdf_document.R should I customize in order to achieve that ?
I've tried various knitr functions that mark output and I can get an intermediary MD file that I could process to remove some markers, but I can't manage to process that intermediary MD file before knitr sends it to Pandoc.

After a while of trial and error I figured it out. It's as simple as changing one line -_-
sqlcode <- function(sql, code = "") {
if (knitr::is_latex_output()) {
knitr::raw_output(paste0('\n```sql\n',sql,'\n```\n'), markers=NULL)
} else if (!knitr::is_html_output(excludes = "markdown")) {
if (length(code)>0) {
code = paste0(" ", code," ")
} else {
code = " "
}
pre <- paste0("{{< sql",code,">}}\n")
post <- "\n{{< /sql >}}"
return(knitr::raw_html(paste0(pre,sql,post)))
}
}

Related

How to preview mermaid graph in RStudio viewer?

Background:
It's possible to "use of an external text file with the .mmd file extension can provide the advantage of syntax coloring and previewing in the RStudio Viewer" (DiagrammeR Docs)
What should look like this:
Problem:
In my minimal working example the graph is not rendered in the viewer panel but the plain text from the mermaid.mmd-file is printed (see below). How to fix this behavior, so that the chart is rendered?
mermaid.mmd:
graph LR
A-->B
Output in viewer panel:
The text inside the mermaid.mmd-file is printed in the viewer panel, but not the rendered graph
My Setup
RStudio 2022.07.2 (<- newest version)
R version 4.2.1 (2022-06-23 ucrt)
DiagrammerR version 1.0.9 (<- newest version)
knitr version 1.40 (<- newest version)
Technical Reason for the Problem
I found the problem. It's the implementation of the handling of extern .mmd-files in the DigrammeR::mermaid()-function.
Within the mermaid()-function the htmlwidgets::createWidget(name = "DiagrammeR", x = x, width = NULL, height = NULL, package = "DiagrammeR")-functions takes the processed input x and renders the graph. This functions expects an input in the format "\ngraph LR\nA-->B\n", where every input start and ends with "\n" and each line in your mermaid-code is also separated by "\n". But the input from an extern .mmd-file (readLines("mermaid.mmd", encoding = "UTF-8", warn = FALSE)) looks like this:
"graph LR" "A-->B" (separated strings for each line of mermaid-code)
Transforming the input into the required format can be done by mermaid.code <- paste0("\n",paste0(mermaid.code, collapse = "\n"),"\n")
Unfortunately this processing step is not implemented for extern .mmd-files in DigrammeR::mermaid()
Soultion
Build a new mermaid()-function, including the required processing step
Replace the mermaid()-function within the DiagrammeR-packages by the new function
# Build new mermaid()-function
mermaid.new = function (diagram = "", ..., width = NULL, height = NULL) {
is_connection_or_file <- inherits(diagram[1], "connection") ||
file.exists(diagram[1])
if (is_connection_or_file) {
diagram <- readLines(diagram, encoding = "UTF-8", warn = FALSE)
diagram <- paste0("\n",paste0(d, collapse = "\n"),"\n") # NEW LINE
}
else {
if (length(diagram) > 1) {
nosep <- grep("[;\n]", diagram)
if (length(nosep) < length(diagram)) {
diagram[-nosep] <- sapply(diagram[-nosep], function(c) {
paste0(c, ";")
})
}
diagram = paste0(diagram, collapse = "")
}
}
x <- list(diagram = diagram)
htmlwidgets::createWidget(name = "DiagrammeR", x = x, width = width,
height = height, package = "DiagrammeR")
}
#Replace mermaid()-function in DiagrammeR-package
if(!require("R.utils")) install.packages("R.utils")
library(R.utils)
reassignInPackage(name="mermaid", pkgName="DiagrammeR", mermaid.new, keepOld=FALSE)
# Test new function
DiagrammeR::mermaid("mer.mmd")
You can preview your codes as simple as running them like this:
library(DiagrammeR)
DiagrammeR(
"
**graph LR
A-->B**
")
You should be able to see
this

How I can zoom-in for a sankey plot in R-shiny?

I have been trying to create a R shiny dashboard including a sankey network. It is working without any problem, however some of the plots seem quite clutter due to high number of nodes and connections based on some input parameters. As an alternative solution, i am trying to implement zooming feature triggered by double click by the user, but I am getting an error of "unused element" by shiny.
The part of the ui code including double click is:
sankeyNetworkOutput("diagram",dblclick = "plot1_dblclick",
brush = brushOpts(id = "plot1_brush",resetOnNew = TRUE)
The server side code is:
output$diagram<- renderSankeyNetwork({
sankeyNetwork(Links = rv1()$links, Nodes = rv1()$nodes,
Source = "IDsource", Target = "IDtarget",
Value = "value", NodeID = "name",
iterations = 0, sinksRight=TRUE,
fontSize=13, nodePadding=20)
observeEvent(input$plot1_dblclick, {
brush <- input$plot1_brush
if (!is.null(brush)) {
ranges$x <- c(brush$xmin, brush$xmax)
ranges$y <- c(brush$ymin, brush$ymax)
} else {
ranges$x <- NULL
ranges$y <- NULL
}
})
})
I would really appreciate if I can get any help regarding to that!
Thanks!

Shiny: Display textOutput() if input is different from the default value

I have a Shiny App with multiple inputs of different kinds (checkboxGroupInput, sliderInput, dateRangeInput ...) with default selected values.
I am trying to display a text message at the top of my dashboardBody if the input values are different from the default ones.
ui <- dashboardPage(
#one of the inputs
dateRangeInput(
"date_reception",
"Sélectionnez une plage de dates",
start = min(dataset_all$date_reception),
end = max(dataset_all$date_reception),
),
#the output to show if input is different from default
textOutput("warning_filters")
----------
)
server <- function(input, output) {
observeEvent(input$date_reception,
{
if ((input$date_reception[1] != min(dataset_all$date_reception)) |
(input$date_reception[2] != max(dataset_all$date_reception))) {
output$warning_filters <-
renderText({
"Warning: filters apply"
})
} else{
NULL
}
})
}
My issue is that the message is correctly displayed when I change one of the dates but does not disappear when I select again the default value (here, min(dataset_all$date_reception) or max(dataset_all$date_reception)).
I have tried playing with ignoreNULL and ignoreInit but nothing changed.
Thank you for your help!
You need to re-assign warning_filters when the condition is false. Now, the warning_filters gets set to the warning text and even though you have the function return NULL when the condition doesn't hold, you don't actually change the values of warning_filters. The code below should work.
observeEvent(input$date_reception,
{
if ((input$date_reception[1] != min(dataset_all$date_reception)) |
(input$date_reception[2] != max(dataset_all$date_reception))) {
output$warning_filters <-
renderText({
"Warning: filters apply"
})
} else{
output$warning_filters <- NULL
}
})
}

How to make sublime text 3's 'SublimeOnSaveBuild' package not compile the file named beginning with '_' prefix

How to make sublime text 3's SublimeOnSaveBuild package not compile the file named beginning with _ prefix?
For Example. I want a.scss or a_b.scss files can be complied when I saving this files. But not include the files such as named _a.scss.
I saw the guide in github is to set the filename_filter configuring.
So I create a SublimeOnSaveBuild.sublime-settings.Contents:
{
"filename_filter": "/^([^_])\\w*.(sass|less|scss)$/"
}
I used two \ , because it seems would saved as a .sublime-settings file which format likes JSON.
But it doesn't work.I use JavaScript to test it, it works well !
let reg = /^[^\_]\w*.(sass|less|scss)$/,
arr = [
'a.scss',
'_a.scss',
'a_b.scss'
];
arr.forEach(function( filename ) {
console.log( filename + '\t' + reg.test(filename) );
});
// a.scss true
// _a.scss false
// a_b.scss true
Thanks!
I found a solution in joshuawinn. But I can't understand why my codes can't work...
{
"filename_filter": "(/|\\\\|^)(?!_)(\\w+)\\.(css|js|sass|less|scss)$",
"build_on_save": 1
}
Sorry for my poor English !
let reg = /^(_|)\w*.(sass|less|scss)$/,
arr = [
'a.scss',
'_a.scss',
'a_b.scss'
];
arr.forEach(function( filename ) {
console.log( filename + '\t' + reg.test(filename) );
});

How to create and display an animated GIF in Shiny?

I'm able to load a saved file as an image but unable to use gganimate to do it directly. Alternate ways of rendering GIFs would be nice to know but knowing how to render gganimate specifically would really solve my problem.
library(gapminder)
library(ggplot2)
library(shiny)
library(gganimate)
theme_set(theme_bw())
ui <- basicPage(
plotOutput("plot1")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
p = ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop, color = continent, frame = year)) +
geom_point() +
scale_x_log10()
gg_animate(p)
})
}
shinyApp(ui, server)
Now that there's a newer breaking version of gganimate, #kt.leap's answer is deprecated. Here's what worked for me with the new gganimate:
library(gapminder)
library(ggplot2)
library(shiny)
library(gganimate)
theme_set(theme_bw())
ui <- basicPage(
imageOutput("plot1"))
server <- function(input, output) {
output$plot1 <- renderImage({
# A temp file to save the output.
# This file will be removed later by renderImage
outfile <- tempfile(fileext='.gif')
# now make the animation
p = ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop,
color = continent)) + geom_point() + scale_x_log10() +
transition_time(year) # New
anim_save("outfile.gif", animate(p)) # New
# Return a list containing the filename
list(src = "outfile.gif",
contentType = 'image/gif'
# width = 400,
# height = 300,
# alt = "This is alternate text"
)}, deleteFile = TRUE)}
shinyApp(ui, server)
I was dealing with the same issue and found only your question and no answers... But the way you phrased it reminded me that renderPlot is finicky:
it won’t send just any image file to the browser – the image must be generated by code that uses R’s graphical output device system. Other methods of creating images can’t be sent by renderPlot()... The solution in these cases is the renderImage() function. source
Modifying the code from that article gives you the following:
library(gapminder)
library(ggplot2)
library(shiny)
library(gganimate)
theme_set(theme_bw())
ui <- basicPage(
imageOutput("plot1"))
server <- function(input, output) {
output$plot1 <- renderImage({
# A temp file to save the output.
# This file will be removed later by renderImage
outfile <- tempfile(fileext='.gif')
# now make the animation
p = ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop,
color = continent, frame = year)) + geom_point() + scale_x_log10()
gg_animate(p,"outfile.gif")
# Return a list containing the filename
list(src = "outfile.gif",
contentType = 'image/gif'
# width = 400,
# height = 300,
# alt = "This is alternate text"
)}, deleteFile = TRUE)}
shinyApp(ui, server)