1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
|
module (..., package.seeall)
require("fs")
-- Create a new config file entry
-- see function description for setoptsinfile
-- line is the current line for this name:value if it exists
local create_entry = function(search_name, value, to_table, optionvalue, line)
local oldvalue, comment = "", ""
if line then
-- find the old value
oldvalue = string.match ( line, '^%s*%S+%s*%=%s*(.*)$' ) or ""
-- split out comment
if string.find ( oldvalue, '#' ) then
oldvalue, comment = string.match ( oldvalue, '^(.*)(#.*)$' )
if comment then
comment = " " .. string.match ( comment, '^(.*%S)%s*$' )
else
comment = ""
end
end
-- remove spaces
oldvalue = string.match ( oldvalue, '^%s*(.*%S)%s*$' ) or ""
end
if to_table == true then
local table = opts_to_table(oldvalue) or {}
table[value] = optionvalue
return search_name .. "=" .. table_to_opts(table) .. comment
else
if value then
return search_name .. "=" .. value .. comment
else
return nil
end
end
end
-- Search the option string for separate options (-x or --xyz) and put them in a table
opts_to_table = function ( optstring, filter )
local optsparams
if optstring then
local optstr = optstring .. " "
for o in string.gmatch(optstr, "%-%-?%a+%s+[^-%s]*") do
local option = string.match(o, "%-%-?%a+")
if not filter or filter == option then
if not optsparams then optsparams = {} end
optsparams[option] = string.match(o, "%S*$")
end
end
end
return optsparams
end
-- Go through an options table and create the option string
table_to_opts = function ( optsparams )
local optstring = {}
for opt,val in pairs(optsparams) do
if val ~= "" then
optstring[#optstring + 1] = opt .. " " .. val
else
optstring[#optstring + 1] = opt
end
end
return table.concat(optstring, " ")
end
-- Set a name=value pair
-- If search_section is undefined or "", goes in the default section
-- If to_table is false or undefined
-- if value is defined we put "search_name=value" into search_section
-- if value is undefined, we clear search_name out of search section
-- If to_table is true (and value is defined)
-- if optionvalue defined, we add "search_value optionvalue" to the value for search_name in search_section
-- if optionvalue undefined, we remove search_value from the value of search_name in search_section
-- Try not to touch anything but the value we're interested in (although will combine multi-line into one)
-- If the search_section is not found, we'll add it at the end of the file
-- If the search_name is not found, we'll add it at the end of the section
function setoptsinfile (file, search_section, search_name, value, to_table, optionvalue)
if not file or not search_name or search_name == "" or (to_table == true and not value) then
return false, nil, "Invalid input for getopts.setoptsinfile()", file
end
search_section = search_section or ""
local conf_file = {}
if (fs.is_file(file)) then
conf_file = fs.read_file_as_array ( file )
else
for line in string.gmatch(file, "([^\n]*)\n") do
conf_file[#conf_file + 1] = line
end
local extra = string.match(file,"([^\n]*)$")
if extra ~= "" then
conf_file[#conf_file + 1] = extra
end
end
local new_conf_file = {}
local section = ""
local done = false
local skip_lines = 0
for i,l in ipairs(conf_file) do
if skip_lines>0 then
skip_lines = skip_lines-1
else
-- check if comment line
if done == false and not string.find ( l, "^%s*#" ) then
-- first, concat lines
local j = 1
while string.find ( l, "\\%s*$" ) and conf_file[i+j] do
l = string.match ( l, "^(.*)\\%s*$" ) .. " " .. conf_file[i+j]
j = j+1
end
if j>1 then skip_lines = j-1 end
-- find section name
local a = string.match ( l, "^%s*%[%s*(%S+)%s*%]" )
if a then
-- we reached a new section, if we were in the one we wanted
-- we have to add in the name:value pair now
if (search_section == section) then
new_conf_file[#new_conf_file + 1] = create_entry(search_name, value, to_table, optionvalue, nil)
done = true
end
section = a
elseif (search_section == section) then
-- find name
a = string.match ( l, "^%s*(%S+)%s*=" )
if a and (search_name == a) then
-- We found the name, change the value
l = create_entry(search_name, value, to_table, optionvalue, l)
done = true
end
end
end
new_conf_file[#new_conf_file + 1] = l
end
end
if done == false then
-- we didn't find the section:name, add it now
if section ~= search_section then
new_conf_file[#new_conf_file + 1] = '[' .. search_section .. ']'
end
new_conf_file[#new_conf_file + 1] = create_entry(search_name, value, to_table, optionvalue, nil)
end
if (fs.is_file(file)) then
fs.write_file(file, table.concat(new_conf_file, '\n'))
else
file = table.concat(new_conf_file, '\n')
end
return true, "File has been modified!", nil, file
end
-- Parse file for name=value pairs, returned in a table
-- If search_section is defined, only report values in matching section
-- If search_name is defined, only report matching name (possibly in multiple sections)
-- If to_table is true, attempt to convert value string to array of options
-- If filter is defined (and table is true), only list option matching filter
function getoptsfromfile (file, search_section, search_name, to_table, filter)
if not file or file == "" then
return nil
end
local opts = nil
local conf_file = {}
if (fs.is_file(file)) then
conf_file = fs.read_file_as_array ( file )
else
for line in string.gmatch(file, "([^\n]*)\n") do
conf_file[#conf_file + 1] = line
end
local extra = string.match(file,"([^\n]*)$")
if extra ~= "" then
conf_file[#conf_file + 1] = extra
end
end
local section = ""
local skip_lines = 0
for i,l in ipairs(conf_file) do
if skip_lines>0 then
skip_lines = skip_lines-1
-- check if comment line
elseif not string.find ( l, "^%s*#" ) then
-- first, concat lines
local j = 1
while string.find ( l, "\\%s*$" ) and conf_file[i+j] do
l = string.match ( l, "^(.*)\\%s*$" ) .. " " .. conf_file[i+j]
j = j+1
end
if j>1 then skip_lines = j-1 end
-- find section name
local a = string.match ( l, "^%s*%[%s*(%S+)%s*%]" )
if a then
section = a
elseif not (search_section) or (search_section == section) then
-- find name
a = string.match ( l, "^%s*(%S+)%s*=" )
if a and (not (search_name) or (search_name == a)) then
-- Figure out the value
local b = string.match ( l, '^%s*%S+%s*%=%s*(.*)$' ) or ""
-- remove comments from end of line
if string.find ( b, '#' ) then
b = string.match ( b, '^(.*)#.*$' ) or ""
end
-- remove spaces from front and back
b = string.match ( b, '^%s*(.*%S)%s*$' ) or ""
-- finally, remove quotes
if #b > 1 and string.sub(b,1,1) == '"' and string.sub(b,-1) == '"' then
b = string.sub(b,2,-2) or ""
end
if to_table == true then
local optstable = opts_to_table(b,filter)
if (optstable) then
if not (opts) then opts = {} end
if not (opts[section]) then opts[section] = {} end
opts[section][a] = optstable
---[[ Next line is DEBUG info. Should be commented out!
--opts[a]["debug"] = b
-- End debug info. --]]
end
else
if not (opts) then opts = {} end
if not (opts[section]) then opts[section] = {} end
opts[section][a] = b
end
end
end
end
end
if opts and search_section and search_name then
return opts[search_section][search_name]
elseif opts and search_section then
return opts[search_section]
end
return opts
end
function getsection (file, search_section)
if not file or file == "" then
return nil
end
search_section = search_section or ""
local conf_file = {}
if (fs.is_file(file)) then
conf_file = fs.read_file_as_array ( file )
else
for line in string.gmatch(file, "([^\n]*)\n") do
conf_file[#conf_file + 1] = line
end
local extra = string.match(file,"([^\n]*)$")
if extra ~= "" then
conf_file[#conf_file + 1] = extra
end
end
local sectionlines = {}
local section = ""
for i,l in ipairs(conf_file) do
-- find section name
local a = string.match ( l, "^%s*%[%s*(%S+)%s*%]" )
if a then
if (search_section == section) then break end
section = a
elseif (search_section == section) then
sectionlines[#sectionlines + 1] = l
end
end
return table.concat(sectionlines, "\n")
end
function setsection (file, search_section, section_content)
if not file then
return false, nil, "Invalid input for getopts.setoptsinfile()", file
end
search_section = search_section or ""
local conf_file = {}
if (fs.is_file(file)) then
conf_file = fs.read_file_as_array ( file )
else
for line in string.gmatch(file, "([^\n]*)\n") do
conf_file[#conf_file + 1] = line
end
local extra = string.match(file,"([^\n]*)$")
if extra ~= "" then
conf_file[#conf_file + 1] = extra
end
end
local new_conf_file = {}
local done = false
local section = ""
for i,l in ipairs(conf_file) do
-- find section name
if not done then
local a = string.match ( l, "^%s*%[%s*(%S+)%s*%]" )
if a then
if (search_section == section) then
done = true
else
section = a
if (search_section == section) then
l = l .. "\n" .. (section_content or "")
end
end
elseif (search_section == section) then
l = nil
end
end
new_conf_file[#new_conf_file + 1] = l
end
if not done then
-- we didn't find the section, add it now
new_conf_file[#new_conf_file + 1] = '[' .. search_section .. ']\n' .. (section_content or "")
end
if (fs.is_file(file)) then
fs.write_file(file, table.concat(new_conf_file, '\n'))
else
file = table.concat(new_conf_file, '\n')
end
return true, "File has been modified!", nil, file
end
|