123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- [[modules-scripting-painless-syntax]]
- === Painless Syntax
- experimental[The Painless scripting language is new and is still marked as experimental. The syntax or API may be changed in the future in non-backwards compatible ways if required.]
- [float]
- [[painless-types]]
- === Variable types
- Painless supports all of https://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html[Java's types],
- including array types, but adds some additional built-in types.
- [float]
- [[painless-def]]
- ==== Def
- The dynamic type `def` serves as a placeholder for any other type. It adopts the behavior
- of whatever runtime type it represents.
- [float]
- [[painless-strings]]
- ==== String
- String constants can be declared with single quotes, to avoid escaping horrors with JSON:
- [source,painless]
- ---------------------------------------------------------
- def mystring = 'foo';
- ---------------------------------------------------------
- [float]
- [[painless-arrays]]
- ==== Arrays
- Arrays can be subscripted starting from `0` for traditional array access or with
- negative numbers to starting from the back of the array. So the following
- returns `2`.
- [source,painless]
- ---------------------------------------------------------
- int[] x = new int[5];
- x[0]++;
- x[-5]++;
- return x[0];
- ---------------------------------------------------------
- [float]
- [[painless-lists]]
- ==== List
- Lists can be created explicitly (e.g. `new ArrayList()`) or initialized similar to Groovy:
- [source,painless]
- ---------------------------------------------------------
- def list = [1,2,3];
- ---------------------------------------------------------
- Lists can also be accessed similar to arrays. They support `.length` and
- subscripts, including negative subscripts to read from the back of the list:
- [source,painless]
- ---------------------------------------------------------
- def list = [1,2,3];
- list[-1] = 5
- return list[0]
- ---------------------------------------------------------
- [float]
- [[painless-maps]]
- ==== Map
- Maps can be created explicitly (e.g. `new HashMap()`) or initialized similar to Groovy:
- [source,painless]
- ---------------------------------------------------------
- def person = ['name': 'Joe', 'age': 63];
- ---------------------------------------------------------
- Map keys can also be accessed as properties.
- [source,painless]
- ---------------------------------------------------------
- def person = ['name': 'Joe', 'age': 63];
- person.retired = true;
- return person.name
- ---------------------------------------------------------
- Map keys can also be accessed via subscript (for keys containing special characters):
- [source,painless]
- ---------------------------------------------------------
- return map['something-absurd!']
- ---------------------------------------------------------
- [float]
- [[painless-pattern]]
- ==== Pattern
- Regular expression constants are directly supported:
- [source,painless]
- ---------------------------------------------------------
- Pattern p = /[aeiou]/
- ---------------------------------------------------------
- Patterns can only be created via this mechanism. This ensures fast performance, regular expressions
- are always constants and compiled efficiently a single time.
- [float]
- [[modules-scripting-painless-regex-flags]]
- ==== Pattern flags
- You can define flags on patterns in Painless by adding characters after the
- trailing `/` like `/foo/i` or `/foo \w #comment/iUx`. Painless exposes all the
- flags from
- https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html[Java's Pattern class]
- using these characters:
- [cols="<,<,<",options="header",]
- |=======================================================================
- | Character | Java Constant | Example
- |`c` | CANON_EQ | `'å' ==~ /å/c` (open in hex editor to see)
- |`i` | CASE_INSENSITIVE | `'A' ==~ /a/i`
- |`l` | LITERAL | `'[a]' ==~ /[a]/l`
- |`m` | MULTILINE | `'a\nb\nc' =~ /^b$/m`
- |`s` | DOTALL (aka single line) | `'a\nb\nc' =~ /.b./s`
- |`U` | UNICODE_CHARACTER_CLASS | `'Ɛ' ==~ /\\w/U`
- |`u` | UNICODE_CASE | `'Ɛ' ==~ /ɛ/iu`
- |`x` | COMMENTS (aka extended) | `'a' ==~ /a #comment/x`
- |=======================================================================
- [float]
- [[painless-operators]]
- === Operators
- All of Java's https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html[operators] are
- supported with the same precedence, promotion, and semantics.
- There are only a few minor differences and add-ons:
- * `==` behaves as Java's for numeric types, but for non-numeric types acts as https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-[`Object.equals()`]
- * `===` and `!==` support exact reference comparison (e.g. `x === y`)
- * `=~` true if a portion of the text matches a pattern (e.g. `x =~ /b/`)
- * `==~` true if the entire text matches a pattern (e.g. `x ==~ /[Bb]ob/`)
- [float]
- [[painless-control-flow]]
- === Control flow
- Java's https://docs.oracle.com/javase/tutorial/java/nutsandbolts/flow.html[control flow statements] are supported, with the exception
- of the `switch` statement.
- In addition to Java's `enhanced for` loop, the `for in` syntax from groovy can also be used:
- [source,painless]
- ---------------------------------------------------------
- for (item : list) {
- ...
- }
- ---------------------------------------------------------
- [float]
- [[painless-functions]]
- === Functions
- Functions can be declared at the beginning of the script, for example:
- [source,painless]
- ---------------------------------------------------------
- boolean isNegative(def x) { x < 0 }
- ...
- if (isNegative(someVar)) {
- ...
- }
- ---------------------------------------------------------
- [float]
- [[painless-lambda-expressions]]
- === Lambda expressions
- Lambda expressions and method references work the same as https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html[Java's].
- [source,painless]
- ---------------------------------------------------------
- list.removeIf(item -> item == 2);
- list.removeIf((int item) -> item == 2);
- list.removeIf((int item) -> { item == 2 });
- list.sort((x, y) -> x - y);
- list.sort(Integer::compare);
- ---------------------------------------------------------
- Method references to functions within the script can be accomplished using `this`, e.g. `list.sort(this::mycompare)`.
|