From fb612bb4e2fb59594a9b46dc86990a6d7a4ecee0 Mon Sep 17 00:00:00 2001 From: Derpius <49565664+Derpius@users.noreply.github.com> Date: Sat, 23 Dec 2023 12:42:12 +0000 Subject: [PATCH] Upgrade prettyValue to preview tables --- packages/lest/src/lua/utils/prettyValue.lua | 93 ++++++++++++++++++- .../src/lua/utils/tests/pretty-value.test.lua | 49 ++++++++++ 2 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 packages/lest/src/lua/utils/tests/pretty-value.test.lua diff --git a/packages/lest/src/lua/utils/prettyValue.lua b/packages/lest/src/lua/utils/prettyValue.lua index 8f503fb..bc20cfa 100644 --- a/packages/lest/src/lua/utils/prettyValue.lua +++ b/packages/lest/src/lua/utils/prettyValue.lua @@ -1,7 +1,39 @@ ---- Formats a value to look prettier +local MAX_TABLE_FIELDS = 3 + +--- Iterator function which returns elements in numeric then lexicographic order +---@param tbl table +---@return fun(): any, any +local function sortedPairs(tbl) + local keys = {} + for key in pairs(tbl) do + table.insert(keys, key) + end + + table.sort(keys, function(a, b) + local aIsNumber = type(a) == "number" + local bIsNumber = type(b) == "number" + + if aIsNumber then + return not bIsNumber or a < b + end + + return not bIsNumber and tostring(a) < tostring(b) + end) + + local i = 1 + return function() + local key = keys[i] + if key ~= nil then + i = i + 1 + return key, tbl[key] + end + end +end + +--- Renders a primitive value, or table with tostring ---@param value any ---@return string -return function(value) +local function renderPrimitive(value) if type(value) == "string" then return '"' .. value .. '"' end @@ -20,3 +52,60 @@ return function(value) return tostring(value) end + +--- Renders an inline truncated table +---@param tbl table +---@return string +local function renderTable(tbl) + local renderedFields = {} + local totalFields = 0 + + for key, value in sortedPairs(tbl) do + if #renderedFields < MAX_TABLE_FIELDS then + if type(key) == "number" then + table.insert(renderedFields, renderPrimitive(value)) + elseif + type(key) == "string" and string.match(key, "^[_%a][_%a%d]*$") + then + table.insert( + renderedFields, + string.format("%s = %s", key, renderPrimitive(value)) + ) + else + table.insert( + renderedFields, + string.format( + "[%s] = %s", + renderPrimitive(key), + renderPrimitive(value) + ) + ) + end + end + + totalFields = totalFields + 1 + end + + if #renderedFields < totalFields then + table.insert( + renderedFields, + string.format("...%d more", totalFields - #renderedFields) + ) + end + + return string.format("{ %s }", table.concat(renderedFields, ", ")) +end + +--- Formats a value to look prettier +---@param value any +---@return string +return function(value) + if + type(value) == "table" + and string.match(tostring(value), "table: [%a%d]+") + then + return renderTable(value) + end + + return renderPrimitive(value) +end diff --git a/packages/lest/src/lua/utils/tests/pretty-value.test.lua b/packages/lest/src/lua/utils/tests/pretty-value.test.lua new file mode 100644 index 0000000..c11a26c --- /dev/null +++ b/packages/lest/src/lua/utils/tests/pretty-value.test.lua @@ -0,0 +1,49 @@ +local prettyValue = require("utils.prettyValue") + +test.each({ + { "string", "foo", [["foo"]] }, + { "number", 123, [[123]] }, + { "boolean", true, [[true]] }, + { "positive infinity", math.huge, [[inf]] }, + { "negative infinity", -math.huge, [[-inf]] }, + { "NaN", 0 / 0, [[NaN]] }, + { + "table with tostring metamethod", + setmetatable({}, { + __tostring = function() + return "Blah" + end, + }), + [[Blah]], + }, + { "array-like table", { 1, "foo", 3 }, [[{ 1, "foo", 3 }]] }, + { + "object-like table", + { foo = true, ["b-ar"] = false }, + [[{ ["b-ar"] = false, foo = true }]], + }, + { + "mixed table", + { 1, foo = 2, [true] = 3 }, + [[{ 1, foo = 2, [true] = 3 }]], + }, + { + "truncated array-like table", + { 1, 2, 3, 4, 5 }, + [[{ 1, 2, 3, ...2 more }]], + }, + { + "truncated object-like table", + { a = 1, ["b"] = 2, ["c-"] = 3, d = 4 }, + [[{ a = 1, b = 2, ["c-"] = 3, ...1 more }]], + }, + { + "truncated mixed table", + { 1, foo = "bar", 2, 3, 4, 5, 6 }, + [[{ 1, 2, 3, ...4 more }]], + }, +})("prettifies %s", function(_, value, expected) + local rendered = prettyValue(value) + + expect(rendered).toBe(expected) +end)