<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ARepr</id>
	<title>Module:Repr - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ARepr"/>
	<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Repr&amp;action=history"/>
	<updated>2026-04-15T04:12:56Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://stockhub.co/index.php?title=Module:Repr&amp;diff=144644&amp;oldid=prev</id>
		<title>imported&gt;WOSlinker: use require(&#039;strict&#039;) instead of require(&#039;Module:No globals&#039;)</title>
		<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Repr&amp;diff=144644&amp;oldid=prev"/>
		<updated>2022-10-21T22:05:04Z</updated>

		<summary type="html">&lt;p&gt;use require(&amp;#039;strict&amp;#039;) instead of require(&amp;#039;Module:No globals&amp;#039;)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;require(&amp;#039;strict&amp;#039;)&lt;br /&gt;
local libraryUtil = require(&amp;quot;libraryUtil&amp;quot;)&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg&lt;br /&gt;
&lt;br /&gt;
local defaultOptions = {&lt;br /&gt;
	pretty = false,&lt;br /&gt;
	tabs = true,&lt;br /&gt;
	semicolons = false,&lt;br /&gt;
	spaces = 4,&lt;br /&gt;
	sortKeys = true,&lt;br /&gt;
	depth = 0,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Define the reprRecursive variable here so that we can call the reprRecursive&lt;br /&gt;
-- function from renderSequence and renderKeyValueTable without getting&lt;br /&gt;
-- &amp;quot;Tried to read nil global reprRecursive&amp;quot; errors.&lt;br /&gt;
local reprRecursive&lt;br /&gt;
&lt;br /&gt;
local luaKeywords = {&lt;br /&gt;
	[&amp;quot;and&amp;quot;]      = true,&lt;br /&gt;
	[&amp;quot;break&amp;quot;]    = true,&lt;br /&gt;
	[&amp;quot;do&amp;quot;]       = true,&lt;br /&gt;
	[&amp;quot;else&amp;quot;]     = true,&lt;br /&gt;
	[&amp;quot;elseif&amp;quot;]   = true,&lt;br /&gt;
	[&amp;quot;end&amp;quot;]      = true,&lt;br /&gt;
	[&amp;quot;false&amp;quot;]    = true,&lt;br /&gt;
	[&amp;quot;for&amp;quot;]      = true,&lt;br /&gt;
	[&amp;quot;function&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;if&amp;quot;]       = true,&lt;br /&gt;
	[&amp;quot;in&amp;quot;]       = true,&lt;br /&gt;
	[&amp;quot;local&amp;quot;]    = true,&lt;br /&gt;
	[&amp;quot;nil&amp;quot;]      = true,&lt;br /&gt;
	[&amp;quot;not&amp;quot;]      = true,&lt;br /&gt;
	[&amp;quot;or&amp;quot;]       = true,&lt;br /&gt;
	[&amp;quot;repeat&amp;quot;]   = true,&lt;br /&gt;
	[&amp;quot;return&amp;quot;]   = true,&lt;br /&gt;
	[&amp;quot;then&amp;quot;]     = true,&lt;br /&gt;
	[&amp;quot;true&amp;quot;]     = true,&lt;br /&gt;
	[&amp;quot;until&amp;quot;]    = true,&lt;br /&gt;
	[&amp;quot;while&amp;quot;]    = true,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Whether the given value is a valid Lua identifier (i.e. whether it can be&lt;br /&gt;
-- used as a variable name.)&lt;br /&gt;
--]]&lt;br /&gt;
local function isLuaIdentifier(str)&lt;br /&gt;
	return type(str) == &amp;quot;string&amp;quot;&lt;br /&gt;
		-- Must start with a-z, A-Z or underscore, and can only contain&lt;br /&gt;
		-- a-z, A-Z, 0-9 and underscore&lt;br /&gt;
		and str:find(&amp;quot;^[%a_][%a%d_]*$&amp;quot;) ~= nil&lt;br /&gt;
		-- Cannot be a Lua keyword&lt;br /&gt;
		and not luaKeywords[str]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Render a string representation.&lt;br /&gt;
--]]&lt;br /&gt;
local function renderString(s)&lt;br /&gt;
	return ((&amp;quot;%q&amp;quot;):format(s):gsub(&amp;quot;\\\n&amp;quot;, &amp;quot;\\n&amp;quot;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Render a number representation.&lt;br /&gt;
--]]&lt;br /&gt;
local function renderNumber(n)&lt;br /&gt;
	if n == math.huge then&lt;br /&gt;
		return &amp;quot;math.huge&amp;quot;&lt;br /&gt;
	elseif n == -math.huge then&lt;br /&gt;
		return &amp;quot;-math.huge&amp;quot;&lt;br /&gt;
	else&lt;br /&gt;
		return tostring(n)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Whether a table has a __tostring metamethod.&lt;br /&gt;
--]]&lt;br /&gt;
local function hasTostringMetamethod(t)&lt;br /&gt;
	return getmetatable(t) and type(getmetatable(t).__tostring) == &amp;quot;function&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Pretty print a sequence of string representations.&lt;br /&gt;
-- This can be made to represent different constructs depending on the values&lt;br /&gt;
-- of prefix, suffix, and separator. The amount of whitespace is controlled by&lt;br /&gt;
-- the depth and indent parameters.&lt;br /&gt;
--]]&lt;br /&gt;
local function prettyPrintItemsAtDepth(items, prefix, suffix, separator, indent, depth)&lt;br /&gt;
	local whitespaceAtCurrentDepth = &amp;quot;\n&amp;quot; .. indent:rep(depth)&lt;br /&gt;
	local whitespaceAtNextDepth = whitespaceAtCurrentDepth .. indent&lt;br /&gt;
	local ret = {prefix, whitespaceAtNextDepth}&lt;br /&gt;
	local first = items[1]&lt;br /&gt;
	if first ~= nil then&lt;br /&gt;
		table.insert(ret, first)&lt;br /&gt;
	end&lt;br /&gt;
	for i = 2, #items do&lt;br /&gt;
		table.insert(ret, separator)&lt;br /&gt;
		table.insert(ret, whitespaceAtNextDepth)&lt;br /&gt;
		table.insert(ret, items[i])&lt;br /&gt;
	end&lt;br /&gt;
	table.insert(ret, whitespaceAtCurrentDepth)&lt;br /&gt;
	table.insert(ret, suffix)&lt;br /&gt;
	return table.concat(ret)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Render a sequence of string representations.&lt;br /&gt;
-- This can be made to represent different constructs depending on the values of&lt;br /&gt;
-- prefix, suffix and separator.&lt;br /&gt;
--]]&lt;br /&gt;
local function renderItems(items, prefix, suffix, separator)&lt;br /&gt;
	return prefix .. table.concat(items, separator .. &amp;quot; &amp;quot;) .. suffix&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Render a regular table (a non-cyclic table with no __tostring metamethod).&lt;br /&gt;
-- This can be a sequence table, a key-value table, or a mix of the two.&lt;br /&gt;
--]]&lt;br /&gt;
local function renderNormalTable(t, context, depth)&lt;br /&gt;
	local items = {}&lt;br /&gt;
&lt;br /&gt;
	-- Render the items in the sequence part&lt;br /&gt;
	local seen = {}&lt;br /&gt;
	for i, value in ipairs(t) do&lt;br /&gt;
		table.insert(items, reprRecursive(t[i], context, depth + 1))&lt;br /&gt;
		seen[i] = true&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Render the items in the key-value part	&lt;br /&gt;
	local keyOrder = {}&lt;br /&gt;
	local keyValueStrings = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		if not seen[k] then&lt;br /&gt;
			local kStr = isLuaIdentifier(k) and k or (&amp;quot;[&amp;quot; .. reprRecursive(k, context, depth + 1) .. &amp;quot;]&amp;quot;)&lt;br /&gt;
			local vStr = reprRecursive(v, context, depth + 1)&lt;br /&gt;
			table.insert(keyOrder, kStr)&lt;br /&gt;
			keyValueStrings[kStr] = vStr&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if context.sortKeys then&lt;br /&gt;
		table.sort(keyOrder)&lt;br /&gt;
	end&lt;br /&gt;
	for _, kStr in ipairs(keyOrder) do&lt;br /&gt;
		table.insert(items, string.format(&amp;quot;%s = %s&amp;quot;, kStr, keyValueStrings[kStr]))&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Render the table structure&lt;br /&gt;
	local prefix = &amp;quot;{&amp;quot;&lt;br /&gt;
	local suffix = &amp;quot;}&amp;quot;&lt;br /&gt;
	if context.pretty then&lt;br /&gt;
		return prettyPrintItemsAtDepth(&lt;br /&gt;
			items,&lt;br /&gt;
			prefix,&lt;br /&gt;
			suffix,&lt;br /&gt;
			context.separator,&lt;br /&gt;
			context.indent,&lt;br /&gt;
			depth&lt;br /&gt;
		)&lt;br /&gt;
	else&lt;br /&gt;
		return renderItems(items, prefix, suffix, context.separator)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Render the given table.&lt;br /&gt;
-- As well as rendering regular tables, this function also renders cyclic tables&lt;br /&gt;
-- and tables with a __tostring metamethod.&lt;br /&gt;
--]]&lt;br /&gt;
local function renderTable(t, context, depth)&lt;br /&gt;
	if hasTostringMetamethod(t) then&lt;br /&gt;
		return tostring(t)&lt;br /&gt;
	elseif context.shown[t] then&lt;br /&gt;
		return &amp;quot;{CYCLIC}&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	context.shown[t] = true&lt;br /&gt;
	local result = renderNormalTable(t, context, depth)&lt;br /&gt;
	context.shown[t] = false&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Recursively render a string representation of the given value.&lt;br /&gt;
--]]&lt;br /&gt;
function reprRecursive(value, context, depth)&lt;br /&gt;
	if value == nil then&lt;br /&gt;
		return &amp;quot;nil&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	local valueType = type(value)&lt;br /&gt;
	if valueType == &amp;quot;boolean&amp;quot; then&lt;br /&gt;
		return tostring(value)&lt;br /&gt;
	elseif valueType == &amp;quot;number&amp;quot; then&lt;br /&gt;
		return renderNumber(value)&lt;br /&gt;
	elseif valueType == &amp;quot;string&amp;quot; then&lt;br /&gt;
		return renderString(value)&lt;br /&gt;
	elseif valueType == &amp;quot;table&amp;quot; then&lt;br /&gt;
		return renderTable(value, context, depth)&lt;br /&gt;
	else&lt;br /&gt;
		return &amp;quot;&amp;lt;&amp;quot; .. valueType .. &amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Normalize a table of options passed by the user.&lt;br /&gt;
-- Any values not specified will be assigned default values.&lt;br /&gt;
--]]&lt;br /&gt;
local function normalizeOptions(options)&lt;br /&gt;
	options = options or {}&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for option, defaultValue in pairs(defaultOptions) do&lt;br /&gt;
		local value = options[option]&lt;br /&gt;
		if value ~= nil then&lt;br /&gt;
			if type(value) == type(defaultValue) then&lt;br /&gt;
				ret[option] = value&lt;br /&gt;
			else&lt;br /&gt;
				error(&lt;br /&gt;
					string.format(&lt;br /&gt;
						&amp;#039;Invalid type for option &amp;quot;%s&amp;quot; (expected %s, received %s)&amp;#039;,&lt;br /&gt;
						option,&lt;br /&gt;
						type(defaultValue),&lt;br /&gt;
						type(value)&lt;br /&gt;
					),&lt;br /&gt;
					3&lt;br /&gt;
				)&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			ret[option] = defaultValue&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Get the indent from the options table.&lt;br /&gt;
--]]&lt;br /&gt;
local function getIndent(options)&lt;br /&gt;
	if options.tabs then&lt;br /&gt;
		return &amp;quot;\t&amp;quot;&lt;br /&gt;
	else&lt;br /&gt;
		return string.rep(&amp;quot; &amp;quot;, options.spaces)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Render a string representation of the given value.&lt;br /&gt;
--]]&lt;br /&gt;
local function repr(value, options)&lt;br /&gt;
	checkType(&amp;quot;repr&amp;quot;, 2, options, &amp;quot;table&amp;quot;, true)&lt;br /&gt;
	&lt;br /&gt;
	options = normalizeOptions(options)&lt;br /&gt;
	local context = {}&lt;br /&gt;
&lt;br /&gt;
	context.pretty = options.pretty&lt;br /&gt;
	if context.pretty then&lt;br /&gt;
		context.indent = getIndent(options)&lt;br /&gt;
	else&lt;br /&gt;
		context.indent = &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if options.semicolons then&lt;br /&gt;
		context.separator = &amp;quot;;&amp;quot;&lt;br /&gt;
	else&lt;br /&gt;
		context.separator = &amp;quot;,&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	context.sortKeys = options.sortKeys&lt;br /&gt;
	context.shown = {}&lt;br /&gt;
	local depth = options.depth&lt;br /&gt;
	&lt;br /&gt;
	return reprRecursive(value, context, depth)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Render a string representation of the given function invocation.&lt;br /&gt;
--]]&lt;br /&gt;
local function invocationRepr(keywordArgs)&lt;br /&gt;
	checkType(&amp;quot;invocationRepr&amp;quot;, 1, keywordArgs, &amp;quot;table&amp;quot;)&lt;br /&gt;
	checkTypeForNamedArg(&amp;quot;invocationRepr&amp;quot;, &amp;quot;funcName&amp;quot;, keywordArgs.funcName, &amp;quot;string&amp;quot;)&lt;br /&gt;
	checkTypeForNamedArg(&amp;quot;invocationRepr&amp;quot;, &amp;quot;args&amp;quot;, keywordArgs.args, &amp;quot;table&amp;quot;, true)&lt;br /&gt;
	checkTypeForNamedArg(&amp;quot;invocationRepr&amp;quot;, &amp;quot;options&amp;quot;, keywordArgs.options, &amp;quot;table&amp;quot;, true)&lt;br /&gt;
	&lt;br /&gt;
	local options = normalizeOptions(keywordArgs.options)&lt;br /&gt;
	local depth = options.depth&lt;br /&gt;
&lt;br /&gt;
	options.depth = depth + 1&lt;br /&gt;
	local items = {}&lt;br /&gt;
	if keywordArgs.args then&lt;br /&gt;
		for _, arg in ipairs(keywordArgs.args) do&lt;br /&gt;
			table.insert(items, repr(arg, options))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local prefix = &amp;quot;(&amp;quot;&lt;br /&gt;
	local suffix = &amp;quot;)&amp;quot;&lt;br /&gt;
	local separator = &amp;quot;,&amp;quot;&lt;br /&gt;
	local renderedArgs&lt;br /&gt;
	if options.pretty then&lt;br /&gt;
		renderedArgs = prettyPrintItemsAtDepth(&lt;br /&gt;
			items,&lt;br /&gt;
			prefix,&lt;br /&gt;
			suffix,&lt;br /&gt;
			separator,&lt;br /&gt;
			getIndent(options),&lt;br /&gt;
			depth&lt;br /&gt;
		)&lt;br /&gt;
	else&lt;br /&gt;
		renderedArgs = renderItems(items, prefix, suffix, separator)&lt;br /&gt;
	end&lt;br /&gt;
	return keywordArgs.funcName .. renderedArgs&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	_isLuaIdentifier = isLuaIdentifier,&lt;br /&gt;
	repr = repr,&lt;br /&gt;
	invocationRepr = invocationRepr,&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>imported&gt;WOSlinker</name></author>
	</entry>
</feed>