util/interpolation.lua
author Kim Alvefur <zash@zash.se>
Sun, 24 Mar 2024 20:39:42 +0100
changeset 13466 720aed1f5cf2
parent 11311 f2e276bb4ef8
permissions -rw-r--r--
util.startup: Check root after detecting platform and reading config (thanks SigmaTel71) Ensures that startup.detect_platform() runs so know whether to use the POSIX method of checking the current user or something else. Also after reading the config so we know whether the root override setting is set.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6723
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     1
-- Simple template language
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     2
--
6774
60957dd5b41b util.{interpolation,prosodyctl,sql}: Trim trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 6723
diff changeset
     3
-- The new() function takes a pattern and an escape function and returns
6723
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     4
-- a render() function.  Both are required.
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     5
--
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     6
-- The function render() takes a string template and a table of values.
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     7
-- Sequences like {name} in the template string are substituted
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     8
-- with values from the table, optionally depending on a modifier
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     9
-- symbol.
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    10
--
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    11
-- Variants are:
6774
60957dd5b41b util.{interpolation,prosodyctl,sql}: Trim trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 6723
diff changeset
    12
-- {name} is substituted for values["name"] and is escaped using the
6723
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    13
-- second argument to new_render().  To disable the escaping, use {name!}.
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    14
-- {name.item} can be used to access table items.
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    15
-- To renter lists of items: {name# item number {idx} is {item} }
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    16
-- Or key-value pairs: {name% t[ {idx} ] = {item} }
6774
60957dd5b41b util.{interpolation,prosodyctl,sql}: Trim trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 6723
diff changeset
    17
-- To show a defaults for missing values {name? sub-template } can be used,
6723
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    18
-- which renders a sub-template if values["name"] is false-ish.
6774
60957dd5b41b util.{interpolation,prosodyctl,sql}: Trim trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 6723
diff changeset
    19
-- {name& sub-template } does the opposite, the sub-template is rendered
6723
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    20
-- if the selected value is anything but false or nil.
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    21
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    22
local type, tostring = type, tostring;
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    23
local pairs, ipairs = pairs, ipairs;
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    24
local s_sub, s_gsub, s_match = string.sub, string.gsub, string.match;
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    25
local t_concat = table.concat;
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    26
6775
805baeca56b6 util.interpolation: Add support for filter functions
Kim Alvefur <zash@zash.se>
parents: 6774
diff changeset
    27
local function new_render(pat, escape, funcs)
6723
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    28
	-- assert(type(pat) == "string", "bad argument #1 to 'new_render' (string expected)");
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    29
	-- assert(type(escape) == "function", "bad argument #2 to 'new_render' (function expected)");
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    30
	local function render(template, values)
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    31
		-- assert(type(template) == "string", "bad argument #1 to 'render' (string expected)");
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    32
		-- assert(type(values) == "table", "bad argument #2 to 'render' (table expected)");
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    33
		return (s_gsub(template, pat, function (block)
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    34
			block = s_sub(block, 2, -2);
10352
3852fc91b2fc util.interpolation: Support unescaped variables with more modifiers (fixes #1452)
Kim Alvefur <zash@zash.se>
parents: 6775
diff changeset
    35
			local name, raw, opt, e = s_match(block, "^([%a_][%w_.]*)(!?)(%p?)()");
6723
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    36
			if not name then return end
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    37
			local value = values[name];
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    38
			if not value and name:find(".", 2, true) then
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    39
				value = values;
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    40
				for word in name:gmatch"[^.]+" do
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    41
					value = value[word];
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    42
					if not value then break; end
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    43
				end
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    44
			end
6775
805baeca56b6 util.interpolation: Add support for filter functions
Kim Alvefur <zash@zash.se>
parents: 6774
diff changeset
    45
			if funcs then
11310
5798ab735619 util.interpolation: Fix combination of filters and fallback values #1623
Kim Alvefur <zash@zash.se>
parents: 10352
diff changeset
    46
				while opt == '|' do
6775
805baeca56b6 util.interpolation: Add support for filter functions
Kim Alvefur <zash@zash.se>
parents: 6774
diff changeset
    47
					local f;
10352
3852fc91b2fc util.interpolation: Support unescaped variables with more modifiers (fixes #1452)
Kim Alvefur <zash@zash.se>
parents: 6775
diff changeset
    48
					f, raw, opt, e = s_match(block, "^([%a_][%w_.]*)(!?)(%p?)()", e);
6775
805baeca56b6 util.interpolation: Add support for filter functions
Kim Alvefur <zash@zash.se>
parents: 6774
diff changeset
    49
					f = funcs[f];
11310
5798ab735619 util.interpolation: Fix combination of filters and fallback values #1623
Kim Alvefur <zash@zash.se>
parents: 10352
diff changeset
    50
					if value ~= nil and f then value = f(value); end
6775
805baeca56b6 util.interpolation: Add support for filter functions
Kim Alvefur <zash@zash.se>
parents: 6774
diff changeset
    51
				end
805baeca56b6 util.interpolation: Add support for filter functions
Kim Alvefur <zash@zash.se>
parents: 6774
diff changeset
    52
			end
6723
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    53
			if opt == '#' or opt == '%' then
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    54
				if type(value) ~= "table" then return ""; end
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    55
				local iter = opt == '#' and ipairs or pairs;
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    56
				local out, i, subtpl = {}, 1, s_sub(block, e);
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    57
				local subvalues = setmetatable({}, { __index = values });
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    58
				for idx, item in iter(value) do
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    59
					subvalues.idx = idx;
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    60
					subvalues.item = item;
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    61
					out[i], i = render(subtpl, subvalues), i+1;
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    62
				end
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    63
				return t_concat(out);
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    64
			elseif opt == '&' then
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    65
				if not value then return ""; end
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    66
				return render(s_sub(block, e), values);
11068
af1e3b7d9ea3 util.interpolation: Add '~' as the opposite of '&' (render sub-block if falsy)
Matthew Wild <mwild1@gmail.com>
parents: 10352
diff changeset
    67
			elseif opt == '~' then
af1e3b7d9ea3 util.interpolation: Add '~' as the opposite of '&' (render sub-block if falsy)
Matthew Wild <mwild1@gmail.com>
parents: 10352
diff changeset
    68
				if value then return ""; end
af1e3b7d9ea3 util.interpolation: Add '~' as the opposite of '&' (render sub-block if falsy)
Matthew Wild <mwild1@gmail.com>
parents: 10352
diff changeset
    69
				return render(s_sub(block, e), values);
6723
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    70
			elseif opt == '?' and not value then
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    71
				return render(s_sub(block, e), values);
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    72
			elseif value ~= nil then
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    73
				if type(value) ~= "string" then
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    74
					value = tostring(value);
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    75
				end
10352
3852fc91b2fc util.interpolation: Support unescaped variables with more modifiers (fixes #1452)
Kim Alvefur <zash@zash.se>
parents: 6775
diff changeset
    76
				if raw ~= '!' then
6723
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    77
					return escape(value);
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    78
				end
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    79
				return value;
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    80
			end
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    81
		end));
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    82
	end
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    83
	return render;
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    84
end
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    85
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    86
return {
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    87
	new = new_render;
936cf2f7531f util.interpolation: A template engine for text
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    88
};