Thymeleaf results in error when using variable inside an expression - thymeleaf

For the provided string in my model, I want to print a "growing" list of substrings. For example, if the given string is Wine, the result should be:
W
Wi
Win
Wine
I've come up with the following construct:
<h1 th:with="len=${#strings.length(name)}" th:each="i : ${#numbers.sequence(1, ${len})}" th:text="${#strings.substring(name, 0, i)}"></h1>
but it doesn't work.
If I change ${#numbers.sequence(1, ${len})} to ${#numbers.sequence(1, 4)} it works. However, this way I'd need to manually change the code whenever my initial string's length changes.
I've tried with messages.msg() alternative, but no luck either.
Error:
An error happened during template parsing (template: "class path resource [templates/name-list.html]")
Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "#numbers.sequence(1, ${len})" (template: "name-list" - line 7, col 53)
What am I doing wrong?

th:each has a higher attribute precedence than th:with. Since th:each is evaluated first, the len variable is not available here.
In most cases, you should not/cannot nest ${...} expressions. If the len variable was available here, you should have used len instead of ${len}.
.
<h1
th:each="i : ${#numbers.sequence(1, #strings.length(name))}"
th:text="${#strings.substring(name, 0, i)}" />

Related

Why we are unable to evaluate comprehension if we have defined it inside a rule body in OPA?

The following is my sample code: https://play.openpolicyagent.org/p/oyY1GOsYaf
Here when I try to evaluate names array, it is showing:
error occurred: 1:1: rego_unsafe_var_error: var names is unsafe
But when I define the same comprehension outside the allow rule definition : https://play.openpolicyagent.org/p/Xv0cF7FM8b, I am able to evaluate the selection
[
"smoke",
"dev"]
could someone help me to point out the difference and if I want to define the comprehention inside the rule is there any syntax I need to follow? Thanks in advance
Note: I am getting the final output as expected in both cases, only issue is with the names array evaluation.
The way the Rego Playground generates a query when evaluating a selection is much more simplistic than one might assume. A query will be generated from your selected text, without taking into account where in the document that text was selected. This means that even if you select a local variable inside a rule body, the query will simply contain that variable name (names, in your case); which will be perceived as a reference to a top-level variable in the document's body, even though a rule-local variable was selected. This is why your first sample returns an error, as there is no top-level variable names in the document; whereas the second sample does, and therefore succeeds.
You can test this quirk by selecting and evaluating the word hello on line 3 here: https://play.openpolicyagent.org/p/n5OPoFnlhx.
package play
# hello
hello {
m := input.message
m == "world"
}
Even though it's just part of a comment, it'll evaluate just as if you had selected the rule name on line 5.

Subscript operator with variable or how to cut the end-of-line characters?

I have an expression in Jenkinsfile:
myvar = myvar.substring(0, myvar.length() - 2)
The goal is to cut the EoL characters from the string (which contains the execution result of the batch command).
Recently I've installed GroovyLint plugin for VSCode and it complained about this line:
Violation in class None. The String.substring(int, int) method can be replaced with the subscript operatorGroovyLint(UnnecessarySubstring-1)
I've googled what is that subscript operator and it looks like the replacement would be something like this:
myvar = myvar[0..myvar.length() - 2]
but unfortunately, it does not work: it gives no visible error, but also makes no changes to the myvar.
What do I miss? Maybe you can't use variables as part of the subscript operator?
Maybe there is a better way to cut those end-of-line characters? I guess I could use regexp, but to me, that sounds like overkill.
Thanks!
Thanks to ernset_k, found the answer!
The problem was that the subscript operator includes the upper bound. In my original scenario, last 2 characters where not printable and that's why I did not see the difference while debugging. I had to use "myvar.length()-3".
But as indicated by ernest_k, instead of calculating the length of the string you need to trim, we can also use other options of the operator. All these examples work as expected:
println myvar[0..myvar.length() - 3]
println myvar[0..<-2]
println myvar[0..-3]

Delphi - Formating a multiple %s string with one argument

When I try to format a string such as '%s%s' using a line of code like so:
format('%s%s', [x]);
I get an exception because you can't have multiple '%s' without using an array with the same amount of arguments such as:
format('%s%s', [x,x]);
However, I don't know how many '%s' I will have to format and therefore I don't know how long the array would have to be. I also only want '%s' assigned to only 1 value.
Is there a way in which you can use multiple '%s' and assign them all to the same index?
As described in the documentation you can use an index specifier to identify the argument by a zero based index. The index specifier is written immediately after the % and is followed by a :.
Your example would be:
Format('%0:s%0:s', [x])
MyStr := StringReplace('%s%s', '%s', x, [rfreplaceALL]);

FitNesse: Variable assignment and simple arithmetic

According to the user guide it is possible to assign values to variables and then perform simple arithmetic.
Imagine I have fixture designed to take an element on the page and extracting the numerical value as a Double (i do this now using the HSAC Slim BrowserTest fixture and my own code)
|script |numbers extraction |
|$testval1=|numeric value of |element1 | |
|$testval2=|numeric value of |element2 | |
Running this gives me something like:
|script |numbers extraction |
|$testval1<-[20.04]|numeric value of |element1 ->[€ 20,04] | |
|$testval2<-[5.1] |numeric value of |element2 ->[€ 5,1] | |
Now say I want to compare the sum of the two doubles with the numeric value of a third element:
|script|numbers extraction |
|check |numeric value of |element3|{=${ ${testval1} + ${testval2} =}|
No matter what combination of parentheses and dollar-signs I use in the last cell, I always get 'invalid expression'.
${= $testval1 + $testval2 =} invalid expression: $testval1 + $testval2
{${=$testval1 + $testval2 =}} {invalid expression: $testval1 + $testval2}
${=${testval1} + ${testval2} =} [invalid expression: undefined variable: testval1 + undefined variable: testval2]
${= !-$testval1-! + !-$testval2-! =} invalid expression: $testval1 + $testval2
${= !-${testval1}-! + !-${testval2}-! =} invalid expression: ${testval1} + ${testval2}
Running the last line (without parenthesis around testval1 and testval2) returns:
|check|numeric value of|element3 ->[€ 25.14]| [25.14] expected [invalid expression: $testval1->[20.04] + $testval2->[5.1]] |
Unfortunately you can can't do what you are looking for. The variables you assign the value of the elements to are actually SLIM symbols, and not variables at the wiki level. If you scroll a bit down on the user guide page you linked to in the question you will find a section called "Difference between variables and SLIM symbols":
Variables are evaluated at render time, before the test executes. This allows for values to be set based on page hierarchy and other things that are purely inputs to the tests.
Symbols only exist at execution time. They can be changed at runtime, so are distinct from variables, which cannot.
I find the three types of variables in FitNesse/SLIM are confusing to people and their different usage, syntax and possibilities cause many issues. My understanding is:
Markup variables (aka wiki variables). For instance ${myVar}, defined using !define. They get their value at page render time, so even before a test is started, so you see their value when you browse to a wiki page, and only in the page's source do you see it is a variable. These can be used in markup expressions, which is what you are trying to do in the question.
Scenario parameters. For instance #{myVar} (or #myVar), defined in the first row of a SLIM scenario table. These are the 'formal parameters' to the scenario, which get their actual value based on the invocation of the scenario (i.e. each usage of the scenario, either from a script table, other scenario or row in a decision table defines their value). They get their value at the start of a test, before its first action is performed. You see the variable when you look at the scenario table that defines it. (When you use the 'table template' table type defined by hsac-fitnesse-plugin (which is included in hsac-fitnesse-fixtures project baseline) you don't need to define the variable names in the first row of the table, they are automatically found based on their occurrence (e.g. #{myVar}) inside the table.)
SLIM symbols. For instance $myVar, they are assigned their value using $myVar=. These are 'runtime variables' that get their value during test execution, they are global to a test suite and their value might be changed during test execution. These are the only kind of variables that can get their value from a property obtained from the 'system under test', and they are the variables you are using in your question's tables. They are actually references to objects inside the SLIM process so fixtures might change the internal state of the object the variable refers to, without this change showing in the wiki representation of the variable (which is just the object's toString() result at time of last assignment).
P.S. The conversion of a string to a double does not require a custom fixture (like your numbers extraction) when you using the hsac-fitnesse-fixtures. You could just use the convert to double method of the library's string fixture.
You seem to be using browser test, this is an HSAC installation I take it? Please mention this in the question as HSAC is a FitNesse fixture.
Anyway, removing the curly brackets should do the trick. With curly brackets it is expecting a global variable, those that are implemented using !define var {foo}
When using variables that are locally defined such as with |$bar=|value of|foo| have to be called in the test using the variable without curly brackets.
|$bar=|value of|foo|
|enter|$bar|as|inputField|
Find more stuff on HSAC usage here: https://github.com/fhoeben/hsac-fitnesse-fixtures/wiki/2.-Slim-Fixtures
Sidenote:
Then there are also table templates that use #var or #{var}, where the use of #{var} is preferred because #{var} will look for the column var and #var will accept a column v or va, if you happen to implement that. Using curly brackets here ensures the full variable name is used.

Why are redundant parenthesis not allowed in syntax definitions?

This syntax module is syntactically valid:
module mod1
syntax Empty =
;
And so is this one, which should be an equivalent grammar to the previous one:
module mod2
syntax Empty =
( )
;
(The resulting parser accepts only empty strings.)
Which means that you can make grammars such as this one:
module mod3
syntax EmptyOrKitchen =
( ) | "kitchen"
;
But, the following is not allowed (nested parenthesis):
module mod4
syntax Empty =
(( ))
;
I would have guessed that redundant parenthesis are allowed, since they are allowed in things like expressions, e.g. ((2)) + 2.
This problem came up when working with the data types for internal representation of rascal syntax definitions. The following code will create the same module as in the last example, namely mod4 (modulo some whitespace):
import Grammar;
import lang::rascal::format::Grammar;
str sm1 = definition2rascal(\definition("unknown_main",("the-module":\module("unknown",{},{},grammar({sort("Empty")},(sort("Empty"):prod(sort("Empty"),[
alt({seq([])})
],{})))))));
The problematic part of the data is on its own line - alt({seq([])}). If this code is changed to seq([]), then you get the same syntax module as mod2. If you further delete this whole expression, i.e. so that you get this:
str sm3 =
definition2rascal(\definition("unknown_main",("the-module":\module("unknown",{},{},grammar({sort("Empty")},(sort("Empty"):prod(sort("Empty"),[
], {})))))));
Then you get mod1.
So should such redundant parenthesis by printed by the definition2rascal(...) function? And should it matter with regards to making the resulting module valid or not?
Why they are not allowed is basically we wanted to see if we could do without. There is currently no priority relation between the symbol kinds, so in general there is no need to have a bracket syntax (like you do need to + and * in expressions).
Already the brackets have two different semantics, one () being the epsilon symbol and two (Sym1 Sym2 ...) being a nested sequence. This nested sequence is defined (syntactically) to expect at least two symbols. Now we could without ambiguity introduce a third semantics for the brackets with a single symbol or relax the requirement for sequence... But we reckoned it would be confusing that in one case you would get an extra layer in the resulting parse tree (sequence), while in the other case you would not (ignored superfluous bracket).
More detailed wise, the problem of printing seq([]) is not so much a problem of the meta syntax but rather that the backing abstract notation is more relaxed than the concrete notation (i.e. it is a bigger language or an over-approximation). The parser generator will generate a working parser for seq([]). But, there is no Rascal notation for an empty sequence and I guess the pretty printer should throw an exception.

Resources