Inline Lua
Lua scripting may be used "inline" in Rainmeter. This is done by using a call to a Lua script as a [SectionVariable], referencing the Script measure containing the ScriptFile
option for the .lua file. The value returned by Lua will "replace" the inline Lua section variable where it is used.
These may be used anywhere a [SectionVariable] is allowed. This can be in almost any option in measures or meters, and any bangs in an action.
As with any [SectionVariable], these will be resolved, in this case executed, when the skin is loaded, and on each update of the measure or meter containing them. As with any [SectionVariable], DynamicVariables=1
must be used on any measure or meter containing them.
Calling a Function()
Functions in a Lua script may be executed "inline", by using a call to a single function() within the Lua script, with optional parameters.
The Lua function will be executed, using the provided parameters, and the single number or string value returned by the function() in the Lua script will replace the [Section Variable] where it is used.
The way to consider this is as a simple [SectionVariable], that works just like any other [SectionVariable]. The only difference is that a [SectionVariable] is used to reference a number or string value returned by some measure in the skin, and this is used to reference a number or string value returned by some function() in the Lua hosted by a Script measure in the skin.
As the inline Lua can reference any function() within the .lua file, and can pass parameters specific to where the inline Lua is used, a single Script measure, and single .lua file, can host any number of functions, and a single function can return context specific values.
Note that this is not designed to execute stand-alone Lua statements, but is used to execute a function() code block in the Lua script file that returns a value. For example:
function SomeFunction(arg1, arg2) |
The syntax of an inline Lua call to a function() is:
[&ScriptMeasureName:LuaFunctionName(numberParameter, 'stringParameter', ...)]
Examples:
[&MeasureMyScript:GetCharacterInString('Rainmeter', 5)]
[&MeasureMyScript:ConvertTemperature([&MeasureCurrentTemp], 'C')]
The types of parameters that can be passed to the Lua function() are:
Number | Any number literal, formula or variable that resolves to a number. | |
String | Any 'string' literal, or variable that resolves to a string, enclosed in 'single quotes' or "double quotes". | |
Boolean | One of either true or false . | |
nil | Special type meaning "nothing". Often used to differentiate between having some data or no data. |
Retrieving a Variable
Inline Lua can also be used to simply retrieve the current value of any variable that that you may set in the Lua, either in Update() or in a Function() that you call with !CommandMeasure or other inline Lua.
This can greatly simplify getting any number of variable values that you may set in Lua. You don't need a return
for each of them, just have your Lua set variable values, and have some inline Lua in measures or meters go "get them".
Example:
[&MeasureMyScript:myVariable]
Nested Variables in Rainmeter
It must be remembered that the entire inline Lua functionality is contained within a [SectionVariable]. This means that any #Variable# or other measure [SectionVariable] you use in the parameters to the Lua function will cause "nesting" of variables within variables. The standard way of expressing #VariableName# and / or [MeasureName] in Rainmeter cannot be "nested", and won't work.
This is solved by using the alternative Nesting Variables syntax in any inline Lua.
That link has a full explanation, but in short:
[#VarName] | Replaces: #VarName# | |
[&MeasureName] | Replaces: [MeasureName] | |
[$MouseVar] | Replaces: $MouseVar$ |
In general, anything useful that you do with this functionality is going to entail passing variables of one form or another to the Lua function, and just always using the Nested Variables syntax with any inline Lua will save a lot of frustration and confusion.
Inline Lua Notes
DynamicVariables=1
MUST be set on any measures or meters where inlineLua is used.
String values in parameters must be explicitly passed as strings to the Lua function, by enclosing them in 'single quotes' or "double quotes". Numbers and formulas are required to be passed without quotes, but any string passed without quoting will be seen by the Lua as a Lua variable name with a nil value, and will fail. Like other numeric options in Rainmeter, formulas are also required to start with a (
.
The Lua boolean
data type may be passed to the Lua function with true
or false
, and any return
to Rainmeter of a boolean true
will be 1 and false
will be 0.
myTable[index]
, may not be directly used in a parameter to the Lua function, you will need to pass the table name and the index number or string as separate parameters and use them to access the table in Lua. However, the Lua may return a single value from a table with return myTable[index]
. The TranslateDay example below demonstrates this.
The Lua nil
data type, indicating that a value doesn't exist, may be used in a parameter, but not as a return type to Rainmeter. In some cases, the boolean
value of false
may be used to indicate NOT, in place of nil
.
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.
Examples
The best way to explain inline Lua is to disassemble a few simple examples:
SimpleLua
SimpleLua.ini:
[Rainmeter] |
So we have a pretty simple skin, which gets the name of the user account logged into Windows with the SysInfoType=USER_NAME
option on the SysInfo plugin measure [MeasureGetUserName].
And we have a Script measure, [MeasureScript], which will load and make available the Lua script file SimpleLua.lua. Note that since we don't use or need an Update() function in the Lua, we can just disable this Script measure. There is nothing it can or should return on each update of the measure itself.
Then in our [MeterWelcome] String meter, we use an inline Lua section variable. Let's look at the construction of that.
Text=[&MeasureScript:GetWelcome('[&MeasureGetUserName]')]
First, we reference our Script measure name with [&MeasureScript
. That is followed with a :
colon, to indicate a modifier, as with any [SectionVariable]. Note that we are using the Nested Variables syntax to reference our Script measure, as we are going to be "nesting" another [SectionVariable] in this.
Then we reference the function() in the Lua script file that we want to call. In this case it is a function called GetWelcome()
, which requires a 'string' parameter.
We want to use the value of our [MeasureGetUserName] measure as the 'string' parameter to the Lua function, so we use the Nested Variables syntax to pass the value of that measure to the Lua as a 'string', with the section variable ('[&MeasureGetUserName]')
. Then we end the initial section variable, our inline Lua, with a ]
square bracket.
SimpleLua.lua:
function GetWelcome(inArg) |
If we pretend that the value of our [MeasureGetUserName] measure is the string RainmeterTeam
, then the function GetWelcome('RainmeterTeam')
will be executed in the Lua script.
The Lua script uses the current hour to choose a greeting appropriate for the time of day, and constructs a string to return as the section variable value to the String meter in Rainmeter. That is done with the return
function in Lua, as return welcomeText
. What would be seen in the skin at nine in the morning is "Good Morning, RainmeterTeam".
FlipCoin
This example is a little more complex, showing how we can combine the use of an "action" in the Rainmeter skin, with inline Lua section variables, to get a result "on demand", and how we can just retrieve variables with Inline Lua, instead of calling a function().
With this one, we will just explain using ;comments in the Rainmeter code, and --comments in the Lua code, as it might be easier to follow the explanation in context.
FlipCoin.ini:
[Rainmeter] |
FlipCoin.lua:
math.randomseed(tonumber(tostring(os.time()):reverse():sub(1,6))) |
TranslateDay
This example adds a few more pieces, showing how we can use both [&SectionVariables] and [#Variables] (remember our Nesting Variables syntax!) embedded in the inline Lua, and how to pass multiple parameters to the Lua function, both number and 'string'.
TranslateDay.ini:
[Rainmeter] |
TranslateDay.lua:
function Initialize() |
In these examples, we concentrated on using the inline Lua to set Text options on a String meter, as they are easy to understand and demonstrate. Remember though, that inline Lua can be used on any measure or meter option, and in any bang. Anywhere that a [SectionVariable] can be used. So this might be X or FontColor on a String meter, Drive on a FreeDiskSpace measure, some value in an ActionTimer measure, the uses are only limited by how clever you are.
Download Examples
You can download the above examples, and a few others, as a .rmskin.