Last active
August 21, 2025 09:38
-
-
Save magicoal-nerb/4f4d9f79acc2a03a2b00659eb9204737 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- pprint.lua | |
| -- suprisingly fast for being a non-tail call optimized | |
| -- pretty printer. huh neat | |
| -- poopbarrel/magicoal_nerb :^) | |
| local function pprintHelper(buff, value, depth) | |
| -- >_> | |
| local t = type(value) | |
| if t == "string" then | |
| -- string | |
| table.insert(buff, '"') | |
| table.insert(buff, value) | |
| return table.insert(buff, '"') | |
| elseif t == "number" then | |
| -- number | |
| return table.insert(buff, string.format("%.3f", value)) | |
| elseif t ~= "table" then | |
| -- not a table | |
| return table.insert(buff, tostring(t)) | |
| elseif not select(2, next(value)) then | |
| -- empty | |
| return table.insert(buff, '{ }') | |
| elseif #value ~= 0 then | |
| -- list | |
| table.insert(buff, '{ ') | |
| local length = #value | |
| for i = 1, length - 1 do | |
| pprintHelper(buff, value[i], depth) | |
| table.insert(buff, ', ') | |
| end | |
| pprintHelper(buff, value[length], depth) | |
| return table.insert(buff, ' }') | |
| end | |
| table.insert(buff, '{\n') | |
| -- dictionary | |
| local tab = string.rep('\t', depth) | |
| for name, v in pairs(value)do | |
| table.insert(buff, tab) | |
| pprintHelper(buff, name, depth+1) | |
| table.insert(buff, ': ') | |
| pprintHelper(buff, v, depth + 1) | |
| table.insert(buff, '\n') | |
| end | |
| table.insert(buff, string.rep('\t', depth-1)) | |
| table.insert(buff, '}') | |
| end | |
| return function(x) | |
| local buff = {} | |
| pprintHelper(buff, x, 1, {}) | |
| print(table.concat(buff)) | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- pprint.luau | |
| -- faster implementation specific to luau | |
| -- magicoal_nerb :^) | |
| local Buffer = {} | |
| Buffer.__index = Buffer | |
| export type Buffer = typeof(setmetatable({} :: { | |
| data: buffer, | |
| size: number, | |
| cursor: number, | |
| }, Buffer)) | |
| local pprintBuiltin = { | |
| ["number"] = function(depth, data, value) | |
| local round = math.floor(value) | |
| if math.abs(value - round) < 1e-3 then | |
| -- Then it's an integer | |
| return data:writestring(string.format("%d", value)) | |
| else | |
| -- Then it's a decimal number | |
| return data:writestring(string.format("%.2f", value)) | |
| end | |
| end, | |
| ["boolean"] = function(depth, data, value) | |
| -- Booleans can be true or false | |
| return data:writestring(if value then "true" else "false") | |
| end, | |
| ["Vector3"] = function(depth, data, value) | |
| -- It's a Vector3 | |
| return data:writestring(string.format("Vector3.new(%.2f, %.2f, %.2f)", value.X, value.Y, value.Z)) | |
| end, | |
| ["Vector2"] = function(depth, data, value) | |
| -- It's a Vector2 | |
| return data:writestring(string.format("Vector2.new(%.2f, %.2f)", value.X, value.Y)) | |
| end, | |
| ["Color3"] = function(depth, data, value) | |
| -- It's a Color3 | |
| return data:writestring(string.format("Color3.fromRGB(%d, %d, %d)", value.R * 255, value.G * 255, value.B * 255)) | |
| end, | |
| ["string"] = function(depth, data, value) | |
| -- It's a string | |
| return data:writestring(`"{value}"`) | |
| end, | |
| } | |
| local function isalpha(code: number): boolean | |
| -- Checks if the given charcode is a letter | |
| return (code >= 0x41 and code <= 0x5A) | |
| or (code >= 0x61 and code <= 0x7A) | |
| end | |
| local function pprintHelper( | |
| depth: number, | |
| data: Buffer, | |
| value: any | |
| ): number | |
| local t = typeof(value) | |
| local dispatch = pprintBuiltin[t] | |
| if dispatch then | |
| -- One of our builtin readers | |
| return dispatch(depth, data, value) | |
| elseif t ~= "table" then | |
| -- It's a userdata or string | |
| return data:writestring(`"{tostring(value)}"`) | |
| elseif #value ~= 0 then | |
| -- It's a list of values | |
| data:writestring('{ ') | |
| local length = #value | |
| for i, object in value do | |
| -- We're assuming that these are all | |
| -- in a list. Luau allows mixed tables and | |
| -- lists, but this is good enough without compromising | |
| -- speed | |
| pprintHelper(depth + 1, data, object) | |
| if i ~= length then | |
| data:writestring(', ') | |
| end | |
| end | |
| return data:writestring(' }') | |
| elseif not select(1, next(value)) then | |
| -- Empty table | |
| return data:writestring('{ }') | |
| end | |
| -- It's a dictionary | |
| data:writestring('{\n') | |
| for name, v in value do | |
| data:writetabs(depth + 1) | |
| if typeof(name) ~= "string" then | |
| -- Non-string type | |
| data:writestring('[') | |
| pprintHelper(depth + 1, data, name) | |
| data:writestring(']') | |
| elseif isalpha(string.byte(name, 1)) then | |
| -- It's a normal key | |
| data:writestring(name) | |
| else | |
| -- Key that needs a quote around it | |
| data:writestring(`["{name}"]`) | |
| end | |
| -- Create assignment | |
| data:writestring(" = ") | |
| pprintHelper(depth + 1, data, v) | |
| data:writestring(',\n') | |
| end | |
| -- Finalize | |
| data:writetabs(depth) | |
| return data:writestring('}') | |
| end | |
| function Buffer.new(size: number) | |
| -- Constructor for the buffer class | |
| return setmetatable({ | |
| size = size, | |
| data = buffer.create(size), | |
| cursor = 0, | |
| }, Buffer) | |
| end | |
| function Buffer.allocate(self: Buffer, bytes: number) | |
| if self.size >= self.cursor + bytes then | |
| return | |
| end | |
| -- Reallocate with an exponential growth factor. | |
| -- Btw... it's kind of ironic I have to do manual dynamic array | |
| -- creation in a really high level language like lua >_> | |
| local newSize = math.max(2 * self.size, self.size + bytes) | |
| local newBuffer = buffer.create(newSize) | |
| buffer.copy(newBuffer, 0, self.data, 0, self.size) | |
| self.size = newSize | |
| self.data = newBuffer | |
| end | |
| function Buffer.writestring(self: Buffer, str: string) | |
| -- Writes a string onto the buffer | |
| local length = #str | |
| self:allocate(length) | |
| buffer.writestring(self.data, self.cursor, str, length) | |
| self.cursor += length | |
| end | |
| function Buffer.writetabs(self: Buffer, tabs: number) | |
| self:allocate(tabs) | |
| if tabs == 0 then | |
| -- No memset required | |
| return | |
| end | |
| -- Write tabs | |
| buffer.fill(self.data, self.cursor, 0x9, tabs) | |
| self.cursor += tabs | |
| end | |
| function Buffer.tostring(self: Buffer): string | |
| -- Converts the buffer into a string | |
| return buffer.readstring(self.data, 0, self.cursor) | |
| end | |
| return function(value: any, initial: number?): string | |
| -- FYI: doesn't check for cyclic arrays... So beware! | |
| local stream = Buffer.new(initial or 64) | |
| pprintHelper(0, stream, value) | |
| return stream:tostring() | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment