It is currently March 30th, 2023, 1:50 pm
Some useful function in lua
-
- Rainmeter Sage
- Posts: 1398
- Joined: April 24th, 2021, 8:13 pm
Re: Some useful function in lua
P.S. not related to toolkit but why don't SKIN object or dofile work if not inside a function block?
from the Realm of Death
-
- Rainmeter Sage
- Posts: 4919
- Joined: February 27th, 2015, 2:38 pm
- Location: Terra Yincognita
Re: Some useful function in lua
Yeah, that was what I was thinking as well. If the function will be included in death.crafter's Functions.lua, then having the function again in the script will likely produce either some conflicts, or confusion at best.
I was thinking the same thing.death.crafter wrote: ↑August 22nd, 2021, 1:29 amActually I went through smurfier's Lua Calender's lua and thought it might be a good idea to centralize some really useful functions that are used a lot.
[...]
I could include Rainmeter docs functions too I guess. Just one dofile and you are ready for some serious automation, without going over to the docs again and again

-
- Rainmeter Sage
- Posts: 1398
- Joined: April 24th, 2021, 8:13 pm
Re: Some useful function in lua
Oh... I thought of iterating through files and stuff, which us beyond the scope if vanilla lua, given io.popen is not available.
Well, that wouldn't be a commonly useful thing, but I guess I should include it so that its not lost to the flow of time

Also thanks for the currentsectionindex function.
from the Realm of Death
-
- Developer
- Posts: 22564
- Joined: April 19th, 2009, 11:02 pm
- Location: Fort Hunt, Virginia, USA
Re: Some useful function in lua
Not sure, it's just a "feature" of how we built the "glue" between Lua and Rainmeter.death.crafter wrote: ↑August 22nd, 2021, 1:31 am P.S. not related to toolkit but why don't SKIN object or dofile work if not inside a function block?
Best to put the dofile in function Initialize() really. It doesn't have to be there, it can be in some other function, but you want to be sure you are loading it before anything in it is "used", and not loading it repeatedly. No need for that.
-
- Rainmeter Sage
- Posts: 1398
- Joined: April 24th, 2021, 8:13 pm
Re: Some useful function in lua
The WriteINI function in the docs is tbh flawed. Why? Because tables in lua can't be iterated in order if not indexed using integers starting from 1. So you end up having a random list of unorderd sections(this matters, a lot) with unordered keys(doesn't matter but looks super weird).Yincognito wrote: ↑August 22nd, 2021, 1:41 am I'm all for the inclusion of WriteINI snippet in your Functions.lua though. I couldn't fully understand it at the time, but I ended up doing a very similar thing in my savegame editor Lua script. With some more generalized form, I guess it could work as a rudimentary JSON parser as well (which is yet another idea, already implemented by someone somewhere, if I'm not mistaken).
I have my workaround but it needs some setup to be done. If you look at the ReadINI in this one, I have made a table of sections, section order and key order of each section, so you can iterate through them easily when needed. When using my version of WriteINI, you have to create a input table similar to the one ReadINI returns, so that WriteINI can put the things in order.
So, since it needs a little bit of more explanation, I will put it in a separate thread, along with ReadINI.
from the Realm of Death
-
- Rainmeter Sage
- Posts: 1398
- Joined: April 24th, 2021, 8:13 pm
Re: Some useful function in lua
Yup. Well, doesn't really matter much since you can easily create a global variable in lua without a hassle.jsmorley wrote: ↑August 22nd, 2021, 1:46 am Not sure, it's just a "feature" of how we built the "glue" between Lua and Rainmeter.
Best to put the dofile in function Initialize() really. It doesn't have to be there, it can be in some other function, but you want to be sure you are loading it before anything in it is "used", and not loading it repeatedly. No need for that.
from the Realm of Death
-
- Rainmeter Sage
- Posts: 4919
- Joined: February 27th, 2015, 2:38 pm
- Location: Terra Yincognita
Re: Some useful function in lua
Ah, yes, now I remember, I believe I had the same problem when loking at that code. Personally, I used specific table array addressing (i.e. no pairs()), like (posted just for reference, disregard the unknowns in my savegame code):death.crafter wrote: ↑August 22nd, 2021, 1:52 am The WriteINI function in the docs is tbh flawed. Why? Because tables in lua can't be iterated in order if not indexed using integers starting from 1. So you end up having a random list of unorderd sections(this matters, a lot) with unordered keys(doesn't matter but looks super weird).
I have my workaround but it needs some setup to be done. If you look at the ReadINI in this one, I have made a table of sections, section order and key order of each section, so you can iterate through them easily when needed. When using my version of WriteINI, you have to create a input table similar to the one ReadINI returns, so that WriteINI can put the things in order.
So, since it needs a little bit of more explanation, I will put it in a separate thread, along with ReadINI.
Code: Select all
function SaveAutosave(outputfile)
if not decryptedautosave then return true end
local st = os.clock()
local lines = {}
for gi = 1, #items do
lines[#lines + 1] = ('%s\n{'):format(items[gi][1])
for ci = 1, #items[gi][2] do
lines[#lines + 1] = ('%s {'):format(items[gi][2][ci][1])
for fi = 1, #items[gi][2][ci][2] do
for vi = 1, #items[gi][2][ci][2][fi][2][1] do
lines[#lines + 1] = (' %s: %s'):format(items[gi][2][ci][2][fi][1], items[gi][2][ci][2][fi][2][vi][1])
end
end
lines[#lines+1] = ('%s'):format('}\n')
end
if gi == #items then lines[#lines+1] = ('%s'):format('}') else lines[#lines+1] = ('%s'):format('}\n') end
end
local file = assert(io.open(outputfile, 'w'), 'ETS2 Autosave Editor: unable to save ' .. outputfile)
file:write(table.concat(lines, '\n'))
file:close()
local et = os.clock()
print('ETS2 Autosave Editor: saved autosave ' .. outputfile .. ' (' .. #lines .. ' lines)' .. string.format('; time = %.5f', et-st) .. ' s')
return true
end
-
- Developer
- Posts: 22564
- Joined: April 19th, 2009, 11:02 pm
- Location: Fort Hunt, Virginia, USA
Re: Some useful function in lua
This is a little toolkit dofile I put together a long time ago...
Code: Select all
function AddSuffix(num) -- Returns the ordinal suffix for an input number.
local suffix = ''
local n = num % 10
if (num - n) == 10 then
suffix = 'th'
else
suffix = (n == 1 and 'st' or n == 2 and 'nd' or n == 3 and 'rd' or 'th')
end
return suffix
end
function FormatCommas(numVar) -- Formats numbers with commas as the thousands separator.
local prefix, number, postfix = string.match(numVar, '^([^%d]*%d)(%d*)(.-)$')
return prefix..(number:reverse():gsub('(%d%d%d)', '%1,'):reverse())..postfix
end
function ConvertToHex(color) -- Converts RGB colors to HEX
local hex = {}
for rgb in color:gmatch('%d+') do
table.insert(hex, ('%02X'):format(tonumber(rgb)))
end
return table.concat(hex)
end
function ConvertToRGB(color) -- Converts HEX colors to RGB
local rgb = {}
for hex in color:gmatch('..') do
table.insert(rgb, tonumber(hex, 16))
end
return table.concat(rgb, ',')
end
function ConvertTemp(num, toScale) -- Converts between Celsius and Fahrenheit.
local outTemp = 0
if toScale == 'c' then
outTemp = Round((5 / 9) * (num - 32))
else
outTemp = Round((9 / 5) * num + 32)
end
return outTemp
end
function AutoScale(num, idp) -- Autoscales a number and adds the scale prefix.
local scales = {'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'}
local places = idp or 0
local scale = ""
local scaled = 0
for i, v in ipairs(scales) do
if (num < (1024 ^ i)) or (i == #scales) then
scale = v
scaled = Round(num / 1024 ^ (i - 1), places)
break
end
end
return scaled..' '..scale
end
function TitleCase(input) -- Capitalizes the first character of a string.
return (input:gsub('(%S)(%S*)', function(first, rest) return first:upper() .. rest:lower() end))
end
function SentenceCase(input) -- Capitalizes the first character of each word in a string.
return (input:gsub('[^.!?]+', function(sentence)
local space, first, rest = sentence:match('(%s*)(.)(.*)')
return space .. first:upper() .. rest:lower():gsub("%si([%s'])", ' I%1')
end))
end
function ParseTwelveHourTime(Hour, Meridiem) -- Takes a number (1-12) and a string ('AM' or 'PM') and returns the equivalent 24-hour figure.
if (string.upper(Meridiem) == 'AM') and (Hour == 12) then
Hour = 0
elseif (string.upper(Meridiem) == 'PM') and (Hour < 12) then
Hour = Hour + 12
end
return Hour
end
function RightPad(str, len, char) --- Pads string str to length len with character char to the right.
if char == nil then char = ' ' end
return str .. string.rep(char, len - #str)
end
function LeftPad(str, len, char) --- Pads string str to length len with character char to the left
if char == nil then char = ' ' end
return string.rep(char, len - #str) .. str
end
function SplitPath(pathArg, pathBit) -- Splits a full path\filename.ext into component parts.
path, file, ext = string.match(pathArg, '(.-)([^\\/]-%.?([^%.\\/]*))$')
if string.upper(pathBit) == 'PATH' then
return path
elseif string.upper(pathBit) == 'FILE' then
return file
elseif string.upper(pathBit) == 'EXT' then
return ext
else
return 'Invalid component'
end
end
function SplitLine(line, delimiter) -- Separate a string into a table by single character delimiter.
local tbl = {}
for word in line:gmatch('[^%' .. delimiter .. ']+') do
table.insert(tbl, word)
end
return tbl
end
function SortRandom(tableName) -- Sorts a given table into a random order.
math.randomseed(tonumber(tostring(os.time()):reverse():sub(1,6)))
local temp, newTable = {}, {}
for _, v in pairs(tableName) do
table.insert(newTable, v)
end
while #newTable > 0 do
table.insert(temp, table.remove(newTable, math.random(1, #newTable)))
end
return temp
end
-- Utility functions
function Round(num, idp) -- Rounds a number to an integer (default) or specified places.
local mult = 10 ^ (idp or 0)
if num >= 0 then
return math.floor(num * mult + 0.5) / mult
else
return math.ceil(num * mult - 0.5) / mult
end
end
-
- Rainmeter Sage
- Posts: 1398
- Joined: April 24th, 2021, 8:13 pm
Re: Some useful function in lua
Thanks!
You saved me the trouble of copy pasting docs snippets

from the Realm of Death
-
- Moderator
- Posts: 1931
- Joined: January 29th, 2010, 1:43 am
- Location: Willmar, MN
Re: Some useful function in lua
Just for posterity's sake, here's my scary math version of the AutoScale function. I'm retyping this by converting an old Rainmeter post in Lua, so bear with me if there are typos.
Code: Select all
function AutoScale(num, idp)
local scales = {'B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'}
local scale = (num == 0) ? 1 : math.ceil(math.log(num) / (10 * math.log(2)))
local scaled = Round((num / 1024 ^ (scale - 1)), idp or 0)
return scaled .. ' ' .. scales[scale]
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 . . .
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 . . .