--- a/spec/util_format_spec.lua Sat Dec 11 13:30:34 2021 +0100
+++ b/spec/util_format_spec.lua Sat Dec 11 13:39:58 2021 +0100
@@ -25,5 +25,14 @@
assert.equal("\"Hello w\\195rld\"", format("%s", "Hello w\195rld"));
end);
+ if _VERSION >= "Lua 5.4" then
+ it("handles %p formats", function ()
+ assert.matches("a 0x%x+ b", format("%s %p %s", "a", {}, "b"));
+ end)
+ else
+ it("does something with %p formats", function ()
+ assert.string(format("%p", {}));
+ end)
+ end
end);
end);
--- a/util/format.lua Sat Dec 11 13:30:34 2021 +0100
+++ b/util/format.lua Sat Dec 11 13:39:58 2021 +0100
@@ -29,6 +29,7 @@
["\027"] = "\226\144\155", ["\028"] = "\226\144\156", ["\029"] = "\226\144\157",
["\030"] = "\226\144\158", ["\031"] = "\226\144\159", ["\127"] = "\226\144\161",
};
+local supports_p = pcall(string.format, "%p", "");
local function format(formatstring, ...)
local args = pack(...);
@@ -44,11 +45,12 @@
-- The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as argument, whereas q and s expect a string.
-- This function does not accept string values containing embedded zeros, except as arguments to the q option.
-- a and A are only in Lua 5.2+
+ -- Lua 5.4 adds a p format that produces a pointer
-- process each format specifier
local i = 0;
- formatstring = formatstring:gsub("%%[^cdiouxXaAeEfgGqs%%]*[cdiouxXaAeEfgGqs%%]", function(spec)
+ formatstring = formatstring:gsub("%%[^cdiouxXaAeEfgGpqs%%]*[cdiouxXaAeEfgGpqs%%]", function(spec)
if spec == "%%" then return end
i = i + 1;
local arg = args[i];
@@ -66,7 +68,7 @@
return
end
- if option ~= "s" and option ~= "q" then
+ if option ~= "s" and option ~= "q" and option ~= "p" then
-- all other options expect numbers
if t ~= "number" then
-- arg isn't number as expected?
@@ -82,7 +84,15 @@
end
end
- if t == "string" then
+
+ if option == "p" and not supports_p then
+ arg = tostring(arg);
+ option = "s";
+ spec = "[%s]";
+ t = "string";
+ end
+
+ if t == "string" and option ~= "p" then
if not valid_utf8(arg) then
option = "q";
else
@@ -95,6 +105,11 @@
args[i] = dump(arg);
return "%s";
end
+
+ if option == "p" and (t == "boolean" or t == "number") then
+ args[i] = tostring(arg);
+ return "[%s]";
+ end
end);
-- process extra args