Expressions and LuaXP Functions
-
No equivalent function, but the name is available as
getEntity( .... ).name
-
LibraSunwrote on Mar 17, 2021, 10:57 PM last edited by LibraSun Mar 17, 2021, 6:58 PM
I'll try that, and encourage you to add that to drop-down.
Also, meanwhile, I'm getting a (null) response with:
getEntity( "vera>device_337" ).attributes.x_vera_device.device_number
which IMHO ought to be(number) 337
, no?
EDIT: Solved with a hard refresh of browser! Weird. -
LibraSunwrote on Mar 18, 2021, 1:56 PM last edited by LibraSun Mar 18, 2021, 11:56 AM
Is there a way to modify the following such that ALL whitespace gets replaced with the underscore (i.e. make the RegExp a 'global')??
replace(msgText, "\s", "_")
-
toggledbitswrote on Mar 18, 2021, 2:44 PM last edited by toggledbits Mar 18, 2021, 10:50 AM
I'm going to enhance the following functions to work like this. I use the "old school" *nix notation for optional parameters by enclosing in square brackets, so where you see that below, those parameters are optional.
match( string, pattern [ , num [ , flags ] ] )
- Find pattern in string. If num is given and the pattern contains regexp groups, the function will return the numth matched group (e.g.match( "The rain in Spain", "r(ai)n", 1 )
returns "ai"; zero is always the full match, and thus the default). If flags is given as "i", a case-insensitive match will be performed.find( string, pattern [ , flags ] )
- Returns the position (0-based) of the matched pattern in string. Returns -1 if the pattern is not matched. The flags have the same meaning as inmatch()
.replace( string, pattern, replacement [ , flags ] )
- Replaces the first occurrence (by default) of pattern in string with replacement. If specified, flags have the same meaning as inmatch()
, plus the additional flag "g" (for global) modifies the behavior to replace all instances of the pattern in string (if needed, multiple flags can simply be concatenated, as in "ig" for case-insensitive + global). The replacement string uses$
as a special pattern lead-in, so $` yields the portion of string before the matched pattern,$'
yields the portion of string after the matched pattern,$&
is the entire matched substring,$n
inserts the match of the nth group in pattern, and$$
yields "$" (self-escape).
Basically, all of this follows JavaScript semantics, which provides the underlying implementation.
-
LibraSunwrote on Mar 18, 2021, 3:50 PM last edited by LibraSun Mar 18, 2021, 11:51 AM
Will MSR still interpret the literal
\n
as a line break (equivalent of<br>
in HTML) in text strings? Or is it going to be escaped differently (if used at all)? -
In what context?
-
For example, I like to pre-format the messages I send via SMTP, and routinely define:
msgText := "Hello from Vera. \n\n I see you are running MSR! \n \n Sincerely, Vera"
-
Yes, will happen. It raises priority on another "to-do" item for the parser, which has rather "blunt" string lexing at the moment. I've got a more formal version working now, but I want to play with it a little more before I commit it to MSR.
-
You make it, I break it.
-
@toggledbits I can't seem to concoct a meaningful example of
DO
..DONE
, since I'm probably not grasping its intended function within the MSR framework.
Does it have a use here, and if so, how would such a statement look? Thanks! -
toggledbitswrote on Mar 25, 2021, 9:13 PM last edited by toggledbits Mar 25, 2021, 5:28 PM
do...done
is intended to help thefirst
andeach
statements (but can be used anywhere, really).- the
each
andfirst
statements operate only on a single expression; do...done
encapsulates multiple expressions (separated by comma), but looks like a single expression toeach
andfirst
;- The result of a
do...done
statement is the value of the last expression executed within it.
Here from my own configuration is an example:
each detector in leak_detectors: do d=getEntity(detector), d.attributes.arming.state && d.attributes.binary_sensor.state ? d.id : null done
There's a separate expression called
leak_detectors
that provides an array of leak detector entity IDs (canonical, across controllers, of course). Theeach
statement iterates over each of them. Thedo...done
encapsulates two expressions: the fetch of the entity stored to a local variable in the first, and then uses that local variable twice in the second expression. The result of thedo...done
is the result of the last expression, which is the detector's ID if it is armed and tripped, or null otherwise. With aneach
expression, anynull
s do not appear in the final array.The idea should be familiar from RFV, although the construction is a little different: it's a loop over a list of known leak detectors and builds an array of those that are armed and in alarm (if any, hopefully not).
- the
-
For a lark, I defined a test variable as:
testObj = { a:5, b:2, c:"cat"}, each num in values(testObj): r = isNaN(num) ? " That's all!" : "Libra owns " + num + " cats"
which spits out:
["Libra owns 5 cats","Libra owns 2 cats","Libra owns cat cats"]
while I had actually expected (due to the
NaN
:["Libra owns 5 cats","Libra owns 2 cats"," That's all!"]
Also, am noticing that the Expression 'value' windows always contract to their initial (1.25-line tall) height, rather than remember what the user enlarged them to.
Are both of these "expected behaviors" in MSR??
-
toggledbitswrote on Mar 25, 2021, 10:07 PM last edited by toggledbits Mar 25, 2021, 6:17 PM
The
isNaN()
is a yes... unlike JavaScript, the lexpjsisNaN()
literally tests to see if the argument isNaN
, which"cat"
is not. You'd need to write your test asr = isNaN( int( num ) ) ? ...etc.
I can't store your selected/custom field sizes. I haven't poked harder into getting it to auto-size. I've done that before, but for some reason it isn't working and I haven't bothered to track it down yet.
-
I'm back with another whopper. Variables allow multiple comma-separated statements, like:
b = 3, c = b + 2 // yields 5
but go bonkers when you try:
testArr = [1,2,3], testArr[1] = 5 // parsing error (similar result with Objects)
By design?
-
Yes, assignment to simple variables only; the left side of an assignment can only be an identifier (right now).
-
LibraSunwrote on Mar 26, 2021, 1:59 AM last edited by LibraSun Mar 25, 2021, 10:00 PM
This one's got me stumped now:
testCalc
=each num in [4,5,6]: do [num, num+1, num+2] done
yields:
[[4,5,6],[4,5,6],[4,5,6]]
instead of:
[[4,5,6],[5,6,7],[6,7,8]]
Or have I stumbled again? (I do realize the DO..DONE is a red herring, but removing it doesn't change the result.)
-
Nope, that's clearly wrong. Not hard to fix. I found a spot where the executive was rewriting a variable rather than returning a copy, specific to arrays, so this particular test would hit it, any other data type would not. Good catch!
-
Already posted as a PR with much-simplified rendering of underlying formula.
-
OK. It may or may not make today's build. I'm still testing other parts of my parser changes.
-
LibraSunwrote on Mar 27, 2021, 2:31 AM last edited by LibraSun Mar 26, 2021, 10:32 PM
Here's an odd response, to an expression defined (in 21085) as:
testStr = [ "cat", " dog", "idle ", " jump " ], trim(testStr)
// result = (string) "cat, dog,idle , jump"
// note (a) the lopsided leftover spaces, (b) concatenation into a single string, (c) type coercion into String
// unsure whethertrim()
ought even accept Array as input?
55/126