<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://idle-pixel.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3AInspectLua</id>
	<title>Module:InspectLua - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://idle-pixel.wiki/index.php?action=history&amp;feed=atom&amp;title=Module%3AInspectLua"/>
	<link rel="alternate" type="text/html" href="https://idle-pixel.wiki/index.php?title=Module:InspectLua&amp;action=history"/>
	<updated>2026-06-20T11:04:05Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.2</generator>
	<entry>
		<id>https://idle-pixel.wiki/index.php?title=Module:InspectLua&amp;diff=50547&amp;oldid=prev</id>
		<title>Dounford: Created page with &quot;local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) &lt; 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local math = _tl_compat and _tl_compat.math or math; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table local inspect = {Options = {}, }                  inspect._VERSION = 'inspect.lua 3.1.0' inspect._URL = 'http://github.com/kikito/inspect.lua'...&quot;</title>
		<link rel="alternate" type="text/html" href="https://idle-pixel.wiki/index.php?title=Module:InspectLua&amp;diff=50547&amp;oldid=prev"/>
		<updated>2024-03-07T20:59:07Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;local _tl_compat; if (tonumber((_VERSION or &amp;#039;&amp;#039;):match(&amp;#039;[%d.]*$&amp;#039;)) or 0) &amp;lt; 5.3 then local p, m = pcall(require, &amp;#039;compat53.module&amp;#039;); if p then _tl_compat = m end end; local math = _tl_compat and _tl_compat.math or math; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table local inspect = {Options = {}, }                  inspect._VERSION = &amp;#039;inspect.lua 3.1.0&amp;#039; inspect._URL = &amp;#039;http://github.com/kikito/inspect.lua&amp;#039;...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) &amp;lt; 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local math = _tl_compat and _tl_compat.math or math; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table&lt;br /&gt;
local inspect = {Options = {}, }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
inspect._VERSION = 'inspect.lua 3.1.0'&lt;br /&gt;
inspect._URL = 'http://github.com/kikito/inspect.lua'&lt;br /&gt;
inspect._DESCRIPTION = 'human-readable representations of tables'&lt;br /&gt;
inspect._LICENSE = [[&lt;br /&gt;
  MIT LICENSE&lt;br /&gt;
&lt;br /&gt;
  Copyright (c) 2022 Enrique García Cota&lt;br /&gt;
&lt;br /&gt;
  Permission is hereby granted, free of charge, to any person obtaining a&lt;br /&gt;
  copy of this software and associated documentation files (the&lt;br /&gt;
  &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including&lt;br /&gt;
  without limitation the rights to use, copy, modify, merge, publish,&lt;br /&gt;
  distribute, sublicense, and/or sell copies of the Software, and to&lt;br /&gt;
  permit persons to whom the Software is furnished to do so, subject to&lt;br /&gt;
  the following conditions:&lt;br /&gt;
&lt;br /&gt;
  The above copyright notice and this permission notice shall be included&lt;br /&gt;
  in all copies or substantial portions of the Software.&lt;br /&gt;
&lt;br /&gt;
  THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS&lt;br /&gt;
  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF&lt;br /&gt;
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.&lt;br /&gt;
  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY&lt;br /&gt;
  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,&lt;br /&gt;
  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE&lt;br /&gt;
  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
]]&lt;br /&gt;
inspect.KEY = setmetatable({}, { __tostring = function() return 'inspect.KEY' end })&lt;br /&gt;
inspect.METATABLE = setmetatable({}, { __tostring = function() return 'inspect.METATABLE' end })&lt;br /&gt;
&lt;br /&gt;
local tostring = tostring&lt;br /&gt;
local rep = string.rep&lt;br /&gt;
local match = string.match&lt;br /&gt;
local char = string.char&lt;br /&gt;
local gsub = string.gsub&lt;br /&gt;
local fmt = string.format&lt;br /&gt;
&lt;br /&gt;
local _rawget&lt;br /&gt;
if rawget then&lt;br /&gt;
   _rawget = rawget&lt;br /&gt;
else&lt;br /&gt;
   _rawget = function(t, k) return t[k] end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function rawpairs(t)&lt;br /&gt;
   return next, t, nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function smartQuote(str)&lt;br /&gt;
   if match(str, '&amp;quot;') and not match(str, &amp;quot;'&amp;quot;) then&lt;br /&gt;
      return &amp;quot;'&amp;quot; .. str .. &amp;quot;'&amp;quot;&lt;br /&gt;
   end&lt;br /&gt;
   return '&amp;quot;' .. gsub(str, '&amp;quot;', '\\&amp;quot;') .. '&amp;quot;'&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local shortControlCharEscapes = {&lt;br /&gt;
   [&amp;quot;\a&amp;quot;] = &amp;quot;\\a&amp;quot;, [&amp;quot;\b&amp;quot;] = &amp;quot;\\b&amp;quot;, [&amp;quot;\f&amp;quot;] = &amp;quot;\\f&amp;quot;, [&amp;quot;\n&amp;quot;] = &amp;quot;\\n&amp;quot;,&lt;br /&gt;
   [&amp;quot;\r&amp;quot;] = &amp;quot;\\r&amp;quot;, [&amp;quot;\t&amp;quot;] = &amp;quot;\\t&amp;quot;, [&amp;quot;\v&amp;quot;] = &amp;quot;\\v&amp;quot;, [&amp;quot;\127&amp;quot;] = &amp;quot;\\127&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
local longControlCharEscapes = { [&amp;quot;\127&amp;quot;] = &amp;quot;\127&amp;quot; }&lt;br /&gt;
for i = 0, 31 do&lt;br /&gt;
   local ch = char(i)&lt;br /&gt;
   if not shortControlCharEscapes[ch] then&lt;br /&gt;
      shortControlCharEscapes[ch] = &amp;quot;\\&amp;quot; .. i&lt;br /&gt;
      longControlCharEscapes[ch] = fmt(&amp;quot;\\%03d&amp;quot;, i)&lt;br /&gt;
   end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function escape(str)&lt;br /&gt;
   return (gsub(gsub(gsub(str, &amp;quot;\\&amp;quot;, &amp;quot;\\\\&amp;quot;),&lt;br /&gt;
   &amp;quot;(%c)%f[0-9]&amp;quot;, longControlCharEscapes),&lt;br /&gt;
   &amp;quot;%c&amp;quot;, shortControlCharEscapes))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local luaKeywords = {&lt;br /&gt;
   ['and'] = true,&lt;br /&gt;
   ['break'] = true,&lt;br /&gt;
   ['do'] = true,&lt;br /&gt;
   ['else'] = true,&lt;br /&gt;
   ['elseif'] = true,&lt;br /&gt;
   ['end'] = true,&lt;br /&gt;
   ['false'] = true,&lt;br /&gt;
   ['for'] = true,&lt;br /&gt;
   ['function'] = true,&lt;br /&gt;
   ['goto'] = true,&lt;br /&gt;
   ['if'] = true,&lt;br /&gt;
   ['in'] = true,&lt;br /&gt;
   ['local'] = true,&lt;br /&gt;
   ['nil'] = true,&lt;br /&gt;
   ['not'] = true,&lt;br /&gt;
   ['or'] = true,&lt;br /&gt;
   ['repeat'] = true,&lt;br /&gt;
   ['return'] = true,&lt;br /&gt;
   ['then'] = true,&lt;br /&gt;
   ['true'] = true,&lt;br /&gt;
   ['until'] = true,&lt;br /&gt;
   ['while'] = true,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local function isIdentifier(str)&lt;br /&gt;
   return type(str) == &amp;quot;string&amp;quot; and&lt;br /&gt;
   not not str:match(&amp;quot;^[_%a][_%a%d]*$&amp;quot;) and&lt;br /&gt;
   not luaKeywords[str]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local flr = math.floor&lt;br /&gt;
local function isSequenceKey(k, sequenceLength)&lt;br /&gt;
   return type(k) == &amp;quot;number&amp;quot; and&lt;br /&gt;
   flr(k) == k and&lt;br /&gt;
   1 &amp;lt;= (k) and&lt;br /&gt;
   k &amp;lt;= sequenceLength&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local defaultTypeOrders = {&lt;br /&gt;
   ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4,&lt;br /&gt;
   ['function'] = 5, ['userdata'] = 6, ['thread'] = 7,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local function sortKeys(a, b)&lt;br /&gt;
   local ta, tb = type(a), type(b)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   if ta == tb and (ta == 'string' or ta == 'number') then&lt;br /&gt;
      return (a) &amp;lt; (b)&lt;br /&gt;
   end&lt;br /&gt;
&lt;br /&gt;
   local dta = defaultTypeOrders[ta] or 100&lt;br /&gt;
   local dtb = defaultTypeOrders[tb] or 100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   return dta == dtb and ta &amp;lt; tb or dta &amp;lt; dtb&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function getKeys(t)&lt;br /&gt;
&lt;br /&gt;
   local seqLen = 1&lt;br /&gt;
   while _rawget(t, seqLen) ~= nil do&lt;br /&gt;
      seqLen = seqLen + 1&lt;br /&gt;
   end&lt;br /&gt;
   seqLen = seqLen - 1&lt;br /&gt;
&lt;br /&gt;
   local keys, keysLen = {}, 0&lt;br /&gt;
   for k in rawpairs(t) do&lt;br /&gt;
      if not isSequenceKey(k, seqLen) then&lt;br /&gt;
         keysLen = keysLen + 1&lt;br /&gt;
         keys[keysLen] = k&lt;br /&gt;
      end&lt;br /&gt;
   end&lt;br /&gt;
   table.sort(keys, sortKeys)&lt;br /&gt;
   return keys, keysLen, seqLen&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function countCycles(x, cycles)&lt;br /&gt;
   if type(x) == &amp;quot;table&amp;quot; then&lt;br /&gt;
      if cycles[x] then&lt;br /&gt;
         cycles[x] = cycles[x] + 1&lt;br /&gt;
      else&lt;br /&gt;
         cycles[x] = 1&lt;br /&gt;
         for k, v in rawpairs(x) do&lt;br /&gt;
            countCycles(k, cycles)&lt;br /&gt;
            countCycles(v, cycles)&lt;br /&gt;
         end&lt;br /&gt;
         countCycles(getmetatable(x), cycles)&lt;br /&gt;
      end&lt;br /&gt;
   end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makePath(path, a, b)&lt;br /&gt;
   local newPath = {}&lt;br /&gt;
   local len = #path&lt;br /&gt;
   for i = 1, len do newPath[i] = path[i] end&lt;br /&gt;
&lt;br /&gt;
   newPath[len + 1] = a&lt;br /&gt;
   newPath[len + 2] = b&lt;br /&gt;
&lt;br /&gt;
   return newPath&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function processRecursive(process,&lt;br /&gt;
   item,&lt;br /&gt;
   path,&lt;br /&gt;
   visited)&lt;br /&gt;
   if item == nil then return nil end&lt;br /&gt;
   if visited[item] then return visited[item] end&lt;br /&gt;
&lt;br /&gt;
   local processed = process(item, path)&lt;br /&gt;
   if type(processed) == &amp;quot;table&amp;quot; then&lt;br /&gt;
      local processedCopy = {}&lt;br /&gt;
      visited[item] = processedCopy&lt;br /&gt;
      local processedKey&lt;br /&gt;
&lt;br /&gt;
      for k, v in rawpairs(processed) do&lt;br /&gt;
         processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)&lt;br /&gt;
         if processedKey ~= nil then&lt;br /&gt;
            processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)&lt;br /&gt;
         end&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
      local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)&lt;br /&gt;
      if type(mt) ~= 'table' then mt = nil end&lt;br /&gt;
      setmetatable(processedCopy, mt)&lt;br /&gt;
      processed = processedCopy&lt;br /&gt;
   end&lt;br /&gt;
   return processed&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function puts(buf, str)&lt;br /&gt;
   buf.n = buf.n + 1&lt;br /&gt;
   buf[buf.n] = str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local Inspector = {}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local Inspector_mt = { __index = Inspector }&lt;br /&gt;
&lt;br /&gt;
local function tabify(inspector)&lt;br /&gt;
   puts(inspector.buf, inspector.newline .. rep(inspector.indent, inspector.level))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Inspector:getId(v)&lt;br /&gt;
   local id = self.ids[v]&lt;br /&gt;
   local ids = self.ids&lt;br /&gt;
   if not id then&lt;br /&gt;
      local tv = type(v)&lt;br /&gt;
      id = (ids[tv] or 0) + 1&lt;br /&gt;
      ids[v], ids[tv] = id, id&lt;br /&gt;
   end&lt;br /&gt;
   return tostring(id)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Inspector:putValue(v)&lt;br /&gt;
   local buf = self.buf&lt;br /&gt;
   local tv = type(v)&lt;br /&gt;
   if tv == 'string' then&lt;br /&gt;
      puts(buf, smartQuote(escape(v)))&lt;br /&gt;
   elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or&lt;br /&gt;
      tv == 'cdata' or tv == 'ctype' then&lt;br /&gt;
      puts(buf, tostring(v))&lt;br /&gt;
   elseif tv == 'table' and not self.ids[v] then&lt;br /&gt;
      local t = v&lt;br /&gt;
&lt;br /&gt;
      if t == inspect.KEY or t == inspect.METATABLE then&lt;br /&gt;
         puts(buf, tostring(t))&lt;br /&gt;
      elseif self.level &amp;gt;= self.depth then&lt;br /&gt;
         puts(buf, '{...}')&lt;br /&gt;
      else&lt;br /&gt;
         if self.cycles[t] &amp;gt; 1 then puts(buf, fmt('&amp;lt;%d&amp;gt;', self:getId(t))) end&lt;br /&gt;
&lt;br /&gt;
         local keys, keysLen, seqLen = getKeys(t)&lt;br /&gt;
&lt;br /&gt;
         puts(buf, '{')&lt;br /&gt;
         self.level = self.level + 1&lt;br /&gt;
&lt;br /&gt;
         for i = 1, seqLen + keysLen do&lt;br /&gt;
            if i &amp;gt; 1 then puts(buf, ',') end&lt;br /&gt;
            if i &amp;lt;= seqLen then&lt;br /&gt;
               puts(buf, ' ')&lt;br /&gt;
               self:putValue(t[i])&lt;br /&gt;
            else&lt;br /&gt;
               local k = keys[i - seqLen]&lt;br /&gt;
               tabify(self)&lt;br /&gt;
               if isIdentifier(k) then&lt;br /&gt;
                  puts(buf, k)&lt;br /&gt;
               else&lt;br /&gt;
                  puts(buf, &amp;quot;[&amp;quot;)&lt;br /&gt;
                  self:putValue(k)&lt;br /&gt;
                  puts(buf, &amp;quot;]&amp;quot;)&lt;br /&gt;
               end&lt;br /&gt;
               puts(buf, ' = ')&lt;br /&gt;
               self:putValue(t[k])&lt;br /&gt;
            end&lt;br /&gt;
         end&lt;br /&gt;
&lt;br /&gt;
         local mt = getmetatable(t)&lt;br /&gt;
         if type(mt) == 'table' then&lt;br /&gt;
            if seqLen + keysLen &amp;gt; 0 then puts(buf, ',') end&lt;br /&gt;
            tabify(self)&lt;br /&gt;
            puts(buf, '&amp;lt;metatable&amp;gt; = ')&lt;br /&gt;
            self:putValue(mt)&lt;br /&gt;
         end&lt;br /&gt;
&lt;br /&gt;
         self.level = self.level - 1&lt;br /&gt;
&lt;br /&gt;
         if keysLen &amp;gt; 0 or type(mt) == 'table' then&lt;br /&gt;
            tabify(self)&lt;br /&gt;
         elseif seqLen &amp;gt; 0 then&lt;br /&gt;
            puts(buf, ' ')&lt;br /&gt;
         end&lt;br /&gt;
&lt;br /&gt;
         puts(buf, '}')&lt;br /&gt;
      end&lt;br /&gt;
&lt;br /&gt;
   else&lt;br /&gt;
      puts(buf, fmt('&amp;lt;%s %d&amp;gt;', tv, self:getId(v)))&lt;br /&gt;
   end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function inspect.inspect(root, options)&lt;br /&gt;
   options = options or {}&lt;br /&gt;
&lt;br /&gt;
   local depth = options.depth or (math.huge)&lt;br /&gt;
   local newline = options.newline or '\n'&lt;br /&gt;
   local indent = options.indent or '  '&lt;br /&gt;
   local process = options.process&lt;br /&gt;
&lt;br /&gt;
   if process then&lt;br /&gt;
      root = processRecursive(process, root, {}, {})&lt;br /&gt;
   end&lt;br /&gt;
&lt;br /&gt;
   local cycles = {}&lt;br /&gt;
   countCycles(root, cycles)&lt;br /&gt;
&lt;br /&gt;
   local inspector = setmetatable({&lt;br /&gt;
      buf = { n = 0 },&lt;br /&gt;
      ids = {},&lt;br /&gt;
      cycles = cycles,&lt;br /&gt;
      depth = depth,&lt;br /&gt;
      level = 0,&lt;br /&gt;
      newline = newline,&lt;br /&gt;
      indent = indent,&lt;br /&gt;
   }, Inspector_mt)&lt;br /&gt;
&lt;br /&gt;
   inspector:putValue(root)&lt;br /&gt;
&lt;br /&gt;
   return table.concat(inspector.buf)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
setmetatable(inspect, {&lt;br /&gt;
   __call = function(_, root, options)&lt;br /&gt;
      return inspect.inspect(root, options)&lt;br /&gt;
   end,&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
return inspect&lt;/div&gt;</summary>
		<author><name>Dounford</name></author>
	</entry>
</feed>