-- https://github.com/kikito/inspect.lua
local a={Options={}}local tostring=tostring;local b=string.rep;local c=string.match;local d=string.char;local e=string.gsub;local f=string.format;local g;if rawget then g=rawget else g=function(h,i)return h[i]end end;local function j(h)return next,h,nil end;local function k(l)if c(l,'"')and not c(l,"'")then return"'"..l.."'"end;return'"'..e(l,'"','\\"')..'"'end;local m={["\a"]="\\a",["\b"]="\\b",["\f"]="\\f",["\n"]="\\n",["\r"]="\\r",["\t"]="\\t",["\v"]="\\v",["\127"]="\\127"}local n={["\127"]="\127"}for o=0,31 do local p=d(o)if not m[p]then m[p]="\\"..o;n[p]=f("\\%03d",o)end end;local function q(l)return e(e(e(l,"\\","\\\\"),"(%c)%f[0-9]",n),"%c",m)end;local r={['and']=true,['break']=true,['do']=true,['else']=true,['elseif']=true,['end']=true,['false']=true,['for']=true,['function']=true,['goto']=true,['if']=true,['in']=true,['local']=true,['nil']=true,['not']=true,['or']=true,['repeat']=true,['return']=true,['then']=true,['true']=true,['until']=true,['while']=true}local function s(l)return type(l)=="string"and not not l:match("^[_%a][_%a%d]*$")and not r[l]end;local t=math.floor;local function u(i,v)return type(i)=="number"and t(i)==i and 1<=i and i<=v end;local w={['number']=1,['boolean']=2,['string']=3,['table']=4,['function']=5,['userdata']=6,['thread']=7}local function x(y,z)local A,B=type(y),type(z)if A==B and(A=='string'or A=='number')then return y<z end;local C=w[A]or 100;local D=w[B]or 100;return C==D and A<B or C<D end;local function E(h)local F=1;while g(h,F)~=nil do F=F+1 end;F=F-1;local G,H={},0;for i in j(h)do if not u(i,F)then H=H+1;G[H]=i end end;table.sort(G,x)return G,H,F end;local function I(J,K)if type(J)=="table"then if K[J]then K[J]=K[J]+1 else K[J]=1;for i,L in j(J)do I(i,K)I(L,K)end;I(getmetatable(J),K)end end end;local function M(N,y,z)local O={}local P=#N;for o=1,P do O[o]=N[o]end;O[P+1]=y;O[P+2]=z;return O end;local function Q(R,S,N,T)if S==nil then return nil end;if T[S]then return T[S]end;local U=R(S,N)if type(U)=="table"then local V={}T[S]=V;local W;for i,L in j(U)do W=Q(R,i,M(N,i,a.KEY),T)if W~=nil then V[W]=Q(R,L,M(N,W),T)end end;local X=Q(R,getmetatable(U),M(N,a.METATABLE),T)if type(X)~='table'then X=nil end;setmetatable(V,X)U=V end;return U end;local function Y(Z,l)Z.n=Z.n+1;Z[Z.n]=l end;local _={}local a0={__index=_}local function a1(a2)Y(a2.buf,a2.newline..b(a2.indent,a2.level))end;function _:getId(L)local a3=self.ids[L]local a4=self.ids;if not a3 then local a5=type(L)a3=(a4[a5]or 0)+1;a4[L],a4[a5]=a3,a3 end;return tostring(a3)end;function _:putValue(L)local Z=self.buf;local a5=type(L)if a5=='string'then Y(Z,k(q(L)))elseif a5=='number'or a5=='boolean'or a5=='nil'or a5=='cdata'or a5=='ctype'then Y(Z,tostring(L))elseif a5=='table'and not self.ids[L]then local h=L;if h==a.KEY or h==a.METATABLE then Y(Z,tostring(h))elseif self.level>=self.depth then Y(Z,'{...}')else if self.cycles[h]>1 then Y(Z,f('<%d>',self:getId(h)))end;local G,H,F=E(h)Y(Z,'{')self.level=self.level+1;for o=1,F+H do if o>1 then Y(Z,',')end;if o<=F then Y(Z,' ')self:putValue(h[o])else local i=G[o-F]a1(self)if s(i)then Y(Z,i)else Y(Z,"[")self:putValue(i)Y(Z,"]")end;Y(Z,' = ')self:putValue(h[i])end end;local X=getmetatable(h)if type(X)=='table'then if F+H>0 then Y(Z,',')end;a1(self)Y(Z,'<metatable> = ')self:putValue(X)end;self.level=self.level-1;if H>0 or type(X)=='table'then a1(self)elseif F>0 then Y(Z,' ')end;Y(Z,'}')end else Y(Z,f('<%s %d>',a5,self:getId(L)))end end;function a.inspect(a6,a7)a7=a7 or{}local a8=a7.depth or math.huge;local a9=a7.newline or'\n'local aa=a7.indent or'  'local R=a7.process;if R then a6=Q(R,a6,{},{})end;local K={}I(a6,K)local a2=setmetatable({buf={n=0},ids={},cycles=K,depth=a8,level=0,newline=a9,indent=aa},a0)a2:putValue(a6)return table.concat(a2.buf)end;setmetatable(a,{__call=function(ab,a6,a7)return a.inspect(a6,a7)end})return a
