I figured it out. although functions (methods) cannot be defined, a closure works fine:

def text = """\ <% def now = java.time.LocalDate.now() def dayName = { theDate -> return theDate.getDayOfWeek().getDisplayName(java.time.format.TextStyle.FULL, java.util.Locale.getDefault()) } %> # Hello Today (<%= dayName(now) %>) is <%= now %>. The weather in next 3 days will be: <% def weather = [ "Sunny", "Rainy", "Cloudy", "Windy" ] for (i = 1; i < 4; i++) { def day = now.plusDays(i) Collections.shuffle weather out.println "- " + dayName(day) + ": " + weather.first() } %> """.stripIndent() def engine = new StreamingTemplateEngine() def template = engine.createTemplate(text) println template.make()

On 7/23/22 19:59, Per Nyfelt wrote:

Hi,

I am trying to use the StreamingTemplateEngine to create dynamic markdown (similarly to the rmd (r markdown, https://rmarkdown.rstudio.com/authoring_quick_tour.html) but I've encountered a snag:

Simple usage such as the following works fine using the StreamingTemplateEngine:

def text = """\ <% def now = java.time.LocalDate.now() %> # Hello Today (<%= now.getDayOfWeek().getDisplayName(java.time.format.TextStyle.FULL, java.util.Locale.getDefault()) %>) is <%= java.time.LocalDate.now() %>. The weather in next 3 days will be: <% def weather = [ "Sunny", "Rainy", "Cloudy", "Windy" ] for (i = 1; i < 4; i++) { def day = now.plusDays(i) def dayName = day.getDayOfWeek().getDisplayName(java.time.format.TextStyle.FULL, java.util.Locale.getDefault()) Collections.shuffle weather out.println "- " + dayName + ": " + weather.first() } %> """.stripIndent() def engine = new StreamingTemplateEngine() def template = engine.createTemplate(text) println template.make()

But if if want to define a function to simplify the code e.g.

def text = """\ <% def now = java.time.LocalDate.now() def dayName(java.time.LocalDate theDate) { return theDate.getDayOfWeek().getDisplayName(java.time.format.TextStyle.FULL, java.util.Locale.getDefault()) } %> # Hello Today (<%= dayName(now) %>) is <%= now %>. The weather in next 3 days will be: <% def weather = [ "Sunny", "Rainy", "Cloudy", "Windy" ] for (i = 1; i < 4; i++) { def day = now.plusDays(i) Collections.shuffle weather out.println "- " + dayName(day) + ": " + weather.first() } %> """.stripIndent() def engine = new StreamingTemplateEngine() def template = engine.createTemplate(text) println template.make()

...the StreamingTemplateEngine does not accept the function definition:


Template parse error 'Unexpected input: '(' ' at line 4, column 12
         3:
     --> 4: def dayName(java.time.LocalDate theDate) {
         5:     return theDate.getDayOfWeek().getDisplayName(java.time.format.TextStyle.FULL, java.util.Locale.getDefault())

groovy.text.TemplateParseException: Template parse error 'Unexpected input: '(' ' at line 4, column 12
         3:
     --> 4: def dayName(java.time.LocalDate theDate) {
         5:     return theDate.getDayOfWeek().getDisplayName(java.time.format.TextStyle.FULL, java.util.Locale.getDefault())


If there a way to define function in the text processed that would work with the StreamingTemplateEngine?


The code works fine "the other way around" i.e from Groovy code:

def now = java.time.LocalDate.now()

def dayName(java.time.LocalDate theDate) {
    return theDate.getDayOfWeek().getDisplayName(java.time.format.TextStyle.FULL, java.util.Locale.getDefault())
}

println "# Hello"

println "Today ${dayName(now)}) is ${now}."

println "The weather in next 3 days will be:"

def weather = [ "Sunny", "Rainy", "Cloudy", "Windy" ]
for (i = 1; i < 4; i++) {
  def day = now.plusDays(i)
  Collections.shuffle weather
  println "- " + dayName(day) + ": " + weather.first()
}

But I would like a "Markdown first" kind of experience rather than a "Groovy first" since in the "normal" case, the amount of text vastly outnumbers the amount of code.


Best regards,

Per

Reply via email to