diff options
-rw-r--r-- | spec/util_format_spec.lua | 1 | ||||
-rw-r--r-- | util/format.lua | 58 |
2 files changed, 38 insertions, 21 deletions
diff --git a/spec/util_format_spec.lua b/spec/util_format_spec.lua index 8d6ba8ad..0e6a36b7 100644 --- a/spec/util_format_spec.lua +++ b/spec/util_format_spec.lua @@ -18,6 +18,7 @@ describe("util.format", function() it("escapes ascii control stuff", function () assert.equal("␁", format("%s", "\1")); + assert.equal("[␁]", format("%d", "\1")); end); it("escapes invalid UTF-8", function () diff --git a/util/format.lua b/util/format.lua index d452fd3d..8168ccaa 100644 --- a/util/format.lua +++ b/util/format.lua @@ -49,36 +49,52 @@ local function format(formatstring, ...) -- process each format specifier local i = 0; formatstring = formatstring:gsub("%%[^cdiouxXaAeEfgGqs%%]*[cdiouxXaAeEfgGqs%%]", function(spec) - if spec ~= "%%" then - i = i + 1; - local arg = args[i]; + if spec == "%%" then return end + i = i + 1; + local arg = args[i]; + + if arg == nil then + args[i] = "nil"; + return "(%s)"; + end + + local option = spec:sub(-1); + local t = type(arg); + + if option == "s" and t == "string" and not arg:find("[%z\1-\31\128-\255]") then + -- No UTF-8 or control characters, assumed to be the common case. + return + end - local option = spec:sub(-1); - if arg == nil then - args[i] = "nil"; - spec = "(%s)"; - elseif option == "q" then - args[i] = dump(arg); - spec = "%s"; - elseif option == "s" then + if option ~= "s" and option ~= "q" then + -- all other options expect numbers + if t ~= "number" then + -- arg isn't number as expected? arg = tostring(arg); - if arg:find("[\128-\255]") and not valid_utf8(arg) then - args[i] = dump(arg); - else - args[i] = arg:gsub("[%z\1-\8\11-\31\127]", control_symbols):gsub("\n\t?", "\n\t"); - end - elseif type(arg) ~= "number" then -- arg isn't number as expected? - args[i] = tostring(arg); - spec = "[%s]"; option = "s"; spec = "[%s]"; t = "string"; elseif expects_integer[option] and num_type(arg) ~= "integer" then args[i] = tostring(arg); - spec = "[%s]"; + return "[%s]"; + else + return -- acceptable number + end + end + + if t == "string" then + if not valid_utf8(arg) then + option = "q"; + else + args[i] = arg:gsub("[%z\1-\8\11-\31\127]", control_symbols):gsub("\n\t?", "\n\t"); + return spec; end end - return spec; + + if option == "q" then + args[i] = dump(arg); + return "%s"; + end end); -- process extra args |