Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
--   http://angg.twu.net/LUA/GetInfo2.lua.html
--   http://angg.twu.net/LUA/GetInfo2.lua
--           (find-angg "LUA/GetInfo2.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- (defun e () (interactive) (find-angg "LUA/GetInfo2.lua"))
-- (defun o () (interactive) (find-angg "LUA/GetInfo.lua"))
-- (defun p () (interactive) (find-angg "LUA/Prosody1.lua"))
-- (find-angg "LUA/lua50init.lua" "DGetInfo")

-- «.DGetInfo»	(to "DGetInfo")
-- «.DGetInfos»	(to "DGetInfos")


-- «DGetInfo»  (to ".DGetInfo")
DGetInfo = Class {
  type = "DGetInfo",
  what = "nSluf",
  atlevel = function (lvl, getvalues)
      local dgi = debug.getinfo(lvl, DGetInfo.what)
      if not dgi then return end
      if getvalues then dgi.values = {} end
      for i=1,1000 do
        local name,value = debug.getlocal(lvl, i)
        if not name then break end
        dgi[i] = name
        if getvalues then dgi.values[i] = value end
      end
      dgi.vars = table.concat(dgi, " ")
      return DGetInfo(dgi)
    end,
  --  
  __tostring = function (dgi) return dgi:tb() end,
  __index = {
    method    = "tblua",
    setmethod = function (dgi,m) DGetInfo.__index.method = method end,
    tbi       = function (dgi,m,i) return format("%2d -> %s", i, dgi:tb(m)) end,
    tb        = function (dgi,m) return dgi[m or dgi.method](dgi) end,
    tbfv      = function (dgi) return dgi:funname().." :: "..dgi.vars end,
    tbprosody = function (dgi) return Prosody.traceback1(dgi) end,
    --
    -- See: (find-angg ".emacs" "find-luatb")
    tblua = function (dgi)
        if dgi.short_src == "[C]"         then return dgi:tblua_C() end
        if dgi.what      == "main"        then return dgi:tblua_main() end
        if dgi.short_src == "(tail call)" then return dgi:tblua_tailcall() end
        return dgi:tblua_other()
      end,
    tblua_C = function (dgi)
        return "[ C ]"
               .." "..dgi.namewhat
               .." C function"
               .." "..(dgi.name and format("%q", dgi.name) or "(unknown name)")
      end,
    tblua_main = function (dgi)
        return "[Lua] "
               ..dgi.short_src
               .." line "
               ..dgi.currentline
      end,
    tblua_tailcall = function (dgi)
        return "[Lua] tail call"
      end,
    tblua_other = function (dgi)
        return -- "[Lua]"..
               " (find-luatb "
               ..'"'..(dgi.short_src or "")
               .." "..(dgi.linedefined or "")
               .." "..(dgi.currentline or "")
               .." "..(dgi.namewhat or "")
               .." "..(dgi.name or "")
               ..'")'
      end,
    --
    funname = function (dgi) return dgi.name or "(noname)" end,
    -- vars = function (dgi) return table.concat(dgi, " ") end,
    --
    convert = function (dgi)
        local i = VTable {}
        local name = VTable {}
        for j,nm in ipairs(dgi) do
          local value = dgi.values and dgi.values[j] or "(no values)"
          i[j] = {name=nm, value=value}
          name[nm] = {i=j, value=value}
        end
        return {name=name, i=i}
      end,
    v0 = function (dgi, varname) return dgi:convert().name[varname] end,
    v  = function (dgi, varname) return dgi:v0(varname).value end,
    --
    names = function (dgi) return dgi:convert().name end,
    -- is = function (dgi) return dgi:convert().i end,
    is = function (dgi, tos)
        tos = tos or mytostring
        local ci = dgi:convert().i
        local f = function (i)
            return format("%2s: %s = %s", i, ci[i].name, tos(ci[i].value))
          end
        return mapconcat(f, seq(1, #ci), "\n")
      end,
  },
}


--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "GetInfo2.lua"
dofile "Prosody1.lua"
dgis = DGetInfos.new()
dgis = DGetInfos.newv()
f = function (a,b,...) local c,d = "cc"; dgis = DGetInfos.newv() end
f("aa","bb","oo","pp")
= dgis[1]
= dgis[1].tbfv
= dgis[1].method
= dgis[1]:tb()
= dgis[1]:tb("tbfv")
= dgis[5]:tb("tbfv")
= dgis[5]:tbprosody()
= dgis[5]:tblua()
= dgis[5]:tbfv()
= dgis[5]:tbi("tbfv", 42)
= dgis[5]:is()
= dgis:tb("tbfv")
= dgis:tb("tbprosody")
= dgis:tb("tblua")
= dgis
= dgis:setmethod("tbfv")
= dgis
= dgis:setmethod("tbprosody")
= dgis
= dgis:setmethod("tblua")
= dgis
= dgis[1]
= dgis[1].vars
= dgis[1]:vars()
= dgis[1]:v"i"
= dgis[1]:v"lvl"
= dgis[1]:v"foo"
= dgis[1]:convert()

= dgis[5]
= PPV(dgis[5])

--]]


-- «DGetInfos»  (to ".DGetInfos")
-- Idea: running something like
--
--   dgis = DGetInfos.newv()
-- 
-- runs lots of "debug.getinfo()"s and "debug.getlocal"s via DGetInfo,
-- and returns a static structure that can be inspected in a repl
-- (both inside an error handler and post-mortem).
--
DGetInfos = Class {
  type = "DGetInfos",
  new  = function (getvalues) return DGetInfos({}):getinfos(getvalues) end,
  newv = function () return DGetInfos.new("getvalues") end,
  __tostring = function (dgis) return dgis:tostring() end,
  __index = {
    setmethod = function (dgis, method)
        DGetInfo.__index.method = method
      end,
    getinfos = function (dgis, getvalues)
        for i=0,1000 do
          dgis[i] = DGetInfo.atlevel(i, getvalues)
          if not dgis[i] then return dgis end
        end
      end,
    seq = function (dgis, a, b, dir)
        a,b = (a or #dgis),(b or 0)
        dir = dir or (a <= b and 1 or -1)
        return seq(a, b, dir)
      end,
    tostring = function (dgis, method, a, b, dir)
        local f = function (i) return dgis[i]:tbi(method, i) end
        return mapconcat(f, dgis:seq(a, b, dir), "\n")
      end,
    tb = function (dgis, method, a, b, dir)
        return dgis:tostring(method, a, b, dir)
      end,
  },
}










-- Local Variables:
-- coding:  utf-8-unix
-- indent-tabs-mode:  nil
-- End: