It is currently April 20th, 2019, 11:13 am

Tips & Tricks Thread

Discuss the use of Lua in Script measures.
User avatar
jsmorley
Developer
Posts: 19178
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Tips & Tricks Thread

jsmorley » August 7th, 2011, 12:59 pm

Thought I would stat a thread where simple little "tips and tricks" could be added as posts, without starting a whole new thread for each one. This should be for reasonably specific snippets or ideas that you find useful in using Lua with Rainmeter, or just in using Lua. Sort of a little "knowledge base" for the clever stuff you folks come up with. If you think about it, change the "subject" of your reply / post to be something about it, to help when folks are searching the forums for a solution.

Do NOT post any "help me" messages in this thread, or they will be deleted without comment. Make a new thread in the main "Lua & Rainmeter" topic instead.
User avatar
jsmorley
Developer
Posts: 19178
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Running Lua scripts on demand

jsmorley » August 7th, 2011, 1:00 pm

For instance:

There is another clever way of having a Lua script run on demand, rather than using disabled/enabled or setting UpdateDivider=-1. Poiru and I were talking about this the other day, and he came up with this, which I think is worth having in your toolbelt if needed.

In the script:

Code: Select all

function Initialize()

	RunMe = false

end -- function Initialize

function Update()

	if RunMe then
	
		-- put your actual code here
		
		RunMe = false
		
	end

	return "I just ran!"
	
end -- function Update
In the skin:

Code: Select all

FinishAction=!CommandMeasure "LuaMeasure" "RunMe = true"
or

Code: Select all

OnRefreshAction=!CommandMeasure "LuaMeasure" "RunMe = true"
or

Code: Select all

LeftMouseUpAction=!CommandMeasure "LuaMeasure" "RunMe = true"
Or any other way you want to execute the script "on demand".

This has advantages over enabled/disabled on the script measure as disabled measures return zero as a numeric value, which you may not want "between runs". It has advantages over UpdateDivider=-1, as that setting will still run the measure one time when the skin is refreshed, and this also may not be what you want. All the methods have their place however, this is just one more.
poiru
Developer
Posts: 2877
Joined: April 17th, 2009, 12:18 pm

Re: Running Lua scripts on demand

poiru » August 7th, 2011, 1:11 pm

jsmorley wrote:This has advantages over enabled/disabled on the script measure as disabled measures return zero as a numeric value, which you may not want "between runs". It has advantages over UpdateDivider=-1, as that setting will still run the measure one time when the skin is refreshed, and this also may not be what you want. All the methods have their place however, this is just one more.
Here is yet another method:

Script (specify Initialize() and Update() if you need them*):

Code: Select all

function SomeFunction()
    -- do whatever you want here
end
And in the skin:

Code: Select all

!CommandMeasure "LuaMeasure" "SomeFunction()"
You could even pass parameters to the function as follows:

Script (specify Initialize() and Update() if you need them):

Code: Select all

function SomeFunction(x)
    -- do whatever you want here, x is a variable
end
And in the skin:

Code: Select all

!CommandMeasure "LuaMeasure" "SomeFunction(10)"
---

* Initialize(), Update(), and the PROPERTIES table are all optional and don't need to be specified. Note that Update() is required for returning a value back to Rainmeter.
User avatar
jsmorley
Developer
Posts: 19178
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Tips & Tricks Thread

jsmorley » September 21st, 2011, 10:48 pm

Reading a .ini file in Lua:

Here is a script with a function to populate a table with the contents of any .ini file. It is a three dimensional matrix of Section / Key / Value.

This script includes the function, and a sample Update() to demonstrate how to use it to print out the [Rainmeter] keys and values in Rainmeter.ini, and how to find the "Update=" value of the current skin.

Based on code here: http://luaforge.net/projects/inilazy/

Code: Select all

function Initialize()

	sIniPath = SKIN:GetVariable("SETTINGSPATH")
	sCurrSkin = SKIN:GetVariable("CURRENTPATH")..SKIN:GetVariable("CURRENTFILE")

end -- function Initialize

function Update()

	tTable = ReadIni(sIniPath ..'Rainmeter.ini')
	for sKey,a in pairs(tTable['Rainmeter']) do
		for sValue,b in pairs(tTable['Rainmeter'][sKey]) do
			print(sKey.."="..sValue)
		end
	end
	
	tTable = ReadIni(sCurrSkin)
	for sKey,a in pairs(tTable['Rainmeter']) do
		if sKey == 'Update' then
			for sValue,b in pairs(tTable['Rainmeter'][sKey]) do
				sSkinUpdate = sValue
				print(sSkinUpdate)
			end
		end	
	end

end -- function Update

function ReadIni(filename)
  local f = io.open(filename,'r')
  if not f then return nil, print("ReadIni: Can't open file: "..filename) end
  local line_counter=0
  local tablename = {}
  local section
  for fline in f:lines() do
    line_counter=line_counter+1
    -- Ignore leading and trailing spaces
    local line = fline:match("^%s*(.-)%s*$")
    -- Ignore comments
    if not line:match("^[%;#]") and #line > 0 then
      -- Check for [Section]
	  local sec = line:match("^%[(.*)%]$")
      if sec then
        section = sec
        if not tablename[section] then tablename[section]={} end
      else
        -- parse Key=Value
        local key, value = line:match("([^=]*)%=(.*)")
        -- Remove white space from Key=Value
        key = key:match("^%s*(%S*)%s*$")
        value = value:match("^%s*(.-)%s*$")
        -- Check for error
        if not (key and value) then return nil, print('Error bad key or value in file:'.. filename..': '.. line_counter.."\n line:".. fline) end
		-- Set Section/Key/Value in table
        if section then
          if not tablename[section][key] then tablename[section][key]={} end
		  if not tablename[section][key][value] then tablename[section][key][value]={} end
        end
      end
    end
  end
  f:close()
  return tablename
  end -- function ReadIni
Note/Caution: If you are going to return the value of a "config" in Rainmeter.ini, you must "escape" any "\" chars.

for sKey,a in pairs(tTable['Enigma\\Clock']) do
User avatar
rezonance
Posts: 9
Joined: March 12th, 2011, 3:18 am

Basic and Standard Lua Functions

rezonance » January 7th, 2012, 9:59 pm

Stumbled across this one today and figured it would be a worthy addition to this thread. For those looking for a rather basic function (like reading or writing to a file, simple mathematical operations, working with strings or arrays, ...), I recommend checking out Rosetta Code's Lua additions. May have what you are looking for or something incredibly close to it.
User avatar
smurfier
Moderator
Posts: 1937
Joined: January 29th, 2010, 1:43 am
Location: Willmar, MN

Re: Tips & Tricks Thread

smurfier » March 3rd, 2012, 3:45 pm

Here's a simple way to change multiple settings of a meter using !SetOption without having to type out every bang.

Code: Select all

mName='MeterName'
for k,v in pairs({
	--PropertyName='Value';
	Text='Some Text';
	Antialias=1;
}) do SKIN:Bang('!SetOption',mName,k,v) end
GitHub | DeviantArt | Tumblr
This is the song that never ends. It just goes on and on my friends. Some people started singing it not knowing what it was, and they'll continue singing it forever just because . . .
User avatar
smurfier
Moderator
Posts: 1937
Joined: January 29th, 2010, 1:43 am
Location: Willmar, MN

Re: Tips & Tricks Thread

smurfier » March 3rd, 2012, 3:52 pm

Here's a simple way to retrieve several variables from the skin, storing them in a table for late use.

Code: Select all

Vars={}
for i,v in pairs({'Var1','Var2'}) do
   Vars[v]=SKIN:GetVariable(v)
end
They can be retrieved in a couple ways.
  • Vars.Var1
  • Vars['Var1']
Note: With this method, only use alphanumeric characters in the variable names.
GitHub | DeviantArt | Tumblr
This is the song that never ends. It just goes on and on my friends. Some people started singing it not knowing what it was, and they'll continue singing it forever just because . . .
User avatar
jsmorley
Developer
Posts: 19178
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Tips & Tricks Thread

jsmorley » March 3rd, 2012, 6:20 pm

smurfier wrote:Here's a simple way to retrieve several variables from the skin, storing them in a table for late use.
I must be missing something in this. I can't get that approach to work at all. What I find is that if you don't set some default value for a "dictionary" index of a table, then it can't be looped through with "pairs". Also I find that I can't use "value" to retrieve or set data, but have to use "index". I mean, you can't say GetVariable(value) when value doesn't exist yet can you?

So this construct in a script, using your approach, does not work for me:

Code: Select all

PROPERTIES =
{

}

function Initialize()

	SkinVars = {
		CURRENTPATH;
		CURRENTFILE;
		CURRENTCONFIG;
		ROOTCONFIGPATH;
	}
	
	for index, value in pairs(SkinVars) do
		SkinVars[value] = SKIN:GetVariable(value)
	end
	
end -->Initialize

function Update()

	return SkinVars.CURRENTCONFIG
	
end -->Update
However, this construct does:

Code: Select all

PROPERTIES =
{

}

function Initialize()

	SkinVars = {
		CURRENTPATH='';
		CURRENTFILE='';
		CURRENTCONFIG='';
		ROOTCONFIGPATH='';
	}
	
	for index, value in pairs(SkinVars) do
		SkinVars[index] = SKIN:GetVariable(index)
	end

end -->Initialize

function Update()

	return SkinVars.CURRENTCONFIG
	
end -->Update
So for me at least, I have to change your example to:

Code: Select all

local Vars = {
   --VariableName;
   Var1='';
   SomeVar='';
}
for index,value in pairs(Vars) do Vars[index]=SKIN:GetVariable(index) end
P.S. I removed "local" from the table definition in mine, as with it you can't set it up in Initialize() and use it in Update().
User avatar
smurfier
Moderator
Posts: 1937
Joined: January 29th, 2010, 1:43 am
Location: Willmar, MN

Re: Tips & Tricks Thread

smurfier » March 3rd, 2012, 6:43 pm

It must have been because of how I altered my approach.

This is what has been working for me.

Code: Select all

Vars={}
for i,v in pairs({'Var1','Var2'}) do
	Vars[v]=SKIN:GetVariable(v)
end
GitHub | DeviantArt | Tumblr
This is the song that never ends. It just goes on and on my friends. Some people started singing it not knowing what it was, and they'll continue singing it forever just because . . .
User avatar
jsmorley
Developer
Posts: 19178
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Tips & Tricks Thread

jsmorley » March 3rd, 2012, 6:49 pm

smurfier wrote:It must have been because of how I altered my approach.

This is what has been working for me.

Code: Select all

Vars={}
for i,v in pairs({'Var1','Var2'}) do
	Vars[v]=SKIN:GetVariable(v)
end
Yeah, works that way, although I'm not sure I have wrapped by head around why it would be Vars[v]=SKIN:GetVariable(v) instead of Vars[i]=SKIN:GetVariable(i), but it is...