Comparison

core/configmanager.lua @ 13626:ac60c21015c7

core.configmanager: Add ways to read config values from files Inspired by something MattJ said Allows retrieving config values from files which are expected to be relative to the config directory, extending on the ENV_ method of retrieving config values from outside the config file. - FileLine retrieves the first line, stripping any trailing newline - FileContents reads the whole file - FileLines reads lines into an array
author Kim Alvefur <zash@zash.se>
date Thu, 16 Jan 2025 15:05:00 +0100
parent 13391:5c783cf58ae7
child 13627:2db7b3b65363
comparison
equal deleted inserted replaced
13625:ff13dd315e68 13626:ac60c21015c7
159 159
160 error("Invalid syntax - missing '=' perhaps?", 2); 160 error("Invalid syntax - missing '=' perhaps?", 2);
161 end; 161 end;
162 }; 162 };
163 163
164 -- For reading config values out of files.
165 local function filereader(basepath, defaultmode)
166 return function(filename, mode)
167 local f, err = io.open(resolve_relative_path(basepath, filename));
168 if not f then error(err, 2); end
169 local content, err = f:read(mode or defaultmode);
170 f:close();
171 if not content then error(err, 2); end
172 return content;
173 end
174 end
175
176 -- Collect lines into an array
177 local function linereader(basepath)
178 return function(filename)
179 local ret = {};
180 for line in io.lines(resolve_relative_path(basepath, filename)) do
181 t_insert(ret, line);
182 end
183 return ret;
184 end
185 end
186
164 parser = {}; 187 parser = {};
165 function parser.load(data, config_file, config_table) 188 function parser.load(data, config_file, config_table)
166 local set_options = {}; -- set_options[host.."/"..option_name] = true (when the option has been set already in this file) 189 local set_options = {}; -- set_options[host.."/"..option_name] = true (when the option has been set already in this file)
167 local warnings = {}; 190 local warnings = {};
168 local env; 191 local env;
192 local config_path = config_file:gsub("[^"..path_sep.."]+$", "");
193
169 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below 194 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below
170 env = setmetatable({ 195 env = setmetatable({
171 Host = true, host = true, VirtualHost = true, 196 Host = true, host = true, VirtualHost = true,
172 Component = true, component = true, 197 Component = true, component = true,
198 FileContents = true,
199 FileLine = true,
200 FileLines = true,
173 Include = true, include = true, RunScript = true }, { 201 Include = true, include = true, RunScript = true }, {
174 __index = function (_, k) 202 __index = function (_, k)
175 if k:match("^ENV_") then 203 if k:match("^ENV_") then
176 return os.getenv(k:sub(5)); 204 return os.getenv(k:sub(5));
177 end 205 end
291 if not lfs then 319 if not lfs then
292 error(format("Error expanding wildcard pattern in Include %q - LuaFileSystem not available", file)); 320 error(format("Error expanding wildcard pattern in Include %q - LuaFileSystem not available", file));
293 end 321 end
294 local path_pos, glob = file:match("()([^"..path_sep.."]+)$"); 322 local path_pos, glob = file:match("()([^"..path_sep.."]+)$");
295 local path = file:sub(1, math_max(path_pos-2,0)); 323 local path = file:sub(1, math_max(path_pos-2,0));
296 local config_path = config_file:gsub("[^"..path_sep.."]+$", "");
297 if #path > 0 then 324 if #path > 0 then
298 path = resolve_relative_path(config_path, path); 325 path = resolve_relative_path(config_path, path);
299 else 326 else
300 path = config_path; 327 path = config_path;
301 end 328 end
306 end 333 end
307 end 334 end
308 return; 335 return;
309 end 336 end
310 -- Not a wildcard, so resolve (potentially) relative path and run through config parser 337 -- Not a wildcard, so resolve (potentially) relative path and run through config parser
311 file = resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file); 338 file = resolve_relative_path(config_path, file);
312 local f, err = io.open(file); 339 local f, err = io.open(file);
313 if f then 340 if f then
314 local ret, err = parser.load(f:read("*a"), file, config_table); 341 local ret, err = parser.load(f:read("*a"), file, config_table);
315 if not ret then error(err:gsub("%[string.-%]", file), 0); end 342 if not ret then error(err:gsub("%[string.-%]", file), 0); end
316 if err then 343 if err then
323 return f, err; 350 return f, err;
324 end 351 end
325 env.include = env.Include; 352 env.include = env.Include;
326 353
327 function env.RunScript(file) 354 function env.RunScript(file)
328 return dofile(resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file)); 355 return dofile(resolve_relative_path(config_path, file));
329 end 356 end
357
358 env.FileContents = filereader(config_path, "*a");
359 env.FileLine = filereader(config_path, "*l");
360 env.FileLines = linereader(config_path);
330 361
331 local chunk, err = envload(data, "@"..config_file, env); 362 local chunk, err = envload(data, "@"..config_file, env);
332 363
333 if not chunk then 364 if not chunk then
334 return nil, err; 365 return nil, err;