r-lib / marquee

Markdown Parser and Renderer for R Graphics
https://marquee.r-lib.org
Other
81 stars 2 forks source link

Programmatic way to include grobs #24

Open teunbrand opened 3 months ago

teunbrand commented 3 months ago

Hi Thomas,

This continues a few comments that we exhanged off-github; I'm having difficulty providing an element_marquee() with a programatically generated list of grobs.

From the code below, I'd like to render the pts$foo grob in the text.

library(marquee)
library(ggplot2)
library(grid)

# Populate element
el  <- ggplot2:::combine_elements(element_marquee(), theme_get()$text)

txt <- "Here be ![](foo) a point"
pts <- list(foo = pointsGrob(0.5, 0.5, default.units = "npc"))
expr <- rlang::expr(element_grob(el, label = txt))

For clear reasons, this wouldn't work out of the box, as the desired grob is in a list somewhere, not the current environment.

grob <- rlang::eval_tidy(expr)
grid.newpage()
grid.draw(grob)

Your suggestion at the time, to use a data mask does not work as I had hoped.

grob <- rlang::eval_tidy(expr, data = pts)
grid.newpage()
grid.draw(grob)

Neither does providing the grobs as the env argument.

grob <- rlang::eval_tidy(expr, env = list2env(pts))
grid.newpage()
grid.draw(grob)

After some trial and error, what I found that did work was to use a local environment. This is fine for my purposes, but I'd prefer it if there were an easier way to do this.

grob <- withr::with_environment(list2env(pts), rlang::eval_tidy(expr))
grid.newpage()
grid.draw(grob)

Created on 2024-06-01 with reprex v2.1.0

lionel- commented 3 months ago

I wonder if we should advise evalq(myexpr(), pts). Does this work as expected too?

thomasp85 commented 3 months ago
grob <- evalq(element_grob(el, label = txt), pts)
grid.newpage()
grid.draw(grob)

also fails to find the object