Skip to content
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

epoxy chunk transformer cannot handle inline instructions #124

Open
AlbertRapp opened this issue Sep 24, 2023 · 3 comments
Open

epoxy chunk transformer cannot handle inline instructions #124

AlbertRapp opened this issue Sep 24, 2023 · 3 comments

Comments

@AlbertRapp
Copy link

Hi Garrick,

great package. I'm currently playing around with the CRAN version of your package and I encountered the problem that the epoxy chunk cannot handle inline instructions once a .transformer is added. Am I doing something wrong or is this a bug?

Reprex

Example from the docs renders just fine

```{epoxy, .transformer = epoxy::epoxy_transform("bold")}
All cars stopped between {min(cars$dist)} and {max(cars$dist)} feet
from a starting speed of {min(cars$speed)}---{max(cars$speed)}
```

All cars stopped between 2 and 120 feet from a starting speed of 425

Fails once an inline formatting option is introduced

I have added a .dollar for the first value that is inserted here (This formatting doesn't make sense here but it's just an example 😄 )

```{epoxy, .transformer = epoxy::epoxy_transform("bold")}
All cars stopped between {.dollar min(cars$dist)} and {max(cars$dist)} feet
from a starting speed of {min(cars$speed)}---{max(cars$speed)}
```
Quitting from lines 21-23 [unnamed-chunk-4] (test_file.qmd)
Error in `parse()`:
! <text>:1:9: unexpected symbol
1: .dollar min
            ^
Backtrace:
  1. global .main()
 19. glue (local) `<fn>`(".dollar min(cars$dist)")
 21. epoxy (local) .transformer(expr, env)
 23. glue (local) transformer(text, envir)
 25. base::parse(text = text, keep.source = FALSE)
Execution halted
@gadenbuie
Copy link
Owner

Thanks Albert! When you set .transformer = epoxy_transform("bold"), you're actually replacing the default transformer, which is epoxy_transform("inline") or epoxy_transform_inline(). The inline transformer applies the inline formatting syntax, so without it the .dollar syntax won't work.

The good news is that you can chain transformers, so .transformer = epoxy_transform("inline", "bold") will apply the inline transformer first, followed by the bold transformer. That would make every replacement bold while still allowing the .dollar syntax.

There's some more information about this in the epoxy_transform() docs, in particular for the ... argument.

As an aside, bold/italic/collapse/etc transformers represent an early iteration of epoxy, and they were helpful in motivating me to figure out how to chain transformers together, which unlocked a few new things. But ultimately, it's a bit more clunky for two reasons: either they apply the same transformation to every replacement or they require some kind of locally-defined syntax (e.g. the & and | syntax of epoxy_transform_collapse()). That frustration and the ease of cli's inline transformers motivated the newer inline formatting syntax. I didn't completely remove the older stuff because they might be useful in some circumstances, or they could provide examples of how to write a transformer if you'd like to write your own. (At some point I might add a vignette about that, although most people would be better off writing their own inline transformer.)

@AlbertRapp
Copy link
Author

Huh, that's interesting. I wouldn't have figured that one also needs to include the inline transformer. After all, using only .transformer = epoxy_transform("bold") and no inline options works with the outputs being inline. The error is also a bit cryptic on that part. So I'm guessing, the intended point is that one should always start out with epoxy_transform_inline() as a basis for all further steps?

@gadenbuie
Copy link
Owner

gadenbuie commented Sep 25, 2023

Ah, so the wording and naming around all of these pieces is indeed confusing and hard to pin down. Let me break this down a little bit:

  1. The inline expression syntax of {expr} comes from the glue package.

  2. glue transforms the expression expr into replacement text (or more simply, output) by evaluating expr as R code. Transformers modify expr or its value as its transformed from an R expression into text.

  3. One of the core ideas of epoxy is to hook into the .transformer option of glue() and give you the ability to do a whole lot more to expr or its result besides just turning it into a character string.

    So epoxy_transform_inline() refers to the transformer that adds the .<class> syntax inside the {expr}. Without including the inline transformer, {expr} still works but you can't do {.dollar expr}.

  4. Also epoxy_transform_inline() is the default transformer in epoxy, but there are a few others in this package that people might want to to use. Someone might even want to disable the inline transformer and replace use one of the other ones. Or they might want to add their own on top of the inline transformer.

    This is why epoxy lets you choose the transformer and also why it supports chaining transformers. If you wanted to use the inline transformer syntax and also make every replacement bold, you could chain the inline and bold transformers with epoxy_transform("inline", "bold").

    That whole area is a little tricky and most people will be very happy to not mess with the .transformer option. (And I should probably take out the bold transformer examples or move them somewhere less prominent.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants