<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://firestone-idle-rpg.de/Modul:Inspect/history?feed=atom</id>
	<title>Modul:Inspect - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://firestone-idle-rpg.de/Modul:Inspect/history?feed=atom"/>
	<link rel="alternate" type="text/html" href="https://firestone-idle-rpg.de/Modul:Inspect/history"/>
	<updated>2026-05-21T21:05:18Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Firestone Idle RPG Wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://firestone-idle-rpg.de/index.php?title=Modul:Inspect&amp;diff=81&amp;oldid=prev</id>
		<title>Webmaster: Die Seite wurde neu angelegt: „--  &lt;nowiki&gt; --- Inspect transforms Lua into a human-readable representation. --  The objective here is human understanding (i.e. for debugging), not --  serialization or compactness. The consistent reconstruction of Lua --  values is not possible from the string representation, because of items --  appearing as `&lt;table&gt;`, `&lt;metatable&gt;` or `&lt;function&gt;` in certain cases. --   --  Historically, this module could serve as a polyfill for the `mw.dumpObject` -…“</title>
		<link rel="alternate" type="text/html" href="https://firestone-idle-rpg.de/index.php?title=Modul:Inspect&amp;diff=81&amp;oldid=prev"/>
		<updated>2023-10-23T22:42:03Z</updated>

		<summary type="html">&lt;p&gt;Die Seite wurde neu angelegt: „--  &amp;lt;nowiki&amp;gt; --- Inspect transforms Lua into a human-readable representation. --  The objective here is human understanding (i.e. for debugging), not --  serialization or compactness. The consistent reconstruction of Lua --  values is not possible from the string representation, because of items --  appearing as `&amp;lt;table&amp;gt;`, `&amp;lt;metatable&amp;gt;` or `&amp;lt;function&amp;gt;` in certain cases. --   --  Historically, this module could serve as a polyfill for the `mw.dumpObject` -…“&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;--  &amp;lt;nowiki&amp;gt;&lt;br /&gt;
--- Inspect transforms Lua into a human-readable representation.&lt;br /&gt;
--  The objective here is human understanding (i.e. for debugging), not&lt;br /&gt;
--  serialization or compactness. The consistent reconstruction of Lua&lt;br /&gt;
--  values is not possible from the string representation, because of items&lt;br /&gt;
--  appearing as `&amp;lt;table&amp;gt;`, `&amp;lt;metatable&amp;gt;` or `&amp;lt;function&amp;gt;` in certain cases.&lt;br /&gt;
--  &lt;br /&gt;
--  Historically, this module could serve as a polyfill for the `mw.dumpObject`&lt;br /&gt;
--  function which was available in Scribunto core but was missing on Fandom.&lt;br /&gt;
--&lt;br /&gt;
--  That function is now available on Fandom as well, though the Inspect library&lt;br /&gt;
--  still provides a few additional features.&lt;br /&gt;
--  &lt;br /&gt;
--  @script             inspect&lt;br /&gt;
--  @author             [[github::kikito|Enrique García Cota]] ([[github:kikito/inspect|Github]])&lt;br /&gt;
--  @author             [[User:DarthKitty|DarthKitty]]&lt;br /&gt;
--  @version            3.1.2+wikia:dev&lt;br /&gt;
--  @release            stable&lt;br /&gt;
--  @see                [[github:kikito/inspect.lua|Original module on Github.]]&lt;br /&gt;
local inspect = {}&lt;br /&gt;
inspect._VERSION = &amp;#039;inspect.lua 3.1.2+wikia:dev&amp;#039;&lt;br /&gt;
inspect._URL = &amp;#039;http://github.com/kikito/inspect.lua&amp;#039;&lt;br /&gt;
inspect._DESCRIPTION = &amp;#039;human-readable representations of tables&amp;#039;&lt;br /&gt;
inspect._LICENSE = [[&lt;br /&gt;
    MIT LICENSE&lt;br /&gt;
&lt;br /&gt;
    Copyright (c) 2013 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;
&lt;br /&gt;
--  Global functions (optimisation).&lt;br /&gt;
local type, rawget, pcall, tostring = type, rawget, pcall, tostring&lt;br /&gt;
local char, format, rep = string.char, string.format, string.rep&lt;br /&gt;
local floor, huge, getmetatable = math.floor, math.huge, getmetatable&lt;br /&gt;
local sort, concat = table.sort, table.concat&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;
--- Apostrophizes the string if it has quotes, but not aphostrophes.&lt;br /&gt;
--  Otherwise, it returns a regular quoted string.&lt;br /&gt;
local function smartQuote(str)&lt;br /&gt;
    if str:match(&amp;#039;&amp;quot;&amp;#039;) and not str:match(&amp;quot;&amp;#039;&amp;quot;) then&lt;br /&gt;
        return &amp;quot;&amp;#039;&amp;quot; .. str .. &amp;quot;&amp;#039;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    return &amp;#039;&amp;quot;&amp;#039; .. str:gsub(&amp;#039;&amp;quot;&amp;#039;, &amp;#039;\\&amp;quot;&amp;#039;) .. &amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Short (alphabetical) control character escape set.&lt;br /&gt;
--  @table              shortControlCharEscapes&lt;br /&gt;
--  @local&lt;br /&gt;
local shortControlCharEscapes = { -- \a =&amp;gt; &amp;#039;\\a&amp;#039;, \0 =&amp;gt; nil&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;
&lt;br /&gt;
--- Long (numerical) control character escape set.&lt;br /&gt;
--  @table              longControlCharEscapes&lt;br /&gt;
--  @local&lt;br /&gt;
local longControlCharEscapes = {[&amp;quot;\127&amp;quot;]=&amp;quot;\127&amp;quot;} -- \a =&amp;gt; nil, \0 =&amp;gt; \000, 31 =&amp;gt; \031&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]  = format(&amp;quot;\\%03d&amp;quot;, i)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
--longControlCharEscapes[&amp;quot;\127&amp;quot;]=&amp;quot;\\127&amp;quot;&lt;br /&gt;
&lt;br /&gt;
--- Escapes string characters with backslashes.&lt;br /&gt;
local function escape(str)&lt;br /&gt;
    return (str:gsub(&amp;quot;\\&amp;quot;, &amp;quot;\\\\&amp;quot;)&lt;br /&gt;
        :gsub(&amp;quot;(%c)%f[0-9]&amp;quot;, longControlCharEscapes)&lt;br /&gt;
        :gsub(&amp;quot;%c&amp;quot;, shortControlCharEscapes))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Whether identifier syntactic sugar can be used for key inspection.&lt;br /&gt;
local function isIdentifier(str)&lt;br /&gt;
    return type(str) == &amp;#039;string&amp;#039; and str:match( &amp;quot;^[_%a][_%a%d]*$&amp;quot; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Whether a key is part of a sequence.&lt;br /&gt;
local function isSequenceKey(k, sequenceLength)&lt;br /&gt;
    return type(k) == &amp;#039;number&amp;#039;&lt;br /&gt;
        and 1 &amp;lt;= k&lt;br /&gt;
        and k &amp;lt;= sequenceLength&lt;br /&gt;
        and floor(k) == k&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Order map for tables key types.&lt;br /&gt;
local defaultTypeOrders = {&lt;br /&gt;
    [&amp;#039;number&amp;#039;]   = 1, [&amp;#039;boolean&amp;#039;]  = 2, [&amp;#039;string&amp;#039;] = 3, [&amp;#039;table&amp;#039;] = 4,&lt;br /&gt;
    [&amp;#039;function&amp;#039;] = 5, [&amp;#039;userdata&amp;#039;] = 6, [&amp;#039;thread&amp;#039;] = 7&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--- Sorts keys by type.&lt;br /&gt;
local function sortKeys(a, b)&lt;br /&gt;
    local ta, tb = type(a), type(b)&lt;br /&gt;
&lt;br /&gt;
    -- strings and numbers are sorted numerically/alphabetically&lt;br /&gt;
    if ta == tb and (ta == &amp;#039;string&amp;#039; or ta == &amp;#039;number&amp;#039;) then return a &amp;lt; b end&lt;br /&gt;
&lt;br /&gt;
    local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]&lt;br /&gt;
    -- Two default types are compared according to the defaultTypeOrders table&lt;br /&gt;
    if dta and dtb then return defaultTypeOrders[ta] &amp;lt; defaultTypeOrders[tb]&lt;br /&gt;
    elseif dta     then return true  -- default types before custom ones&lt;br /&gt;
    elseif dtb     then return false -- custom types after default ones&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- custom types are sorted out alphabetically&lt;br /&gt;
    return ta &amp;lt; tb&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Custom length operator.&lt;br /&gt;
--  For implementation reasons, the behavior of rawlen &amp;amp; # is &amp;quot;undefined&amp;quot; when&lt;br /&gt;
--  tables aren&amp;#039;t pure sequences. So we implement our own # operator.&lt;br /&gt;
local function getSequenceLength(t)&lt;br /&gt;
    local len = 1&lt;br /&gt;
    local v = rawget(t,len)&lt;br /&gt;
    while v ~= nil do&lt;br /&gt;
        len = len + 1&lt;br /&gt;
        v = rawget(t,len)&lt;br /&gt;
    end&lt;br /&gt;
    return len - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Getter for non-sequential key portion of a table.&lt;br /&gt;
local function getNonSequentialKeys(t)&lt;br /&gt;
    local keys, keysLength = {}, 0&lt;br /&gt;
    local sequenceLength = getSequenceLength(t)&lt;br /&gt;
    for k,_ in rawpairs(t) do&lt;br /&gt;
        if not isSequenceKey(k, sequenceLength) then&lt;br /&gt;
            keysLength = keysLength + 1&lt;br /&gt;
            keys[keysLength] = k&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    sort(keys, sortKeys)&lt;br /&gt;
    return keys, keysLength, sequenceLength&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Counter for table appearances for recursive loops in tables.&lt;br /&gt;
local function countTableAppearances(t, tableAppearances)&lt;br /&gt;
    tableAppearances = tableAppearances or {}&lt;br /&gt;
&lt;br /&gt;
    if type(t) == &amp;#039;table&amp;#039; then&lt;br /&gt;
        if not tableAppearances[t] then&lt;br /&gt;
            tableAppearances[t] = 1&lt;br /&gt;
            for k,v in rawpairs(t) do&lt;br /&gt;
                countTableAppearances(k, tableAppearances)&lt;br /&gt;
                countTableAppearances(v, tableAppearances)&lt;br /&gt;
            end&lt;br /&gt;
            countTableAppearances(getmetatable(t), tableAppearances)&lt;br /&gt;
        else&lt;br /&gt;
            tableAppearances[t] = tableAppearances[t] + 1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return tableAppearances&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Creates a copy of a Lua sequence.&lt;br /&gt;
local copySequence = function(s)&lt;br /&gt;
    local copy, len = {}, #s&lt;br /&gt;
    for i = 1, len do copy[i] = s[i] end&lt;br /&gt;
    return copy, len&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Generates a path sequence to the index.&lt;br /&gt;
local function makePath(path, ...)&lt;br /&gt;
    local keys = {...}&lt;br /&gt;
    local newPath, len = copySequence(path)&lt;br /&gt;
    for i = 1, #keys do&lt;br /&gt;
        newPath[len + i] = keys[i]&lt;br /&gt;
    end&lt;br /&gt;
    return newPath&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Recursive processing function for transformation.&lt;br /&gt;
local function processRecursive(process, item, path, 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;#039;table&amp;#039; 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) ~= &amp;#039;table&amp;#039; then mt = nil end -- ignore not nil/table __metatable field&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;
--------------------------------------------------------------------------------&lt;br /&gt;
--  Inspector class, used for Lua value transformation.&lt;br /&gt;
--  @type               Inspector&lt;br /&gt;
--  @local&lt;br /&gt;
local Inspector = {}&lt;br /&gt;
local Inspector_mt = {__index = Inspector}&lt;br /&gt;
&lt;br /&gt;
--- Inserts `...` into the inspector buffer.&lt;br /&gt;
--  @private&lt;br /&gt;
function Inspector:puts(...)&lt;br /&gt;
    local args   = {...}&lt;br /&gt;
    local buffer = self.buffer&lt;br /&gt;
    local len    = #buffer&lt;br /&gt;
    for i = 1, #args do&lt;br /&gt;
        len = len + 1&lt;br /&gt;
        buffer[len] = args[i]&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Used to indent the `f` buffer insertion.&lt;br /&gt;
--  @private&lt;br /&gt;
function Inspector:down(f)&lt;br /&gt;
    self.level = self.level + 1&lt;br /&gt;
    f()&lt;br /&gt;
    self.level = self.level - 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Inserts a newline and starting indent into inspector buffer.&lt;br /&gt;
--  @private&lt;br /&gt;
function Inspector:tabify()&lt;br /&gt;
    self:puts(self.newline, rep(self.indent, self.level))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Whether a table/function is already present in buffer.&lt;br /&gt;
--  @private&lt;br /&gt;
function Inspector:alreadyVisited(v)&lt;br /&gt;
    return self.ids[v] ~= nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Identifier getter for an identified table or function.&lt;br /&gt;
--  @private&lt;br /&gt;
function Inspector:getId(v)&lt;br /&gt;
    local id = self.ids[v]&lt;br /&gt;
    if not id then&lt;br /&gt;
        local tv = type(v)&lt;br /&gt;
        id              = (self.maxIds[tv] or 0) + 1&lt;br /&gt;
        self.maxIds[tv] = id&lt;br /&gt;
        self.ids[v]     = id&lt;br /&gt;
    end&lt;br /&gt;
    return tostring(id)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Inserts named (non-identifier) key into buffer.&lt;br /&gt;
--  @private&lt;br /&gt;
function Inspector:putKey(k)&lt;br /&gt;
    if isIdentifier(k) then return self:puts(k) end&lt;br /&gt;
    self:puts(&amp;quot;[&amp;quot;)&lt;br /&gt;
    self:putValue(k)&lt;br /&gt;
    self:puts(&amp;quot;]&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Inserts string representation of table into buffer.&lt;br /&gt;
--  @private&lt;br /&gt;
function Inspector:putTable(t)&lt;br /&gt;
    if t == inspect.KEY or t == inspect.METATABLE then&lt;br /&gt;
        self:puts(tostring(t))&lt;br /&gt;
    elseif self:alreadyVisited(t) then&lt;br /&gt;
        self:puts(&amp;#039;&amp;lt;table &amp;#039;, self:getId(t), &amp;#039;&amp;gt;&amp;#039;)&lt;br /&gt;
    elseif self.level &amp;gt;= self.depth then&lt;br /&gt;
        self:puts(&amp;#039;{...}&amp;#039;)&lt;br /&gt;
    else&lt;br /&gt;
        if self.tableAppearances[t] &amp;gt; 1 then self:puts(&amp;#039;&amp;lt;&amp;#039;, self:getId(t), &amp;#039;&amp;gt;&amp;#039;) end&lt;br /&gt;
&lt;br /&gt;
        local nonSequentialKeys, nonSequentialKeysLength, sequenceLength = getNonSequentialKeys(t)&lt;br /&gt;
        local mt                = getmetatable(t)&lt;br /&gt;
&lt;br /&gt;
        self:puts(&amp;#039;{&amp;#039;)&lt;br /&gt;
        self:down(function()&lt;br /&gt;
            local count = 0&lt;br /&gt;
            for i = 1, sequenceLength do&lt;br /&gt;
                if count &amp;gt; 0 then self:puts(&amp;#039;,&amp;#039;) end&lt;br /&gt;
                self:puts(&amp;#039; &amp;#039;)&lt;br /&gt;
                self:putValue(t[i])&lt;br /&gt;
                count = count + 1&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            for i = 1, nonSequentialKeysLength do&lt;br /&gt;
                local k = nonSequentialKeys[i]&lt;br /&gt;
                if count &amp;gt; 0 then self:puts(&amp;#039;,&amp;#039;) end&lt;br /&gt;
                self:tabify()&lt;br /&gt;
                self:putKey(k)&lt;br /&gt;
                self:puts(&amp;#039; = &amp;#039;)&lt;br /&gt;
                self:putValue(t[k])&lt;br /&gt;
                count = count + 1&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            if type(mt) == &amp;#039;table&amp;#039; then&lt;br /&gt;
                if count &amp;gt; 0 then self:puts(&amp;#039;,&amp;#039;) end&lt;br /&gt;
                self:tabify()&lt;br /&gt;
                self:puts(&amp;#039;&amp;lt;metatable&amp;gt; = &amp;#039;)&lt;br /&gt;
                self:putValue(mt)&lt;br /&gt;
            end&lt;br /&gt;
        end)&lt;br /&gt;
&lt;br /&gt;
        if nonSequentialKeysLength &amp;gt; 0 or type(mt) == &amp;#039;table&amp;#039; then -- result is multi-lined. Justify closing }&lt;br /&gt;
            self:tabify()&lt;br /&gt;
        elseif sequenceLength &amp;gt; 0 then -- array tables have one extra space before closing }&lt;br /&gt;
            self:puts(&amp;#039; &amp;#039;)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        self:puts(&amp;#039;}&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Inserts string representation of value into buffer.&lt;br /&gt;
--  @private&lt;br /&gt;
function Inspector:putValue(v)&lt;br /&gt;
    local tv = type(v)&lt;br /&gt;
&lt;br /&gt;
    if tv == &amp;#039;string&amp;#039; then&lt;br /&gt;
        self:puts(smartQuote(escape(v)))&lt;br /&gt;
    elseif tv == &amp;#039;number&amp;#039; or tv == &amp;#039;boolean&amp;#039; or tv == &amp;#039;nil&amp;#039; or&lt;br /&gt;
                 tv == &amp;#039;cdata&amp;#039; or tv == &amp;#039;ctype&amp;#039; then&lt;br /&gt;
        self:puts(tostring(v))&lt;br /&gt;
    elseif tv == &amp;#039;table&amp;#039; then&lt;br /&gt;
        self:putTable(v)&lt;br /&gt;
    else&lt;br /&gt;
        self:puts(&amp;#039;&amp;lt;&amp;#039;, tv, &amp;#039; &amp;#039;, self:getId(v), &amp;#039;&amp;gt;&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--  Transforms any Lua value into a human-readable representation.&lt;br /&gt;
--  @function           inspect.inspect&lt;br /&gt;
--  @alias              inspect&lt;br /&gt;
--  @param              {table|function|number|string|boolean} root&lt;br /&gt;
--                      Lua value to transform into string.&lt;br /&gt;
--  @param[opt]         {table} options&lt;br /&gt;
--                      Configuration options for transformation.&lt;br /&gt;
--  @param[opt]         {number} options.depth&lt;br /&gt;
--                      Maximum depth to print inside a table before table&lt;br /&gt;
--                      truncation occurs in the form `{...}`. Default:&lt;br /&gt;
--                      @{math.huge}.&lt;br /&gt;
--  @param[opt]         {number} options.newline&lt;br /&gt;
--                      Newline character to insert before dictionary keys.&lt;br /&gt;
--                      Default: `&amp;quot;\n&amp;quot;`.&lt;br /&gt;
--  @param[opt]         {number} options.indent&lt;br /&gt;
--                      Indentation to insert before keys or sequential values.&lt;br /&gt;
--                      Default: `&amp;quot;  &amp;quot;`.&lt;br /&gt;
--  @param[opt]         {function} options.process&lt;br /&gt;
--                      Returns the `item` if the inspected table is displayed.&lt;br /&gt;
--                      Signature: `function(item, path)`.&lt;br /&gt;
--                       ** `item` Either a key or value on the table/subtables.&lt;br /&gt;
--                       ** `path` Sequence representing root index keys used to&lt;br /&gt;
--                      reach `item`.&lt;br /&gt;
--                         *** Values have a regular list of keys. Example: to&lt;br /&gt;
--                      index `1` in `{a = {b = 1}}`, the path is `{&amp;#039;a&amp;#039;, &amp;#039;b&amp;#039;}`.&lt;br /&gt;
--                         *** Keys have a list of keys followed by the enum&lt;br /&gt;
--                      @{inspect.KEY}. Example: to index `c` in `{a = {b =&lt;br /&gt;
--                      {c=1}}}`, the path is `{&amp;#039;a&amp;#039;, &amp;#039;b&amp;#039;, &amp;#039;c&amp;#039;, inspect.KEY&lt;br /&gt;
--                      }`.&lt;br /&gt;
--                         *** Metatables have a list of keys followed by the&lt;br /&gt;
--                      enum @{inspect.METATABLE}. Example: to index `{b=1}`&amp;#039;s&lt;br /&gt;
--                      metatable in `{a = {b=1}}`, the path&amp;#039;s `{&amp;#039;a&amp;#039;, {b=1},&lt;br /&gt;
--                      inspect.METATABLE}`.&lt;br /&gt;
--  @return             {string} Human-readable representation of `root`.&lt;br /&gt;
--                       * Primitives (`boolean` or `nil`) are converted into an&lt;br /&gt;
--                      executable string representation of the value.&lt;br /&gt;
--                       * Strings are converted into quoted strings with&lt;br /&gt;
--                      backslash escapes if they contain special characters.&lt;br /&gt;
--                       * Tables are converted into a human-readable&lt;br /&gt;
--                      representation. The keys will be sorted alphanumerically&lt;br /&gt;
--                      when possible.&lt;br /&gt;
--                         ** Array keys are rendered horizontally.&lt;br /&gt;
--                         ** Dictionary keys are rendered one element per line.&lt;br /&gt;
--                         ** Metatables are rendered with the `&amp;lt;metatable&amp;gt;`&lt;br /&gt;
--                        field.&lt;br /&gt;
--                         ** Repeated tables are serialised as `&amp;lt;%d&amp;gt;` first,&lt;br /&gt;
--                        then `&amp;lt;table %d&amp;gt;`.&lt;br /&gt;
--                         ** Recursive table loops are serialised as `&amp;lt;table&lt;br /&gt;
--                        %d&amp;gt;`.&lt;br /&gt;
--                       * Functions are serialised as `&amp;lt;function %d&amp;gt;`.&lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      -- Primitives.&lt;br /&gt;
--      assert(inspect(nil) == &amp;quot;nil&amp;quot;)&lt;br /&gt;
--      assert(inspect(1) == &amp;quot;1&amp;quot;)&lt;br /&gt;
--      assert(inspect(&amp;quot;Hello&amp;quot;) == &amp;#039;&amp;quot;Hello&amp;quot;&amp;#039;)&lt;br /&gt;
--  &lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      -- Array-like table.&lt;br /&gt;
--      assert(inspect({1,2,3,4}) == &amp;quot;{ 1, 2, 3, 4 }&amp;quot;)&lt;br /&gt;
--  &lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      -- Dictionary-like table.&lt;br /&gt;
--      assert(inspect({a=1,b=2}) == [[{&lt;br /&gt;
--        a = 1,&lt;br /&gt;
--        b = 2&lt;br /&gt;
--      }]])&lt;br /&gt;
--  &lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      -- Hybrid dictionary-array table.&lt;br /&gt;
--      assert(inspect({1,2,3,b=2,a=1}) == [[{ 1, 2, 3,&lt;br /&gt;
--        a = 1,&lt;br /&gt;
--        b = 2&lt;br /&gt;
--      }]])&lt;br /&gt;
--  &lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      -- Table with a subtable and function.&lt;br /&gt;
--      assert(inspect({a={f=tostring}}) == [[{&lt;br /&gt;
--        a = {&lt;br /&gt;
--          f = &amp;lt;function 1&amp;gt;&lt;br /&gt;
--        }&lt;br /&gt;
--      }]])&lt;br /&gt;
--  &lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      -- Table with a metatable.&lt;br /&gt;
--      assert(inspect(setmetatable({a=1}, {b=2}) == [[{&lt;br /&gt;
--        a = 1&lt;br /&gt;
--        &amp;lt;metatable&amp;gt; = {&lt;br /&gt;
--          b = 2&lt;br /&gt;
--        }&lt;br /&gt;
--      }]]))&lt;br /&gt;
--  &lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      -- Table with a recursive loop.&lt;br /&gt;
--      local a = {1, 2}&lt;br /&gt;
--      local b = {3, 4, a}&lt;br /&gt;
--      a[3] = b -- a references b, and b references a&lt;br /&gt;
--      assert(inspect(a) == &amp;quot;&amp;lt;1&amp;gt;{ 1, 2, { 3, 4, &amp;lt;table 1&amp;gt; } }&amp;quot;)&lt;br /&gt;
--  &lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      -- `options.depth`.&lt;br /&gt;
--      assert(inspect(t5, {depth = 2}) == [[{&lt;br /&gt;
--        a = {&lt;br /&gt;
--          b = {...}&lt;br /&gt;
--        }&lt;br /&gt;
--      }]])&lt;br /&gt;
--  &lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      -- `options.newline` &amp;amp; `options.indent`.&lt;br /&gt;
--      assert(inspect(&lt;br /&gt;
--          t,&lt;br /&gt;
--          {newline=&amp;#039;@&amp;#039;, indent=&amp;quot;++&amp;quot;}),&lt;br /&gt;
--          &amp;quot;{@++a = {@++++b = 1@++}@}&amp;quot;&lt;br /&gt;
--      )&lt;br /&gt;
--  &lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      -- `options.process` metatable removal.&lt;br /&gt;
--      local account = { &amp;#039;peter&amp;#039;, &amp;#039;GlaHquq0&amp;#039; }&lt;br /&gt;
--      local account_mt = { __tostring = inspect }&lt;br /&gt;
--      setmetatable(account, account_mt)&lt;br /&gt;
--      &lt;br /&gt;
--      local remove_mt = function(item) -- removes specific metatable&lt;br /&gt;
--          if item ~= account_mt then return item end&lt;br /&gt;
--      end&lt;br /&gt;
--      &lt;br /&gt;
--      assert(inspect(t, {process = remove_mt}) == &amp;quot;{ &amp;#039;peter&amp;#039;, &amp;#039;GlaHquq0&amp;#039; }&amp;quot;)&lt;br /&gt;
--      &lt;br /&gt;
--      local remove_all_metatables = function(item, path)&lt;br /&gt;
--          if path[#path] ~= inspect.METATABLE then return item end&lt;br /&gt;
--      end&lt;br /&gt;
--      &lt;br /&gt;
--      assert(inspect(t, {process = remove_all_metatables}) == &amp;quot;{ &amp;#039;peter&amp;#039;, &amp;#039;GlaHquq0&amp;#039; }&amp;quot;)&lt;br /&gt;
--      &lt;br /&gt;
--  @usage&lt;br /&gt;
--  &lt;br /&gt;
--      -- `options.process` item filtering.&lt;br /&gt;
--      local anonymize_password = function(item, path)&lt;br /&gt;
--        if path[#path] == 2 then return item:gsub(&amp;#039;.&amp;#039;, &amp;#039;●&amp;#039;) end&lt;br /&gt;
--        return item&lt;br /&gt;
--      end&lt;br /&gt;
--      &lt;br /&gt;
--      assert(inspect(info, {process = anonymize_password}) == &amp;quot;{ &amp;#039;peter&amp;#039;, &amp;#039;●●●●●●●●&amp;#039; }&amp;quot; )&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 huge&lt;br /&gt;
    local newline = options.newline or &amp;#039;\n&amp;#039;&lt;br /&gt;
    local indent  = options.indent  or &amp;#039;  &amp;#039;&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 inspector = setmetatable({&lt;br /&gt;
        depth            = depth,&lt;br /&gt;
        level            = 0,&lt;br /&gt;
        buffer           = {},&lt;br /&gt;
        ids              = {},&lt;br /&gt;
        maxIds           = {},&lt;br /&gt;
        newline          = newline,&lt;br /&gt;
        indent           = indent,&lt;br /&gt;
        tableAppearances = countTableAppearances(root)&lt;br /&gt;
    }, Inspector_mt)&lt;br /&gt;
&lt;br /&gt;
    inspector:putValue(root)&lt;br /&gt;
&lt;br /&gt;
    return concat(inspector.buffer)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })&lt;br /&gt;
&lt;br /&gt;
--- Processing enumerable for a key in inspection paths.&lt;br /&gt;
--  @member             {table} inspect.KEY&lt;br /&gt;
inspect.KEY       = setmetatable({}, { __tostring = function() return &amp;#039;inspect.KEY&amp;#039; end })&lt;br /&gt;
&lt;br /&gt;
--- Processing enumerable for a metatable in inspection paths.&lt;br /&gt;
--  @member             {table} inspect.METATABLE&lt;br /&gt;
inspect.METATABLE = setmetatable({}, { __tostring = function() return &amp;#039;inspect.METATABLE&amp;#039; end })&lt;br /&gt;
&lt;br /&gt;
return inspect&lt;/div&gt;</summary>
		<author><name>Webmaster</name></author>
	</entry>
</feed>