You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@groovy.apache.org by Per Nyfelt <pe...@alipsa.se> on 2022/07/23 17:59:59 UTC
Defining functions in text processed by the StreamingTemplateEngine
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
Re: Defining functions in text processed by the StreamingTemplateEngine
Posted by Per Nyfelt <pe...@alipsa.se>.
Even better! Thank you!
On 7/23/22 23:55, Paul King wrote:
> The SimpleTemplateEngine supports methods (and imports and even local
> class definitions):
>
> def text ="""\ <% import java.time.LocalDate import java.time.format.TextStyle
> def now = LocalDate.now() def dayName(theDate) {
> theDate.dayOfWeek.getDisplayName(TextStyle.FULL, Locale.default) }
> class Const { static days = 3 } %> # Hello Today (<%= dayName(now) %>)
> is <%= now %>. The weather in next <%= Const.days %> days will be: <%
> def weather = [ "Sunny", "Rainy", "Cloudy", "Windy" ] Const.days.times
> { out.println "- " + dayName(now + it) + ": " + weather.shuffled()[0]
> } %> """.stripIndent()
>
> def engine =new groovy.text.SimpleTemplateEngine()
> def template =engine.createTemplate(text)
> printlntemplate.make()
> Cheers, Paul.
>
>
> On Sun, Jul 24, 2022 at 6:35 AM Per Nyfelt <pe...@alipsa.se> wrote:
>
> 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
>>
>>
Re: Defining functions in text processed by the StreamingTemplateEngine
Posted by Paul King <pa...@asert.com.au>.
The SimpleTemplateEngine supports methods (and imports and even local class
definitions):
def text = """\
<%
import java.time.LocalDate
import java.time.format.TextStyle
def now = LocalDate.now()
def dayName(theDate) {
theDate.dayOfWeek.getDisplayName(TextStyle.FULL, Locale.default)
}
class Const {
static days = 3
}
%>
# Hello
Today (<%= dayName(now) %>) is <%= now %>.
The weather in next <%= Const.days %> days will be:
<%
def weather = [ "Sunny", "Rainy", "Cloudy", "Windy" ]
Const.days.times {
out.println "- " + dayName(now + it) + ": " + weather.shuffled()[0]
}
%>
""".stripIndent()
def engine = new groovy.text.SimpleTemplateEngine()
def template = engine.createTemplate(text)
println template.make()
Cheers, Paul.
On Sun, Jul 24, 2022 at 6:35 AM Per Nyfelt <pe...@alipsa.se> wrote:
> 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())}%># HelloToday (<%= 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
>
>
>
Re: Defining functions in text processed by the StreamingTemplateEngine
Posted by Per Nyfelt <pe...@alipsa.se>.
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
>
>