Reno is the second iteration of the AWMTK-powered AwesomeWM config.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
5.8 KiB

2 years ago
2 years ago
  1. -- This file is part of Reno desktop.
  2. --
  3. -- 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.
  4. --
  5. -- 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.
  6. --
  7. -- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
  8. -- Various utilitiy parsers
  9. local parsers = {}
  10. local function split_strings(text)
  11. -- probably the cleanest function to split by strings i've written to date
  12. local split = {}
  13. while text:find("\"") do
  14. local strstart = text:find("\"")
  15. while text:sub(strstart-1,strstart-1) == "\\" do
  16. strstart = text:find("\"",strstart+1)
  17. end
  18. local strend = text:find("\"",strstart+1)
  19. while text:sub(strend-1,strend-1) == "\\" do
  20. strend = text:find("\"",strend+1)
  21. end
  22. if not strend then
  23. return nil, "String not closed at "..strstart
  24. end
  25. local before_string = text:sub(1,strstart-1)
  26. local string = text:sub(strstart,strend):gsub("\\\"","\"")
  27. text = text:sub(strend+1,-1)
  28. table.insert(split,before_string)
  29. table.insert(split,string)
  30. end
  31. table.insert(split,text)
  32. return split
  33. end
  34. parsers.fast_split_yaml = function(cfgtext)
  35. -- Fast yaml splitter - incomplete parsing, only first layer is parsed
  36. -- Used within timers to find objects while decreasing CPU usage
  37. local items = {}
  38. local replacements = 1
  39. cfgtext = cfgtext:gsub("^%s*","")
  40. while replacements > 0 do
  41. cfgtext,replacements = cfgtext:gsub("^(.-\n)(%S+)",function(struct,n)
  42. table.insert(items,struct)
  43. return ""..n
  44. end)
  45. end
  46. table.insert(items,cfgtext)
  47. return items
  48. end
  49. parsers.yaml_pseudo = function(cfgtext)
  50. -- Somewhat yaml-like structure used by pactl
  51. local struct = {}
  52. local lines = {}
  53. cfgtext:gsub("(%s*)([^\n]*)",function(spacing,line)
  54. table.insert(lines,
  55. {
  56. spacing:len(),
  57. -- key
  58. line:match("^([^:=]-)%s*[:=]") or line,
  59. -- value
  60. line:match(":%s*(.-)%s*$") or
  61. line:match("=%s*(.-)%s*$")
  62. }
  63. )
  64. end)
  65. local history = {struct}
  66. local spacing_width = 0
  67. for k,v in pairs(lines) do
  68. if v[1] > spacing_width then
  69. history[#history][lines[k-1][2]] = {
  70. [lines[k-1][2]] = lines[k-1][3]
  71. }
  72. history[#history+1] = history[#history][lines[k-1][2]]
  73. elseif v[1] < spacing_width then
  74. history[#history] = nil
  75. end
  76. if v[3] and v[3]:match("^%s*\".*\"%s*$") then
  77. history[#history][v[2]] = v[3]:match("^%s*\"(.*)\"%s*$")
  78. else
  79. history[#history][v[2]] = v[3]
  80. end
  81. spacing_width = v[1]
  82. end
  83. return struct
  84. end
  85. local function quotestrip(txt)
  86. if (txt:sub(1,1):match("['\"]"))
  87. and (txt:sub(-1,-1) == txt:sub(1,1)) then
  88. return txt:sub(2,-2)
  89. else
  90. return txt
  91. end
  92. end
  93. parsers.conf = function(cfgtext)
  94. -- Conf style parser (not exactly TOML)
  95. cfgtext = cfgtext:gsub("#[^\n]*","")
  96. local split_by_strings,err = split_strings(cfgtext)
  97. if not split_by_strings then error(err) end
  98. local full_split = {{}}
  99. local current_line = full_split[1]
  100. -- tokenizer
  101. for _,v in pairs(split_by_strings) do
  102. v = v:match("^[ \t]*(.*)[ \t]*$")
  103. if (not (v == "")) then
  104. if not v:match("^\".*\"$") then
  105. v:gsub("[^ \t]+",function(text)
  106. while text:match("\n") do
  107. local before,after = text:match("([^\n]*)\n(.*)")
  108. if before ~= "" then
  109. table.insert(current_line,before)
  110. end
  111. if #current_line > 0 then
  112. table.insert(full_split,{})
  113. current_line = full_split[#full_split]
  114. end
  115. text = after
  116. end
  117. if text ~= "" then
  118. table.insert(current_line,text)
  119. end
  120. end)
  121. else
  122. table.insert(current_line,v)
  123. end
  124. end
  125. end
  126. table.remove(full_split,#full_split)
  127. local struct = {global = {}}
  128. local block = "global"
  129. -- parser
  130. for _,line in pairs(full_split) do
  131. if line[1] and line[1]:match("^%[[^%]]+%]$") then -- block
  132. block = line[1]:match("^%[([^%]]+)%]$")
  133. struct[block] = {}
  134. elseif #line == 3 then -- assignment
  135. if (line[3]:sub(1,1):match("['\"]")) -- string
  136. and (line[3]:sub(-1,-1) == line[3]:sub(1,1)) then
  137. struct[block][quotestrip(line[1])] = quotestrip(line[3])
  138. elseif line[3]:match("^%d+$") then -- number
  139. struct[block][quotestrip(line[1])] = tonumber(line[3])
  140. elseif (line[3] == "true") or (line[3] == "false") then -- boolean
  141. struct[block][quotestrip(line[1])] = (line[3] == "true")
  142. else
  143. error("Invalid assignment expression: "..line[3])
  144. end
  145. else -- invalid
  146. local textline = ""
  147. for _,v in pairs(line) do
  148. textline = textline..v.." "
  149. end
  150. error("Invalid config expression: "..textline:sub(1,-2))
  151. end
  152. end
  153. return struct
  154. end
  155. return parsers