It is currently December 3rd, 2021, 6:18 am

Help with using lua for writing variables

Discuss the use of Lua in Script measures.
psatyarthi
Posts: 5
Joined: May 11th, 2021, 4:55 pm

Help with using lua for writing variables

Post by psatyarthi »

Whenever I want to write a variable to a skin, I use the !SetVariable bang along with the !WriteKeyValue bang and then update and redraw that specific meter to avoid having to refresh the whole skin to load the changes.
I currently have a skin that writes variables to a notes skin using the InputText plugin using the following lua code:

Code: Select all

function AddItem()
	local input, crlf = SKIN:GetVariable('Item0'):gsub("\r\n", "#*CRLF*#")
	if input ~= "" then
		for i = 1, 15 do
			SKIN:Bang('[!WriteKeyValue Variables Item'..(i+1)..' """'..SKIN:GetVariable('Item'..i):gsub("\n", "#*CRLF*#")..'""" "#@#Notes\\Notes.txt"]')
		end
		SKIN:Bang('[!WriteKeyValue Variables Item1 """'..input..'""" "#@#Notes\\Notes.txt"][!Refresh]')
	end
The notes skin has 16 items (Item1, Item2, Item3, and so on) and what the script does is that it shifts the contents of each item to the next item and finally writes the user input value to the first item and refreshes the skin to load the changes.
I tried adding the !SetVariable bang after !WriteKeyValue as
SKIN:Bang('[!SetVariable Item'..(i+1)..' """'..SKIN:GetVariable('Item'..i):gsub("\n", "#CRLF#")..'"""]')
But what it did was write the value of Item2 to all the items and the value of user input to Item1.
Is there any way to do this correctly?
MikeG621
Posts: 83
Joined: March 18th, 2013, 1:59 pm

Re: Help with using lua for writing variables

Post by MikeG621 »

You're have the right idea, the problem is the loop itself. The way it is right now, it does the following:

Item1 > Item2
Item2 > Item3
Item3 (which now equals Item2) > Item4
Item4 (which now also equals Item2) > Item5
...
Input > Item1

Run the loop backwards, from 15 to 1.
User avatar
jsmorley
Developer
Posts: 22416
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Help with using lua for writing variables

Post by jsmorley »

I would consider a different format for the call to SKIN:Bang() as well.

You don't need, and truth be told, don't want, to send the entire bang as a single string. Formatting that single string can get VERY complicated and VERY hard to read / debug.

Here is a Lua script that shows the two ways you can format a SKIN:Bang() call.

Skin:

Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1

[Variables]

[Lua]
Measure=Script
ScriptFile=Test.lua
Disabled=1

[MeterOne]
Meter=String
FontSize=11
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=LogIt1
LeftMouseUpAction=[&Lua:LogIt1()]
DynamicVariables=1

[MeterTwo]
Meter=String
Y=2R
FontSize=11
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=LogIt2
LeftMouseUpAction=[&Lua:LogIt2()]
DynamicVariables=1
Lua:

Code: Select all

function LogIt1()

	SKIN:Bang('[!Log Four][!Log Three]')

end

function LogIt2()

	SKIN:Bang('!Log', 'Two')
	SKIN:Bang('!Log', 'One')

end
While you can't "stack up" bangs in a single call with the preferred second approach, you can't / don't need to use the [] brackets, and the formatting is a lot more straightforward in my view. Instead of a single long string that you must carefully construct to deal with a ton of single quotes and .. appends to jump in and out of literal and variable values, you just format it as SKIN:Bang('!BangName', 'Parm1', 'Parm2').

Probably the biggest advantage is that this entirely eliminates the need to worry about passing "double-quotes" to Rainmeter to help Rainmeter parse the bang out into the various parameters. Basically double-quotes are just not needed. The Lua SKIN:Bang() function will take care of separating the parameters properly for Rainmeter. Let it do the work.

Code: Select all

function LogIt1()

	SKIN:Bang('[!Log "Item Four"][!Log "Item Three"]')

end

function LogIt2()

	SKIN:Bang('!Log', 'Item Two')
	SKIN:Bang('!Log', 'Item One')

end

Code: Select all

function LogIt1()

	i4 = 'Four'
	i3 = 'Three'
	SKIN:Bang('[!Log "Item '..i4..'"][!Log "Item '..i3..'"]')

end

function LogIt2()

	i2 = 'Two'
	i1 = 'One'
	SKIN:Bang('!Log', 'Item '..i2)
	SKIN:Bang('!Log', 'Item '..i1)

end
While this is a very simple example indeed, it is already way more complicated than I like to use the first method. Ick... You'd better hope you have a text editor that can warn you of mismatched quotes in the context of Lua.

While the single-string approach will still work, it is "deprecated" in favor of the new method...

https://docs.rainmeter.net/manual-beta/lua-scripting/#Bang
User avatar
Yincognito
Rainmeter Sage
Posts: 4108
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Help with using lua for writing variables

Post by Yincognito »

psatyarthi wrote: June 14th, 2021, 1:14 pmI currently have a skin that writes variables to a notes skin using the InputText plugin using the following lua code [...]
Is there any way to do this correctly?
A bit late to reply (not present much in this section of the forum), but if you already use Lua to do this instead of native Rainmeter code, why not directly write to the variables file using Lua's own functions and a "lines" table, e.g. assert(io.open(outputfile, 'w'),'some fail to open file message'), file:write(table.concat(lines, '\n')) and file:close()? I might be wrong, but to me it seems it would be easier than trying to figure out how to escape everything by using the Lua-Rainmeter "bridge"... :confused: