136 lines
4.8 KiB
Lua
136 lines
4.8 KiB
Lua
-- This file is part of Reno desktop.
|
|
--
|
|
-- Reno desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
--
|
|
-- Reno desktop is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
--
|
|
-- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
-- Various utilitiy parsers
|
|
local parsers = {}
|
|
|
|
local function split_strings(text)
|
|
-- probably the cleanest function to split by strings i've written
|
|
local split = {}
|
|
while text:find("\"") do
|
|
local strstart = text:find("\"")
|
|
while text:sub(strstart-1,strstart-1) == "\\" do
|
|
strstart = text:find("\"",strstart+1)
|
|
end
|
|
local strend = text:find("\"",strstart+1)
|
|
while text:sub(strend-1,strend-1) == "\\" do
|
|
strend = text:find("\"",strend+1)
|
|
end
|
|
if not strend then
|
|
return nil, "String not closed at "..strstart
|
|
end
|
|
local before_string = text:sub(1,strstart-1)
|
|
local string = text:sub(strstart,strend):gsub("\\\"","\"")
|
|
text = text:sub(strend+1,-1)
|
|
table.insert(split,before_string)
|
|
table.insert(split,string)
|
|
end
|
|
table.insert(split,text)
|
|
return split
|
|
end
|
|
|
|
parsers.fast_split_yaml = function(cfgtext)
|
|
-- Fast yaml splitter - incomplete parsing, only first layer is parsed
|
|
-- Used within timers to find objects while decreasing CPU usage
|
|
local items = {}
|
|
local replacements = 1
|
|
cfgtext = cfgtext:gsub("^%s*","")
|
|
while replacements > 0 do
|
|
cfgtext,replacements = cfgtext:gsub("^(.-\n)(%S+)",function(struct,n)
|
|
table.insert(items,struct)
|
|
return ""..n
|
|
end)
|
|
end
|
|
table.insert(items,cfgtext)
|
|
return items
|
|
end
|
|
parsers.yaml_pseudo = function(cfgtext)
|
|
-- Somewhat yaml-like structure used by pactl
|
|
local struct = {}
|
|
local lines = {}
|
|
cfgtext:gsub("(%s*)([^\n]*)",function(spacing,line)
|
|
table.insert(lines,
|
|
{
|
|
spacing:len(),
|
|
-- key
|
|
line:match("^([^:=]-)%s*[:=]") or line,
|
|
-- value
|
|
line:match(":%s*(.-)%s*$") or
|
|
line:match("=%s*(.-)%s*$")
|
|
}
|
|
)
|
|
end)
|
|
local history = {struct}
|
|
local spacing_width = 0
|
|
for k,v in pairs(lines) do
|
|
if v[1] > spacing_width then
|
|
history[#history][lines[k-1][2]] = {
|
|
[lines[k-1][2]] = lines[k-1][3]
|
|
}
|
|
history[#history+1] = history[#history][lines[k-1][2]]
|
|
elseif v[1] < spacing_width then
|
|
history[#history] = nil
|
|
end
|
|
if v[3] and v[3]:match("^%s*\".*\"%s*$") then
|
|
history[#history][v[2]] = v[3]:match("^%s*\"(.*)\"%s*$")
|
|
else
|
|
history[#history][v[2]] = v[3]
|
|
end
|
|
spacing_width = v[1]
|
|
end
|
|
return struct
|
|
end
|
|
|
|
parsers.conf = function(cfgtext)
|
|
-- Conf style parser (not exactly TOML)
|
|
cfgtext = cfgtext:gsub("#[^\n]*","")
|
|
local split_by_strings,err = split_strings(cfgtext)
|
|
if not split_by_strings then
|
|
error(err)
|
|
end
|
|
local struct = {global = {}}
|
|
local block = "global"
|
|
local last_string_key = nil
|
|
local err
|
|
for k,v in pairs(split_by_strings) do
|
|
if not v:match("^\".*\"$") then
|
|
v:gsub("[^\n]*",function(line)
|
|
-- Nothing
|
|
if line:match("^%s*$") then
|
|
return
|
|
end
|
|
-- Namespace block
|
|
if line:match("^%s*%[[^%]]-%]%s*$") then
|
|
block = line:match("%[([^%]]-)%]")
|
|
struct[block] = {}
|
|
return
|
|
end
|
|
-- String/Multiline string assignment
|
|
if line:match("^%s*[^=]-%s*=%s*$") then
|
|
last_string_key = line:match("^%s*([^=]-)%s*=%s*$")
|
|
return
|
|
end
|
|
-- Number/boolean assignment
|
|
local key,value = line:match("^%s*([^=]-)%s*=%s*(.-)%s*$")
|
|
-- number
|
|
if value:match("^[%d%.]*$") then
|
|
value = tonumber(value)
|
|
-- bool
|
|
elseif (value:lower() == "yes") or (value:lower() == "no") then
|
|
value = (value:lower() == "yes")
|
|
end
|
|
struct[block][key] = value
|
|
end)
|
|
else
|
|
struct[block][last_string_key] = v:sub(2,-2)
|
|
end
|
|
end
|
|
return struct
|
|
end
|
|
return parsers
|