It is currently March 29th, 2024, 12:28 am

[BUG?]Multiple execution of inline Lua when using it in various meter otions

Report bugs with the Rainmeter application and suggest features.
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

[BUG?]Multiple execution of inline Lua when using it in various meter otions

Post by death.crafter »

When using inline lua in options like color and co-ordinates, the function is executed twice.

Example:

Lua:

Code: Select all

i=1
function Example(meter)

    print('looped '..i..' for '..meter)
    i=i+1

end
Skin:

Code: Select all

[Rainmeter]
Update=-1
AccurateText=1

[Lua]
Measure=Script
ScriptFile=Example.lua

[MeterString]
Meter=String
X=[&Lua:Example('[#CURRENTSECTION]')]
Text=Letter is
FontSize=20
FontColor=FEFEFE
DynamicVariables=1

[MeterShape]
Meter=Shape
Shape=Rectangle 0,30,20,20,10 | Stroke Color [&Lua:Example('[#CURRENTSECTION]')]
DynamicVariables=1
Here is a snap of the log:
Screenshot 2021-06-16 214102.png

While some options have this effect, some don't. For example if you use OnUpdateAction=[&Lua:Example()], it will execute only once.

Snap with OnUpdateAction:

Screenshot 2021-06-16 214359.png

Is this normal behavior or a bug?

P.S.: Original functions are different but show the same behaviour.
You do not have the required permissions to view the files attached to this post.
from the Realm of Death
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: [BUG?]Multiple execution of inline Lua when using it in various meter otions

Post by jsmorley »

The issue comes down to how things are "parsed" when the skin is first read after it is loaded or refreshed. Section variables in options in measures and meters are "resolved" when they are "read". Resolving those Inline Lua section variables causes the Lua to execute the function.

So any of the Inline options like those calls to Lua will actually be "executed" when they are read, which will happen when the meters are first evaluated. Then they will be executed a second time, during the first update of the skin.

So even though you have Update=-1 in [Rainmeter], those kinds of Inline operations will be executed twice.

I think you would need to have the Lua ignore the first call to the function. More or less set i = 0 and then test for i > 0 in the loop.

https://docs.rainmeter.net/manual-beta/lua-scripting/inline-lua/
Important Final Note

Any inline Lua used in options in measures or meters are resolved when the skin is first read and created on load or refresh. This is the same for all [SectionVariables] in Rainmeter.

During this "initialization" phase of the skin, before the first actual "update" of the skin, the value of all measures will be set to an initial numeric value of 0, and if applicable, a string value of "". This will normally be transparent, as before any "result" of the inline Lua is "used", before the skin is "drawn" for the first time, all measures and meters will have been updated and the correct and expected results will happen. However some care should be taken to ensure that a one-time initial value of 0 being passed to your Lua doesn't cause any logic or formula errors.

In addition, the Initialize() function in a Lua script will only be executed during the first update cycle of the skin. This means that if you are defining and setting some default values for variables in Initialize() in your Lua, those values will not be visible before the first skin update, which will be after any inline Lua in measures or meters are first run. This may cause "nil" values to be seen and result in errors.

In many cases, this can be resolved by defining and setting these variables in the global scope of the Lua script, outside of any function block. This global scope will be executed during the initialization phase of the skin, and the values will be immediately available. The global scope of Lua has not been much needed before in Rainmeter, but with inline Lua it can be valuable.

Again, in both cases, this all will generally be transparent and of no consequence, since by the time the skin is first drawn, at the end of the first skin update, all will be well. This issue should be kept in mind however, if you find you are getting single initial error messages in the log.

Inline Lua used in bangs in actions in the skin will only be executed when the action is executed, and so will not display this behavior. They simply can't be executed before the first update of the skin.
So the behavior will happen when an Inline Lua section variable is used in an "option" on any measure or meter, but NOT when the Inline Lua section variable is used in a "bang" in an "action". Section variables in "actions" are not "resolved" when they are "read", since it is not needed to initially "create" the measure or meter in question. In that case they are only resolved when the action is triggered.

P.S. I think you will find that OnUpdateAction=[&Lua:Example()] doesn't execute at all, since it is an invalid / error call to the function that is expecting a value to be passed to it to populate the variable "meter" in the Lua. You can't specify an "argument" in the definition of a Lua function, and then just not send one. Lua will just bark at you in the log.
User avatar
Yincognito
Rainmeter Sage
Posts: 7029
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [BUG?]Multiple execution of inline Lua when using it in various meter otions

Post by Yincognito »

As jsmorley pointed out, yes, this is normal - I encountered this too when working in the Rainmeter-Lua combo. However, this is not a problem, since most of the times the execution at refresh time will be more or less "invalid" from a functional point of view, due to parameters or the environment needed for a practical execution not yet being set. If this is still a problem (as it was in my case, where although not breaking anything I still got an error at start), you can easily initialize the desired parameters or global variables in the Initialize() funtion in Lua.

One other thing that I personally never do: using inline Lua functions in an option. I never do that, for me inline Lua functions follows the "bang principle", in that it's an action that needs to take place and not a variable to retrieve. If you want to use Lua in options like you showed earlier, better directly retrieve the desired variable using [&Script:SomeLuaVariable] instead, and execute the needed action / function that sets the variable prior to that somewhere.

P.S. Another choice would be to use custom options (i.e. parameters) in the Lua script measure and just grab the result of the Update() when the measure updates.

P.S.S. When I mentioned "use Lua in options like you showed earlier" I meant functions with no return value (like yours is) - in some languages they are called "procedures", to differentiate them from "functions" that return some value. I guess for functions returning something, using them in options like X=[&Script:SomeFunction(SomeParameters)] would make sense, but even so I'd still choose getting the variable directly from Lua in such cases, as it makes much more sense.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Re: [BUG?]Multiple execution of inline Lua when using it in various meter otions

Post by death.crafter »

Yincognito wrote: June 16th, 2021, 6:18 pm
While at it, is there a way to include an [...](pair of square brackets with string inside) in inline lua? It gets cancelled unless I use a #. And I want to take in a regex.
from the Realm of Death
User avatar
Yincognito
Rainmeter Sage
Posts: 7029
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [BUG?]Multiple execution of inline Lua when using it in various meter otions

Post by Yincognito »

death.crafter wrote: June 16th, 2021, 6:57 pm While at it, is there a way to include an [...](pair of square brackets with string inside) in inline lua? It gets cancelled unless I use a #. And I want to take in a regex.
Maybe I don't understand exactly what you mean, because for me it works:

Code: Select all

function Sum(a, b)
  local c = '["something"]'
  print(c)
  return a + b
end

Code: Select all

[Variables]

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
BackgroundMode=2
SolidColor=47,47,47,255

---Measures---

[MeasureScript]
Measure=Script
ScriptFile=#@#Script.lua
UpdateDivider=-1

[MeasureCalc]
Measure=Calc
Formula=(7+3)
UpdateDivider=-1
DynamicVariables=1

---Meters---

[MeterTest]
Meter=STRING
FontFace=Consolas
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
FontSize=16
AntiAlias=1
Text="Script = [&MeasureScript:Sum(7,3)]#CRLF#Calc   = [MeasureCalc]"
UpdateDivider=-1
DynamicVariables=1
This works without the double quotes too. Maybe giving a simple example of your not working attempt would clarify what you mean.

Other than that, regexes - unless in a library - don't work in Lua as they are replaced by patterns (a similar but less powerful method).
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Re: [BUG?]Multiple execution of inline Lua when using it in various meter otions

Post by death.crafter »

Yincognito wrote: June 16th, 2021, 7:17 pm Maybe I don't understand exactly what you mean, because for me it works:

Code: Select all

function Sum(a, b)
  local c = '["something"]'
  print(c)
  return a + b
end

Code: Select all

[Variables]

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
BackgroundMode=2
SolidColor=47,47,47,255

---Measures---

[MeasureScript]
Measure=Script
ScriptFile=#@#Script.lua
UpdateDivider=-1

[MeasureCalc]
Measure=Calc
Formula=(7+3)
UpdateDivider=-1
DynamicVariables=1

---Meters---

[MeterTest]
Meter=STRING
FontFace=Consolas
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
FontSize=16
AntiAlias=1
Text="Script = [&MeasureScript:Sum(7,3)]#CRLF#Calc   = [MeasureCalc]"
UpdateDivider=-1
DynamicVariables=1
This works without the double quotes too. Maybe giving a simple example of your not working attempt would clarify what you mean.

Other than that, regexes - unless in a library - don't work in Lua as they are replaced by patterns (a similar but less powerful method).
Oops! Sorry you had to go this far. What I meant was using [&Lua:SomeFunc('someArg', '[someString]')]. I found an work around by using a variable. But thanks for the reply.😀
from the Realm of Death
User avatar
Yincognito
Rainmeter Sage
Posts: 7029
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [BUG?]Multiple execution of inline Lua when using it in various meter otions

Post by Yincognito »

death.crafter wrote: June 16th, 2021, 7:36 pm Oops! Sorry you had to go this far. What I meant was using [&Lua:SomeFunc('someArg', '[someString]')]. I found an work around by using a variable. But thanks for the reply.😀
No problem, this is more or less how my basic test skin (stored and used when I need it) looks like, I only got so far as to write a print() line into it, that's all. :D
As for using [&Lua:SomeFunc('someArg', '[someString]')], why not passing just the string to Lua, like [&Lua:SomeFunc('someArg', 'someString')], and then add the square brackets to it in Lua? Like:

Code: Select all

function SomeFunc(a, b)
  local bwithbrackets = '[' .. b .. ']'
  ...
end
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Re: [BUG?]Multiple execution of inline Lua when using it in various meter otions

Post by death.crafter »

Yincognito wrote: June 16th, 2021, 7:47 pm No problem, this is more or less how my basic test skin (stored and used when I need it) looks like, I only got so far as to write a print() line into it, that's all. :D
As for using [&Lua:SomeFunc('someArg', '[someString]')], why not passing just the string to Lua, like [&Lua:SomeFunc('someArg', 'someString')], and then add the square brackets to it in Lua? Like:

Code: Select all

function SomeFunc(a, b)
  local bwithbrackets = '[' .. b .. ']'
  ...
end
It is a way but not useful for my usecase. As regex patterns may include [...] in the middle of the string. And 'gsub'ing another character is not an option. So a variable is the only possible way.

Thanks again.
from the Realm of Death
User avatar
Yincognito
Rainmeter Sage
Posts: 7029
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: [BUG?]Multiple execution of inline Lua when using it in various meter otions

Post by Yincognito »

death.crafter wrote: June 16th, 2021, 7:52 pm It is a way but not useful for my usecase. As regex patterns may include [...] in the middle of the string. And 'gsub'ing another character is not an option. So a variable is the only possible way.

Thanks again.
Ah, ok then. :thumbup:
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth