Parops (parameter options) are usually used to give extra parameters or options to built-in macros.
They are key/value pairs at the start of the input of the built-in macro.
Java classes support the parsing of these parops that the built-in macros can use.
This parsing is also used for user-defined macros when the macro is defined with the named
parameter option (parop).
Note
|
Name of the game
User-defined macros have parameters.
Jamal uses options defined using the macro |
Even though built-in macros can parse their input in any way, there are support classes to make this task easier. Using these classes has two advantages.
-
These classes are thoroughly tested, documented, and easy to use. They save development time and effort.
-
Macros are more coherent and easier for users to understand when they follow similar patterns.
This document describes the format and use of the options parsed using these supporting Java classes.
Macro options are name-value pairs that modify the behavior of a macro.
They are not to be confused with global options set using the macro options
.
For example, the line
{@include [verbatim lines=1..13] otherContent.txt}
will instruct Jamal to include the file verbatim and only the lines from 1 to 13.
The options in this case are between the [
and ]
characters.
They have to form name=value
pairs separated by spaces.
The enclosing characters for the parops are not hard-wired.
Each macro can declare the characters it uses to enclose the parops.
We use [
and ]
for the core macros, and it is customary to use (
and )
for the macros in other packages.
Note
|
The use of the To keep backward compatibility, it was decided that core macros will use |
There are macros that do not need any content other than the parops. In this case, the parops are the whole input and are not enclosed in any characters. Some macros use line oriented input, and they assume no input on the first line. These macros use the first line options, also not needing any enclosing characters.
When a macro implements the option parsing specifying the first line or the whole input, as an option source, the macro still can be used with parops enclosed in (
and )
characters.
The options can be mandatory and optional. Parops have types and can have default values. Specifying a parop not handled by the macro is an error.
The macro Java implementation declares the parop names, types, and optionally default values. The helper tool automatically parses the input. The macro Java code gets the values for the parops parsed and converted. This ensures conformity for the option parsing.
Options can be
-
integer numbers,
-
strings,
-
enumerated values,
-
boolean values (always have a default value ˛false`),
-
regular expression patterns, and
-
lists (multiple string values).
Some parops may have multiple values.
The Java code can define a name and also aliases for the same parop. The names and aliases can be used interchangeably, though the Java code can query the actual name used. The use of this feature is acceptable in some special cases only. Generally, macros are encouraged to be implemented in a way that it should make no difference which alias the user uses.
Names and aliases are case-sensitive.
The option name is also the name of the user-defined macro that can be used to define the value of the parop. Aliases are not considered as macro names when searching for values. An option may be declared in a way that it has no names, only aliases. In this case, the option value cannot be defined globally only as a case by case option.
Tip
|
Let’s say that a parop has the name globalFormat an the alias format .
In that case the user defined macro globalFormat can be used to define the value of the parop.
The parop name globalFormat can also be used as a parop name on the input and so can the alias format .
However, even if there is a macro defined and named format it will not be used to define the value of the parop.
Aliases work only in the input of the macro.
|
Note
|
The options start and end with an opening and closing character. The macros have opening and closing strings. Macro parop parsing uses single characters. |
As we have seen, the include
macro with the parops
{@include [verbatim lines=1..13] otherContent.txt}
uses the [
and ]
characters.
The built-in core macros use these separator characters. Currently 14 built-in core macros have parops.
The class Scanner
provides the tools to ease parop parsing.
When macros need parops using the support classes, they look at different sources for the values. First, they look at the macro’s input and try to find the parops. The parops are specified in the format
name1=value1 name2=value2 ... nameN=valueN
The names are the parop names that the macro may use.
The macro first passes the input to the parsing method.
When a parop is not defined, the algorithm tries to look up a user-defined macro with the name.
If you set {@define margin=2}
somewhere in your Jamal source, this value will be used by every trimLine
following it.
If the value is not defined as a parop or a user-defined macro, then the built-in macros can use default values.
Note
|
The macro default usually steps into the place of an undefined macro.
Not in this case.
It is also an error if the macro used as the configuration has parameters unless the option {@options lenient} is specified.
|
The parops have types.
-
In the case of boolean parops, the values
false
,0
, orno
are treated as false. Everything else will resulttrue
. The usual way to use boolean parops is to specify the name only. If a required boolean parop is not present, then the option of the same name is taken into account. The option is the one that you can set using the macro{@options …}
. For example, you can specify{@options trimVertical}
if you want all uses of the macrotrimLine
to trim vertically. User-defined macros for a boolean parops are NOT used. All boolean options arefalse
by default; hence there are no mandatory boolean parops. Undefined boolean parops arefalse
. -
parops can be strings and integers. These can be defined in a parop or as the value of a macro, as described above. A parop is string or integer when it is declared like that in the Java source. You can freely enclose integer parops in quotes and specify a string without quotes. Note, however, that in the latter case you cannot use some special characters in the string, like spaces or
=
. -
Some parops can have more than one value. The
name
can appear more than once with multiple values assigned to it. In this case, the name or an alias appears multiple times a value assigned. The names and the aliases can be mixed arbitrarily.
Macros may decide whether to define any default value for a parop. If not, the macro will error if the parop is not defined and there is no user-defined macro.
The parop names can have aliases. These are used solely inside the macro as parops. Alias names do not play a role as user-defined macros. In other words, the "main" name of the parop can also be a macro; aliases cannot.
The core macro uses $forsep
as a parop name and has an alias separator
.
If neither is specified in the macro, only the user-defined macro $forsep
is consulted.
If there is a {@define separator=;}
in the code, it will not alter the for
macro execution.
In the parop list, however, the names and the aliases are interchangeable.
Macros can define parops using only aliases.
Technically they specify null
as the name and give meaningful strings only for one or more aliases.
In that case, there is no way to define a global value for the parop as a macro.
Aliases are specific to the macro. Different macros may use the same parop name for different purposes, providing different or the same aliases. It is up to the macro implementation what parop names and aliases they use. However, the parop names and the aliases are unique in a single macro implementation.
In the parop definition
name1=value1 name2=value2 ... nameN=valueN
the value1, value2, …, valueN
values are either numeric, boolean or string values.
The type depends on what the macro awaiting for the specific parop.
You can enclose the values between "
, """
or without any delimiter.
"…"
is a typical string representation.
Using the "
is optional if there is no space or a particular escape sequence in the value.
For example, margin=1
is just as good as margin="1"
.
On the other hand, name=Peter Verhas
is not valid.
It has to be represented as name="Peter Verhas"
because it contains a space.
A string starting and ending with a "
character must not contain a new-line character.
If you need multi-line strings, use the \n
characters or a triple-quoted multi-line string.
A multi-line string starts and ends with """
, three quote characters.
Some macros use only the first line for parops. Even in this case, the new-line character inside a triple-quoted string is part of the value and does not stop the parsing. The parsing stops only at the first new-line character, which is not part of any value and not escaped.
If there are many parops, and the first line becomes too long, then the \
character escapes the new line.
Subsequent lines can also escape the new-line character using the \
character.
It makes the parser skip the new line and go on parsing on the following line.
Let’s assume that we have a macro someMacro
and the Java class SomeMacro
declares the parops to be on the first line of the input.
{@someMacro header="""
This is the header
text and it is
multi-line
""" paging=true skip="A" skip="DD" skip="3.145" \
comment="this is still a parop because of the \\ at the end of the previous line"
this is the input the macro will use for its result; everything else until here are parops
}
When the macro declares that the parops are on the first line or until the end of the input you can still optionally use (
and )
to enclose the parops.
When the macro asks the parser to parse the input, it also specifies the parop names it can handle. An error will occur if there is any parop the macro does not handle.
The macro also specifies the type of the parop. If Jamal cannot convert the parop value to the required type, an error will occur.
-
Numeric parops are integers. You can enclose them between
"
or"""
. -
Boolean parops are
true
if they are present without any value. Using the string valuesfalse
,0
, orno
will mean afalse
value. They arefalse
if they are not present as a parop, and the name (not an alias) is alsofalse
as an option. A name isfalse
as an option if the macro{@options name}
was not invoked in the current or higher scope or if you invoked the option in the form{@options ~name}
. You can set a boolean parop totrue
by mentioning the name without=
and any value. Any value other than that listed forfalse
will mean atrue
value. We recommend using only the name without any value assigned to it.
As you can see in the example, some parops can have multiple values. An error will occur if multiple parops are defined, but the macro accepts only one. If only one value is defined, but the macro needs a list, it will get a one-element list. You cannot specify multiple values for such parops using user-defined macros. Jamal will not add the global or locally defined user macro to the parop list if the parop is specified at least once on the input. If there are parops, those values are used; the macro values are ignored.
Single-line and multi-line strings have similar syntax as Java strings. You can use the same escape sequences.
In this chapter, we list some syntax examples and the use of the parops. These examples come from the unit test file
../jamal-test/src/test/java/javax0/jamal/test/tools/params/TestParams.java
The display of each example contains a definition line, an INPUT part, and a RESULT part.
The "INPUT" part shows the code that defines the values of the parops.
It may also contain at the start some options
or define
macro in case some parops get value from this source.
The "RESULT" part shows the calculated value of every parop.
The definition line contains the parops' names comma separated.
Each parop has at least one name.
In case the parop has an alias that can be used as a parop name instead of the original name, it is given after a |
character.
The parop type is either I
integer, S
string, B
boolean, or L
list.
The last part following the last :
is the default value, if there is any.
The test parses this definition string and calls the appropriate orElse()
, orElseInt()
, asString()
and so on methods, which define the type of the parop.
The RESULT part shows the parops with the values as key=value
.
When the returned value is a string, the result is enclosed between quotes.
When the value has some other type, it is shown like a casting operation (type)
in front of the value.
This example shows the simple use of two integers and a string parameter use.
margin:I,top:I,left:S
INPUT
margin=2 top=3 left="aligned"
RESULT
margin=2
top=3
left="aligned"
The integer parameters are not enclosed between "
characters, although it is perfectly okay to do so. On the
other hand the value "aligned"
is specified between quotes. This value is also eligible to be specified without
"
as it contains neither space, not special escape character or the parsing closing character, which was \n
in this case.
Boolean parameters can be specified by the sheer presence. When a boolean parameter is not present and not
defined as an option, then the value is false
.
left:B,right:B
INPUT
left
RESULT
left=(boolean)true
right=(boolean)false
Boolean true
parameters can be represented by the appearance of the parameter on the line. In this example the
parameter`left` simple appears on the input without any value. The parameter right
does not and it is also not
set to true
as an option, so the value if false.
margin:I,top:I,left:S
INPUT
{@define margin=2}
top=3 left="aligned"
RESULT
margin=2
top=3
left="aligned"
In this example two values are present as parameters, but the parameter
margin
is present by a user defined macro.
This example shows that a parameter defined in a user-defined macro is overridden by the definition of the parameter on the input.
margin:I
INPUT
{@define margin=3}
margin=2
RESULT
margin=2
The parameter margin
is defined as a user defined parameter, but the value 3
is ignored because it is also
defined on the input to be 2
and this is stronger.
When a parameter is used by a macro and there is no default value for the parameter then not defining the parameter will be an error.
margin:I,missing:S
INPUT
margin=2
RESULT
javax0.jamal.api.BadSyntax: The key 'missing' for the macro 'test environment' is mandatory
The sample macro configuration requires two parameters: margin
and missing
.
None of them has default value and they are also no boolean or list values.
Margin is defined in the input but the parameter missing
, aptly named, is indeed missing.
This makes the parameter parsing to throw an exception.
This example shows that the first line can be extended using continuation lines, which are escaped using \
character at the end of the line.
margin:I,top:I,left:S
INPUT
margin=2 top=3 \
left="aligned"
RESULT
margin=2
top=3
left="aligned"
The parameters margin
and top
are defined on the first line.
The parameter left
would have been too long.
It got into the next line.
To do that the last character on the previous line is a \
character.
This example shows how you can use multi-line strings as parameters.
Multi-line strings start and end with the """
characters and can span multiple lines.
In this example the sample multi-line string does not span multiple line showing that this is not a must.
The use also demonstrates that single "
characters do not need to be escaped, but they may be escaped.
left:S
INPUT
left="""ali"gn\"ed"""
RESULT
left="ali\"gn\"ed"
The value of the parameter`left` is specified as a multi-line string, and it contains two "
characters, one escaped, the other without escaping.
This example shows how you can use multi-line strings as parameters.
Multi-line strings start and end with the """
characters and can span multiple lines.
In this example the sample multi-line string spans two lines.
left:S
INPUT
left="""alig
ned"""
RESULT
left="alig\nned"
This time the parameter aligned
contains a new line in the string.
Multi-valued parameters can apper more than once as parameter. But it is not a must. They may be missing, or specified only one time. This example shows that a multi-valued parameter can appear one time.
left:L
INPUT
left="aligned"
RESULT
left=[aligned]
The parameter left
is a L
list as it is declared by the testing macro.
Even though it is a list it appears only once as a parameter.
The result for the macro is that this parameter will be a list that has a single element.
This example shows how to specify multiple values for a parameter that is declared to have multiple values.
left:L
INPUT
left="aligned"left="alignad"
RESULT
left=[aligned,alignad]
This example shows an extensive list of all the possibilities how a boolean parameter can be defined.
trueOption:B,explicitFalseOption:B,implicitFalseOption:B,falseAsNo:B,falseAsFalse:B,
falseAs0:B,trueAsTrue:B,trueAsYes:B,trueAs1:B,trueAsAnything:B,trueStandalone:B
INPUT
{@options trueOption|~explicitFalseOption}
falseAsNo=no falseAsFalse=false falseAs0=0 trueAsTrue=true \
trueAsYes=yes trueAs1=1 trueAsAnything="really anything goes" trueStandalone
RESULT
trueOption=(boolean)true
explicitFalseOption=(boolean)false
implicitFalseOption=(boolean)false
falseAsNo=(boolean)false
falseAsFalse=(boolean)false
falseAs0=(boolean)false
trueAsTrue=(boolean)true
trueAsYes=(boolean)true
trueAs1=(boolean)true
trueAsAnything=(boolean)true
trueStandalone=(boolean)true
The parameter trueOption
is set globally calling the macro options
. The explicitFalseOption
is set to false
on the same line. This is an example about how to set and reset options, even more than one at the same time.
-
The parameter
implicitFalseOption
is not set anywhere. It is required by the macro, it is notdefined as an option and also not as a parameter. This parameter will befalse
by default. -
The parameter
falseAsNo
is set tono
as a parameter. SimilarlyfalseAsFalse
is set tofalse
,falseAs0
is set to0
. -
As the false parameters are listed with all the values the
true
values are also listed with some of the possible assignment values that result atrue
value.trueAsTrue
is set totrue
. The parametertrueAsYes
is set toyes
,trueAs1
is set to1
. FinallytrueAsAnything
is set to an arbitrary string that will be converted to a true value. -
The parameter
trueStandalone
demonstrate the use of a boolean parameter when the name is simply listed as a parameter without any value. In this case the presence of the parameter signals the true value it presents.
Using some arbitrary value to signal a boolean value is usually not the best choice. Other than choosing
presenting the value in the form of a standalone parameter, or with value yes
, true
, no
, 0
, false
is a
matter of taste. Use the one that you feel makes your code the most readable. Jamal source can get very easily
really messy and complex. Strive to make it as simple as possible.