Skip to content

Latest commit

 

History

History
127 lines (92 loc) · 5.78 KB

escape.adoc

File metadata and controls

127 lines (92 loc) · 5.78 KB

escape

since version 1.5.4

Syntax

{@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.

History

  • since 1.9.1 (escape*)

Description

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.

Jamal source
{@escape `a`{`a`}

will result

output
{
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 escape macro automatically.

There is another way to escape content from macro evaluation. You can write a * right after the escape keyword (no space between), as

Jamal source
{@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 escape* macro. It is eliminated after the whole file was processed by Jamal invoking a so-called closer. The closer object is automatically created and registered by Jamal when the escape* macro is used.

You can use the closer functionality of Jamal via the defer macro.

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 *.