since version 1.5.4
{@escape `SEP`...`SEP`} {@escape* `SEP`...`SEP`}
Escape the content of the macro from evaluation even if it contains macro opening and closing strings.
The `SEP`
is any string that does not appear in the content of the macro.
When you want to include something into the output that looks like a Jamal macro but should not be evaluated as such, you can use the escape
macro.
An example is a reference to a Maven property in a pom.jam
file, like ${project.build.sourceDirectory}
.
In pom.jam
files the convention is to use {
and }
as macro opening and closing strings.
This collides with the Maven property reference.
Jamal may interpret the Maven property reference as a macro and try to evaluate it.
You can use some special macro opening and closing string, but it may be cumbersome.
It may be the right choice when there are many Maven property references in the file.
On the other than, when you already have a complex and relatively large pom.jam
file, and you need to reference only one property in it, it may be simpler to use the escape
macro.
This macro is parsed specially and overrides the macro parsing.
When Jamal sees a macro, it has to find the end of the macro before evaluating the macro.
It does that by looking up the macro closing string, taking all opening strings and the proper nesting into account on the way.
This logic is implemented in the interface Macro
as a default method.
The implementation of the escape
macro overrides this default method.
It simply looks at the `SEP`
string at the start and then seeks forward ignoring all macro opening and closing strings or nesting logic until it finds the same `SEP`
string again.
The part SEP
between the back-tick characters can be any string, which does not appear inside the escaped part of the file.
This string along with the back-ticks has to be repeated at the end of the macro before the macro end string.
This kind of string enclosure is similar to the shell "here string" syntax.
The result of the macro is the escaped string without any modification.
{@escape `a`{`a`}
will result
{
Note
|
This macro originally was intended to be used by Jamal itself when evaluating a user defined macro, which was defined using different macro opening and closing strings than the actual one. In this case the macro opening and closing strings, which were in effect at the time of the macro definition are replaced with the current one. That way the macros defined inside the macros will be evaluated even though the macro opening and closing strings have changed. At the same time the current macro opening and closing strings had no special effect by the time of the macro definition.
If there is any current macro opening and closing string in the definition of the macro, then they should not play a special role.
They get protected using the |
There is another way to escape content from macro evaluation.
You can write a *
right after the escape
keyword (no space between), as
{@escape* `a`{`a`}
In this case, the escape does not only escape the macro opening and any other otherwise processable content but also results in the protecting shell around the escaped string. The result in this case will be
{@escape*`a`{`a`}
The macro finally will result the escaped string when the processing of the whole input is finished in a final phase.
This is useful when the escaped part is inside a macro and due to the complex macro evaluation, it is evaluated multiple times.
You could enclose the escaped string into surrounding escapes, and putting a *
is similar to that.
It is infinitely deep, and it is not necessary to know how deep the escaping is until the whole file was processed.
Note
|
You will never see in your output the You can use the closer functionality of Jamal via the |
Built-in macros implemented in Java have the possibility to register an object to be executed after the processing of the whole content. Such an object is a closer, and it can be used to close resources that were open by the macro during processing. During the execution of this closer the code can access and modify the final result.
The macro escape*
registers a closer that will invoke the Jamal processing again for the output with a flag that tells every escape*
macro to release its content.
In some cases it may happen that you want the escape*
closer run before some other closers, but the escape*
happens later than the register of the other closer.
The different closers are invoked in the order they were registered.
You may use a macro defer
, which also creates a closer.
The use of the macro defer
precedes the first evaluation of an escape*
macro.
In this case the closer registered by defer
would be evaluated before the escape*
closer.
If you want the escape*
closer to run first, you have to use the macro escape*
before defer
.
The simplest form is
{@escape*````}
It essentially escapes an empty string delimited by two backtick delimited empty strings.
(Hence, the four back-ticks.)
After the content liberation the result will be an empty string, thus there is no harm using this before any defer
macro.
The closer registered by escape*
is simple.
It simply evaluates the result setting a flag that tells escape*
that this time it should ignore the *
.