view util/argparse.lua @ 14066:b085d32af140 13.0

prosody, prosodyctl: Load loader directly from source directory This should ensure that loader.lua is loaded from the source directory and does the right thing when installed with `make install` There are currently three ways Prosody can be run: - Directly from the source directory, like `./prosody` - Installed with `make install` - Installed into Lua paths with e.g. dh-lua or luarocks In the first two cases, Lua search paths need to include the source directory and ensure that `require "prosody.util.json"` ends up loading `util/json.lua` relative to the installation (CFG_SOURCEDIR) or the source checkout. Finally, in the last case where Prosody resources are installed under the 'prosody.*' namespace in regular Lua search paths, then loader.lua should activate the compatibility mode that makes sure that both `require"util.json"` and `require"prosody.util.json"` both resolve to `(one path from of package.path)/prosody/util/json.lua`
author Kim Alvefur <zash@zash.se>
date Mon, 09 Feb 2026 16:59:42 +0100
parents 81856814d74f
children aac30c5ee334
line wrap: on
line source

local function parse(arg, config)
	local short_params = config and config.short_params or {};
	local value_params = config and config.value_params or {};
	local array_params = config and config.array_params or {};
	local kv_params = config and config.kv_params or {};
	local strict = config and config.strict;
	local stop_on_positional = not config or config.stop_on_positional ~= false;

	local parsed_opts = {};

	if #arg == 0 then
		return parsed_opts;
	end
	while true do
		local raw_param = arg[1];
		if not raw_param then
			break;
		end

		local prefix = raw_param:match("^%-%-?");
		if not prefix and stop_on_positional then
			break;
		elseif prefix == "--" and raw_param == "--" then
			table.remove(arg, 1);
			break;
		end

		if prefix then
			local param = table.remove(arg, 1):sub(#prefix+1);
			if #param == 1 and short_params then
				param = short_params[param];
			end

			if not param then
				return nil, "param-not-found", raw_param;
			end

			local uparam = param:match("^[^=]*"):gsub("%-", "_");

			local param_k, param_v;
			if value_params[uparam] or array_params[uparam] then
				param_k = uparam;
				param_v = param:match("^=(.*)$", #uparam+1);
				if not param_v then
					param_v = table.remove(arg, 1);
					if not param_v then
						return nil, "missing-value", raw_param;
					end
				end
			else
				param_k, param_v = param:match("^([^=]+)=(.+)$");
				if not param_k then
					if param:match("^no%-") then
						param_k, param_v = param:sub(4), false;
					else
						param_k, param_v = param, true;
					end
				end
				param_k = param_k:gsub("%-", "_");
				if strict and not kv_params[param_k] then
					return nil, "param-not-found", raw_param;
				end
			end
			if array_params[uparam] then
				if parsed_opts[param_k] then
					table.insert(parsed_opts[param_k], param_v);
				else
					parsed_opts[param_k] = { param_v };
				end
			else
				parsed_opts[param_k] = param_v;
			end
		elseif not stop_on_positional then
			table.insert(parsed_opts, table.remove(arg, 1));
		end
	end

	if stop_on_positional then
		for i = 1, #arg do
			parsed_opts[i] = arg[i];
		end
	end

	return parsed_opts;
end

return {
	parse = parse;
}