Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
--   http://anggtwu.net/LUA/PrintFunction1.lua.html
--   http://anggtwu.net/LUA/PrintFunction1.lua
--          (find-angg "LUA/PrintFunction1.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- Also here:
--   (find-angg "LUA/lua50init.lua" "PrintFunction")
--
-- This file defines the class `PrintFunction', that is used by `help'
-- and by `PreTraceback'. For example:
--
--   > = help(split)
--   (find-luatb "~/LUA/lua50init.lua 351 357")
--
--
-- Old comments
-- ============
-- ...and stack frames either in a very compact format that looks like
-- this (that I took from a pretraceback),
--
--   [ C ]  C function (unknown name)
--   [Lua] stdin line 1
--   (find-luatb "~/LUA/lua50init.lua 2325 2329 global run_repl3_now")
--   (find-luatb "~/LUA/Repl3.lua 146 148 method repl")
--
-- or, with the method :v(), in a low-level "vertical" format that
-- looks like this:
--
--   { "currentline"=2329,
--     "func"=<function: 0x560195e1d770>,
--     "lastlinedefined"=2330,
--     "linedefined"=2325,
--     "name"="run_repl3_now",
--     "namewhat"="global",
--     "nups"=0,
--     "short_src"="/home/edrx/LUA/lua50init.lua",
--     "source"="@/home/edrx/LUA/lua50init.lua",
--     "what"="Lua"
--   }
--
-- debug.getinfo only fills the fields "name" and "namewhat" for stack
-- frames, so
--
--   PrintFunction.from(run_repl3_now)
--
-- returns just:
--
--   (find-luatb "~/LUA/lua50init.lua 2325 2330")
--
-- instead of:
--
--   (find-luatb "~/LUA/lua50init.lua 2325 2329 global run_repl3_now")
--
-- PrintFunction was inspired by the traceback in Prosody,
--
--   http://angg.twu.net/LUA/Prosody1.lua.html
--           (find-angg "LUA/Prosody1.lua")
--
-- but I changed the output format completely.
--
-- Based on/supersedes:
--   (find-angg "LUA/DGetInfo1.lua" "DGetInfo")
-- See:
--   (find-angg "LUA/PreTraceback1.lua")
--   (find-TH "Repl3" "PrintFunction1.lua")
--   (find-lua51manual "#pdf-debug.getinfo")
--   (find-lua51manual "#pdf-debug.getlocal")
--
-- (defun e () (interactive) (find-angg "LUA/PrintFunction1.lua"))

-- «.ObjToFunction»		(to "ObjToFunction")
-- «.ObjToFunction-tests»	(to "ObjToFunction-tests")
-- «.PrintFunction»		(to "PrintFunction")
-- «.PrintFunction-any»		(to "PrintFunction-any")
-- «.PrintFunction-keys»	(to "PrintFunction-keys")
-- «.PrintFunction-tests»	(to "PrintFunction-tests")

require "SortedKeys2"     -- (find-angg "LUA/SortedKeys2.lua")


--   ___  _     _ _____     _____                 _   _             
--  / _ \| |__ (_)_   _|__ |  ___|   _ _ __   ___| |_(_) ___  _ __  
-- | | | | '_ \| | | |/ _ \| |_ | | | | '_ \ / __| __| |/ _ \| '_ \ 
-- | |_| | |_) | | | | (_) |  _|| |_| | | | | (__| |_| | (_) | | | |
--  \___/|_.__// | |_|\___/|_|   \__,_|_| |_|\___|\__|_|\___/|_| |_|
--           |__/                                                   
-- `ObjToFunction.from(o)' is used by PrintFunction to make it
-- support (my) classes:
--   it returns functions unchanged,
--   it returns the __tostring method of a class when it exists,
--   it returns the __tostring method of the class of an object
--      when that makes sense and the __tostring method exists,
--   and it has some _unreliable hacks_ for classes without a
--      a __tostring method, and for objects of those classes.
--
-- In the code below:
--   "C"    means "`C'lass",
--   "TM"   means "`T'able with `M'etatable",
--   "CWT"  means "`C'lass `W'ith      a __`T'ostring", and
--   "CWOT" means "`C'lass `W'ith`O'ut a __`T'ostring".
--
-- «ObjToFunction»  (to ".ObjToFunction")
-- Also here: (find-angg "LUA/lua50init.lua" "ObjToFunction")
--
ObjToFunction = Class {
  type    = "ObjToFunction",
  from    = function (o) return ObjToFunction{}:from(o) end,
  __index = {
    tt    = function (a,o) return  type(o) == "table" end,
    ts    = function (a,o) return  type(o) == "string" end,
    tf    = function (a,o) return (type(o) == "function") and o end,
    tm    = function (a,o) return a:tt(o)  and getmetatable(o) end,
    isc   = function (a,c) return a:tt(c)  and a:tt(c.__index) and a:ts(c.type) end,
    iscwt = function (a,c) return a:isc(c) and a:tf(c.__tostring) end,
    --
    -- `fft': First function in the table T
    -- `ffc': first function in the class C
    ffc   = function (a,C) return a:fft(C) or a:fft(C.__index) end,
    fft   = function (a,T)
          for _,k in ipairs(sortedkeys(T)) do
            if a:tf(T[k]) then return T[k] end
          end
        end,
    from  = function (a,o)    
        return a:tf(o)                             -- o is a function,
            or a:iscwt(o)                          -- o is a CWT,
            or (a:tm(o) and a:iscwt(a:tm(o)))      -- o is an object of a CWT,
            or (a:isc(o) and a:ffc(o))             -- o is a CWOT,
            or (a:isc(a:tm(o)) and a:ffc(a:tm(o))) -- o is an object of a CWOT
            or (a:tt(o) and a:fft(o))              -- no `__tostring', no `__index'
            or error("Objfunction{}:from(o) failed")
      end,
  },
}

-- «ObjToFunction-tests»  (to ".ObjToFunction-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "PrintFunction1.lua"
foo = function (o) return PrintFunction.fromf(ObjToFunction{}:from(o)) end

= foo(foo)
= foo(Set)
= foo(Set {})
= foo(Tos)
= foo(Tos {})
= foo(Class)

--]]




--  ____       _       _   _____                 _   _             
-- |  _ \ _ __(_)_ __ | |_|  ___|   _ _ __   ___| |_(_) ___  _ __  
-- | |_) | '__| | '_ \| __| |_ | | | | '_ \ / __| __| |/ _ \| '_ \ 
-- |  __/| |  | | | | | |_|  _|| |_| | | | | (__| |_| | (_) | | | |
-- |_|   |_|  |_|_| |_|\__|_|   \__,_|_| |_|\___|\__|_|\___/|_| |_|
--                                                                 
-- `PrintFunction.fromf' expects a function.
-- `PrintFunction.fromfunction' is a hack to support (my) classes:
--   it returns functions unchanged,
--   it returns the __tostring method of a class when it exists,
--   it returns the __tostring method of the class of an object
--     when that makes sense and the __tostring method exists,
--   and it has some _unreliable hacks_ for classes without a
--     a __tostring method, and for objects of those classes.
--
-- In the code below:
--   "C"    means "`C'lass",
--   "TM"   means "`T'able with `M'etatable",
--   "CWT"  means "`C'lass `W'ith      a __`T'ostring", and
--   "CWOT" means "`C'lass `W'ith`O'ut a __`T'ostring".
--
-- «PrintFunction»  (to ".PrintFunction")
-- Also here: (find-angg "LUA/lua50init.lua" "PrintFunction")
--
PrintFunction = Class {
  type = "PrintFunction",
  tostring = function (o) return PrintFunction.from(o):tostring() end,
  fromf    = function (f) return PrintFunction(debug.getinfo(f, "nSluf")) end,
  from     = function (o) return PrintFunction.fromf(ObjToFunction.from(o)) end,
  --
  __tostring = function (pf) return pf:tostring() end,
  __index = {
    tostring   = function (pf) return pf:_any() end,
    tostring2  = function (pf) return pf:sks() end,
    tostring3  = function (pf) return tostring(VTable(copy(pf))) end,
    -- 
    -- «PrintFunction-any»  (to ".PrintFunction-any")
    -- `pf:_any()' returns a line like `(find-luatb "..." 42)' or `[C]'
    _shortsrc0 = function (pf) return ee_shorten(pf.short_src) end,
    _shortsrc0 = function (pf) return ee_shorten(pf.source:sub(2)) end,
    _shortsrc  = function (pf) return pf.short_src and pf:_shortsrc0() end,
    _name0     = function (pf) return pf.name and format("%q", pf.name) end,
    _name      = function (pf) return pf:_name0() or "(unknown name)" end,
    _linedef   = function (pf) return pf.linedefined end,
    _linelast  = function (pf) return pf.lastlinedefined end,
    _linecurr0 = function (pf) return pf.currentline end,
    _linecurr  = function (pf) return pf:_linecurr0()~=-1 and pf:_linecurr0() end,
    _line1     = function (pf) return pf:_linedef() end,
    _line2     = function (pf) return pf:_linecurr() or pf:_linelast() end,
    _tailcall0 = function (pf) return "[Lua] tail call" end,
    _main0     = function (pf) return "[Lua] "..pf:_shortsrc()
                                   .." line "..pf:_linecurr() end,
    _C0        = function (pf) return "[ C ] "..pf.namewhat
                                   .." C function "..pf:_name() end,
    _tbbody0   = function (pf) return (pf:_shortsrc() or "")
                               .." "..(pf:_line1() or "")
                               .." "..(pf:_line2() or "")
                               .." "..(pf.namewhat or "")
                               .." "..(pf.name or "") end,
    _tbbody    = function (pf) return rtrim(pf:_tbbody0()) end,
    _findluatb = function (pf) return format('(find-luatb \"%s\")', pf:_tbbody()) end,
    _any       = function (pf)
        if pf.short_src == "[C]"         then return pf:_C0() end
        if pf.what      == "main"        then return pf:_main0() end
        if pf.short_src == "(tail call)" then return pf:_tailcall0() end
        return pf:_findluatb()
      end,
    --
    -- «PrintFunction-keys»  (to ".PrintFunction-keys")
    -- Returns a multi-line string with all the key-value pairs of
    -- `pf', grouped and sorted in a nice way. Needs SortedKeys2.
    keys = [[ what namewhat source short_src
              linedefined lastlinedefined currentline
              nups ]],
    sk1 = function (pf,k) return format("%-15s -> %s", k, mytostring(pf[k])) end,
    skL = function (pf,ks)
        local f = function (k) return pf:sk1(k) end
        return mapconcat(f,ks,"\n")
      end,
    sks = function (pf) return pf:skL(SortedKeys.from(pf, pf.keys).list) end,
  },
}

help = function (o) return PrintFunction.tostring(o) end

-- «PrintFunction-tests»  (to ".PrintFunction-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "PrintFunction1.lua"
= help(split)
= help(print)
= help(mytostring)
= help(Set)
= help(Set {})

Foo = Class {
  type    = "Foo",
  __mul   = function (a,b) return a[1]*b[1] end,
  __index = {
  },
}
= help(Foo)
= help(Foo {2})
= help(Tos)
= help(Tos {})
= help(Class)

o = print
o = split
= PrintFunction.from(o):tostring()
= PrintFunction.from(o):tostring2()
= PrintFunction.from(o):tostring3()

--]]








-- (find-angg "LUA/DGetInfo1.lua" "DGetInfos")






-- Local Variables:
-- coding:  utf-8-unix
-- End: