Keats / tera

A template engine for Rust based on Jinja2/Django
http://keats.github.io/tera/
MIT License
3.43k stars 279 forks source link

[Feature Request] Ability to change start and stop delimiters #343

Open lukehsiao opened 5 years ago

lukehsiao commented 5 years ago

With the template delimiters as {{ }} {%, etc., is there a way to use Tera in content that heavily uses these curly braces and %? For example, if I wanted to use tera to template a LaTeX section like this:

Trying to template name.last

\newbibmacro{name:bold_author}{%
  \ifthenelse{\equal{\namepartfamily}{ {{name.last}} }}%
    {\textbf{\ifblank{\namepartgiven}{}{\namepartgiveni\space}\namepartfamily}}%
    {\ifblank{\namepartgiven}{}{\namepartgiveni\space}\namepartfamily}%
  \ifthenelse{\value{listcount}=1 \AND\value{liststop}=2}%
    {\space and\space}
    {\ifthenelse{\value{listcount}<\value{liststop}}%
      {\addcomma\space}
      {}
    }
}

Tera fails to parse with the error:

Parsing error(s):
* Failed to parse "test.tex"
  --> 27:31
   |
27 | \newbibmacro{name:bold_author}{%
   |                               ^---
   |
   = unexpected tag; expected some content

presumably due to the conflicting use of {} and %.

Using jinja options, I am able to switch delimiters:

block_start_string='~<',
block_end_string='>~',
variable_start_string='<<',
variable_end_string='>>',
comment_start_string='<#',
comment_end_string='#>',

which allows me to make a template that looks like the following and parses correctly:

\newbibmacro{name:bold_author}{%
  \ifthenelse{\equal{\namepartfamily}{ <<name.last>> }%
    {\textbf{\ifblank{\namepartgiven}{}{\namepartgiveni\space}\namepartfamily}}%
    {\ifblank{\namepartgiven}{}{\namepartgiveni\space}\namepartfamily}%
  \ifthenelse{\value{listcount}=1 \AND\value{liststop}=2}%
    {\space and\space}
    {\ifthenelse{\value{listcount}<\value{liststop}}%
      {\addcomma\space}
      {}
    }
}

But, without being able to change delimiters in Tera, am I stuck? Is it impossible to use tera in templates that already use curly braces and percentage signs?

Keats commented 5 years ago

Is it impossible to use tera in templates that already use curly braces and percentage signs?

If you want to interpolate variables from Tera yes :/ The parser generator I am using doesn't allow passing arguments but it could be possible to hardcode an alternative parser by duplicating the grammar. You won't be able to pick which delimiters you want to use though

lukehsiao commented 5 years ago

If you want to interpolate variables from Tera yes :/

I see, I may need to look around at alternatives for now, then. Thanks for the quick response and for your work on Tera and Gutenberg!

Keats commented 5 years ago

Re-opening it, it's worth having open to think about it

lukehsiao commented 5 years ago

Re-opening it, it's worth having open to think about it

Fair enough. The ability to switch delimiters would really open up some applications. In the rust ecosystem, there are many HTML templating crates, but I've been having a hard time trying to find one that can generalize to something like LaTeX like Jinja2 does.

lukehsiao commented 1 year ago

I've grown to really like Tera over the years, and still would love to template some LaTeX files. Is there any guidance you could give me if I wanted to do this, even if it involves a local fork with hard-coded changes to the delimiters?

E.g., how would I hardcode an alternative parser with different delimiters in a duplicate grammar?

Keats commented 1 year ago

You can fork the repo and replace https://github.com/Keats/tera/blob/master/src/parser/tera.pest#L148-L155 to use your delimiters of choice

xpe commented 4 months ago

I think many people see value here. The catch seems to be an implementation detail. As I understand it, the Tera parser is generated at compile time with hardcoded template delimiters.

This leaves the question: what are good ways to create a parser with user-definable template delimiters. Here are two options I see:

  1. Use a macro to generate a template parser. This would allow customization of the template delimiters.
  2. Make the parser's initialization/configuration accept custom template delimiters.

Of course, some choices of custom template delimiters might clash with other syntax. The library could check for clashes perhaps.

Of course, the above options have complexity and tradeoffs. I'm not very familiar with the idea of user customizations of parsers. Perhaps others see other ways?

Keats commented 4 months ago

It's not really doable for v1 but it should be pretty easy for v2 to implement that.