since version 1.0.0
The macro script
defines a user-defined macro interpreted as a script.
The syntax of the command is
{@script/scripttype id(parameters)=body}
If script
is followed by a /
character, then the subsequent identifier specifies the type of script. If omitted, JShell
is used by default. Any scripting language that supports the Java scripting API and has its interpreter on the classpath can be utilized.
The handling of parameters differs from that of user-defined macros created with the define
built-in macro. For user-defined macros, parameter strings are replaced with their actual values during evaluation. In scripts, however, parameters are treated as global variable names, and their actual values are injected into the script’s context before evaluation.
This approach limits the freedom in choosing parameter names. With define
, any string can be used as a parameter identifier, provided it does not contain ,
or )
. For scripts, parameter names must be valid identifiers within the scripting language since they are utilized as such.
Value injection transforms the actual parameter values into script values. To facilitate this, Jamal performs several conversions:
-
It first attempts to interpret the parameter as an integer. If successful, the corresponding global variable will store an integer value.
-
If integer conversion fails, it tries to convert the value to a double.
-
If neither numeric conversion is possible, it checks if the value is the lowercase
true
orfalse
. If so, the variable will hold aBoolean
value. -
Otherwise, the global variable is assigned the actual value as a string.
The actual scripting implementation might not support Integer
, Double
, or Boolean
types, but corresponding script types will be available.
Below is a sample script that demonstrates a looping construct in JShell.
The source Jamal file:
{@script for(loopvar,start,end,text)=
var c = "";
for( var i = start ; i <= end ; i++ ){
c = c + text.replaceAll(loopvar, ""+i);
}
System.out.print(c);
}
{for%xxx%1%3%xxx. iterated
}
The output generated by the Jamal preprocessor:
1. iterated
2. iterated
3. iterated
Note that the script code itself contains the macro opening and closing strings. This does not do any harm so long as long these are in pairs. It is a better practice to change the separator characters to something that cannot appear in the body of the script macro.
Starting with version 1.3.0, Jamal supports the JShell built-in scripting engine.
You can define JShell
as a script type.
In this case, the content will be passed to the Java built-in JShell engine.
When the script is invoked, the result of the macro will be the string printed by the JShell script.
If this is empty, the value of the last Java shell snippet will be used.
The argument names have to be valid Java identifiers.
When the script is invoked they will be defined as String
, long
, double
or boolean
variables.
They will get the actual values of the parameters.
The type depends on the actual value.
If the value string can be interpreted as a long
, then it will be converted to long
.
If the string is not a long, but can be converted to double
, then the variable will be double
.
If the string is either true
or false
case insensitive, then the variable will be boolean
.
In any other case the variable will be declared as String
.
In short, the arguments to a script
macro will be converted to the following types in this order, whichever first succeeds:
-
long
-
double
-
boolean
-
String
For more information and details, see the macro JShell
.