It is currently April 26th, 2024, 9:25 am

Using Regex to escape variables

Get help with creating, editing & fixing problems with skins
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Using Regex to escape variables

Post by raiguard »

I have a script that can import settings from a "settings backup". This is meant to facilitate preserving the user's settings when they update the suite to a new version. The way it works is that it uses jsmorley's ReadINI function to parse the file, then uses !WriteKeyValue bangs to set the variables in the suite to the ones from the backup, without touching any new settings.

The problem with this is that when !WriteKeyValue writes, it writes the values of any variables as they were at the time. I need to be able to escape the variables when they're read by the ReadINI function so the variable references are preserved, but I am completely clueless at Regex and need some help. Preferably I would like it to be able to escape both standard and inline formatted variables.

Could someone point me in the right direction?

Code: Select all

-- parses a INI formatted text file into a 'Table[Section][Key] = Value' table
function ReadIni(inputfile)
	local file = assert(io.open(inputfile, 'r'), 'Unable to open ' .. inputfile)
	local tbl, section = {}
  local num = 0
	for line in file:lines() do
		num = num + 1
		if not line:match('^%s;') then
			local key, command = line:match('^([^=]+)=(.+)')
			if line:match('^%s-%[.+') then
				section = line:match('^%s-%[([^%]]+)')
				LogHelper('[' .. section .. ']', 'Debug')
				if not tbl[section] then tbl[section] = {} end
			elseif key and command and section then
				LogHelper(key .. '=' .. command, 'Debug')
				tbl[section][key:match('(%S*)%s*$')] = command:match('^s*(.-)%s*$')
			elseif #line > 0 and section and not key or command then
				LogHelper(num .. ': Invalid property or value.', Debug)
			end
		end
	end
	if not section then print('No sections found in ' .. inputfile) end
	file:close()
	return tbl
end
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
jsmorley
Developer
Posts: 22630
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Using Regex to escape variables

Post by jsmorley »

Sorry, I don't follow...
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: Using Regex to escape variables

Post by raiguard »

jsmorley wrote:Sorry, I don't follow...
When !WriteKeyValue imports the values from the backup, any variables that are in the settings it imports are resolved and their values are written instead. I want the ReadINI script to be able to escape the variables when it's parsing so when !WriteKeyValue is used, the variable references are preserved.

For example, if I am importing contentMarginRight=((#bgWidth# + #bgOffset#) - #contentMarginAbs# - 1) from the backup, it will be written as contentMarginRight=((150 + 5) - 3 - 1) instead. I want it to remain as it was without the variables resolving.

Here is the full LUA script if needed:

Code: Select all

-- MODERNGADGETS SETTINGS BACKUP SCRIPT
--
-- This script makes backups of the settings files every two hours, which
-- prevents them from being lost when updating the suite.

debug = false

function Initialize()

  dofile(SKIN:GetVariable('scriptPath') .. 'Utilities.lua')

  fileNames = { 'GlobalSettings.inc',
                'CpuSettings.inc',
                'NetworkSettings.inc',
                'GpuSettings.inc',
                'DisksSettings.inc'  }


  backupsPath = SKIN:GetVariable('SETTINGSPATH') .. 'ModernGadgetsSettings\\'

  filesPath = SKIN:GetVariable('@') .. 'Settings\\'

  cpuMeterPath = SKIN:GetVariable('cpuMeterPath')
  networkMeterPath = SKIN:GetVariable('networkMeterPath')
  gpuMeterPath = SKIN:GetVariable('gpuMeterPathBase')
  disksMeterPath = SKIN:GetVariable('disksMeterPath')

end 

function Update() end

function ImportBackup()

  for i=1, 5 do
    local bTable = ReadIni(backupsPath .. fileNames[i])
    local sTable = ReadIni(filesPath .. fileNames[i])
    CrossCheck(bTable, sTable, filesPath .. fileNames[i])
  end
  
  SKIN:Bang('!RefreshGroup', 'MgImportRefresh')

  LogHelper('Imported settings backup', 'Notice')

end

function CrossCheck(bTable, sTable, filePath)

  for i,v in pairs(bTable) do
    if type(v) == 'table' then
      for a,b in pairs(v) do
        if sTable[i][a] then
          SKIN:Bang('!WriteKeyValue', i, a, b, filePath)
        else
          LogHelper('Key \'' .. a .. '\' does not exist in local', 'Debug')
        end
      end
    end
  end

end

function CheckForBackup()

  local file = io.open(backupsPath .. fileNames[1])
  if file == nil then
    SKIN:Bang('!ActivateConfig', 'ModernGadgets\\Config\\GadgetManager', 'Config.ini')
    SKIN:Bang('!CommandMeasure', 'MeasureCreateBackup', 'Run')
  else
    SKIN:Bang('!Hide')
    SKIN:Bang('!ShowMeterGroup', 'Essentials')
    SKIN:Bang('!ShowMeterGroup', 'ImportBackupPrompt')
    SKIN:Bang('!SetOption', 'BackgroundHeightAdjuster', 'Y', 'R')
    SKIN:Bang('!UpdateMeter', 'BackgroundHeightAdjuster')
    SKIN:Bang('!UpdateMeterGroup', 'Essentials')
    SKIN:Bang('!Redraw')
    SKIN:Bang('!ShowFade')
    file:close()
  end
  
end

-- parses a INI formatted text file into a 'Table[Section][Key] = Value' table
function ReadIni(inputfile)
  local file = assert(io.open(inputfile, 'r'), 'Unable to open ' .. inputfile)
  local tbl, section = {}
  local num = 0
  for line in file:lines() do
    num = num + 1
    if not line:match('^%s;') then
      local key, command = line:match('^([^=]+)=(.+)')
      if line:match('^%s-%[.+') then
        section = line:match('^%s-%[([^%]]+)')
        LogHelper('[' .. section .. ']', 'Debug')
        if not tbl[section] then tbl[section] = {} end
      elseif key and command and section then
        LogHelper(key .. '=' .. command, 'Debug')
        tbl[section][key:match('(%S*)%s*$')] = command:match('^s*(.-)%s*$')
      elseif #line > 0 and section and not key or command then
        LogHelper(num .. ': Invalid property or value.', Debug)
      end
    end
  end
  if not section then print('No sections found in ' .. inputfile) end
  file:close()
  return tbl
end
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
jsmorley
Developer
Posts: 22630
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Using Regex to escape variables

Post by jsmorley »

User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: Using Regex to escape variables

Post by raiguard »

I know, what I'm asking for is help with the Regex to make the ReadINI script automatically escape the variables before putting them into the table.
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
jsmorley
Developer
Posts: 22630
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Using Regex to escape variables

Post by jsmorley »

I'm not sure there is anyway to get there. !WriteKeyValue is ALWAYS going to resolve #Variables# before it writes them, and if you escape them, like:

Lua:

Code: Select all

function Initialize()

end	

function Update()

	myVar = 'contentMarginRight=((#bgWidth# + #bgOffset#) - #contentMarginAbs# - 1)'
	
	myVar = myVar:gsub( '#(.-)#', '#\*%1\*#')
	-- contentMarginRight=((#*bgWidth*# + #*bgOffset*#) - #*contentMarginAbs*# - 1)	
	
	return myVar

end
That's all well and good, but what will be written to the file with !WriteKeyValue will literally be:

contentMarginRight=((#*bgWidth*# + #*bgOffset*#) - #*contentMarginAbs*# - 1)

Which is not going to be of much use later.

I THINK what you are saying is that you want !WriteKeyValue to write #Variable# without either resolving it or changing it, and I know of no way to do that.
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: Using Regex to escape variables

Post by raiguard »

I just tested it and !WriteKeyValue will write the references if you escape the variables. Here's an example:

Code: Select all

[Rainmeter]
Update=1000
MiddleMouseUpAction=[!Refresh]

[Variables]
test=#debug1# #debug2#
debug1=foo
debug2=bar

[StyleString]
FontFace=Arial
FontSize=10
FontColor=240,240,240
X=5
Y=2R
Antialias=1

[MeterBackground]
Meter=Shape
Shape=Rectangle 1,1,100,45,1 | Fill Color 15,15,15 | StrokeWidth 0

[MeterEscaped]
Meter=String
MeterStyle=StyleString
Y=5
Text="Escaped"
LeftMouseUpAction=[!WriteKeyValue Variables test "#*debug1*# #*debug2*#"]

[MeterNotEscaped]
Meter=String
MeterStyle=StyleString
Text="Not Escaped"
LeftMouseUpAction=[!WriteKeyValue Variables test "#debug1# #debug2#"]
When the variables in !WriteKeyValue are escaped, the bang will write the references correctly. When they're not escaped, !WriteKeyValue will write the values of the variables (as expected).
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
jsmorley
Developer
Posts: 22630
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Using Regex to escape variables

Post by jsmorley »

The * escape character in #*Variables*# and [*SectionVariables*] is designed to be used with !SetOption, so you can set an option with a #Variable#, and not have it be resolved when the option is set by the !SetOption bang, but when the option is used. That just doesn't apply to !WriteKeyValue.
User avatar
raiguard
Posts: 660
Joined: June 25th, 2015, 7:02 pm
Location: The Sky, USA

Re: Using Regex to escape variables

Post by raiguard »

Then why, in my example, does !WriteKeyValue clearly exhibit the same behavior as !SetOption?
”We are pretty sure that r2922 resolves the regression in resolution caused by a reversion to a revision.” - jsmorley, 2017
User avatar
jsmorley
Developer
Posts: 22630
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Using Regex to escape variables

Post by jsmorley »

raiguard wrote:Then why, in my example, does !WriteKeyValue clearly exhibit the same behavior as !SetOption?
The ability to handle "escapes" is just not written into the functionality of !WriteKeyValue. It was, is designed to write a string to a file, and it will always resolve variables before writing. If you escape the variable, that's fine, but that is exactly how it will be written.