Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: -- http://angg.twu.net/LUA/Tos.lua.html -- http://angg.twu.net/LUA/Tos.lua -- (find-angg "LUA/Tos.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 2023nov26 -- Public domain. -- -- A class that lets me build lots of tostring-like functions. -- This "is" a standalone version, with comments and tests, of: -- (find-angg "LUA/lua50init.lua" "Tos") -- but I haven't tested its standaloneness in ages... -- -- See also: (find-es "lua5" "Tos") -- (find-es "lua5" "Tos-2021") -- (find-angg "LUA/tos.lua") -- (find-angg "LUA/Tos2.lua") -- «.Tos» (to "Tos") -- «.tos0-and-tosp» (to "tos0-and-tosp") -- «.mytostring» (to "mytostring") -- «.PP» (to "PP") -- «.HTable-and-VTable» (to "HTable-and-VTable") -- «.tests» (to "tests") -- From: (find-angg "LUA/lua50init.lua" "eoo") -- (find-dn6 "eoo.lua") -- Class = { type = "Class", __call = function (class, o) return setmetatable(o, class) end, } setmetatable(Class, Class) -- From: (find-angg "LUA/lua50init.lua" "compat") -- (find-angg "LUA/lua50init.lua" "pack-and-unpack") -- (find-angg "LUA/lua50init.lua" "printf") -- (find-angg "LUA/lua50init.lua" "sorted") -- (find-angg "LUA/lua50init.lua" "map") -- format = string.format write = io.write pack = table.pack or function (...) return {n=select("#", ...), ...} end printf = function (...) write(format(...)) end -- sorted = function (tbl, lt) table.sort(tbl, lt); return tbl end map = function (f, arr, n) local brr = {} for i=1,(n or #arr) do table.insert(brr, (f(arr[i]))) end return brr end mapconcat = function (f, tbl, sep, n) return table.concat(map(f, tbl, n), sep) end rawtostring = function (o) if type(o) == "table" then local mt = getmetatable(o); setmetatable(o, nil) local rawtos = tostring(o); setmetatable(o, mt) return rawtos end return tostring(o) end rawtostring_comp = function (o1, o2) local t1, t2 = type(o1), type(o2) if t1 == t2 then if t1 == "number" then return o1 < o2 end if t1 == "string" then return o1 < o2 end return rawtostring(o1) < rawtostring(o2) -- fast else return t1 < t2 -- numbers before strings before tables, etc end end -- «Tos» (to ".Tos") -- Also here: (find-angg "LUA/lua50init.lua" "Tos") -- Tos = Class { type = "Tos", __index = { -- -- Basic methods: -- o: object (of any type) to string -- ov: like o, but vertical in a simplistic way -- t: table to string -- t0: table to string, low level -- kvs: listofkeyvaluepairs to string -- kv: keyvaluepair to string -- k: key to string -- o = function (tos, o, a,sep,b,emp) local ty = type(o) if ty=="number" then return tostring(o) end if ty=="string" then return format("%q", o) end if ty=="table" then return tos:t(o, a,sep,b,emp) end return "<"..tostring(o)..">" end, ov = function (tos, o, a,sep,b,emp) return tos:o(o, "{ ", ",\n ", "\n}", "{}") end, t = function (tos, T, a,sep,b,emp) return tos:t0(T, a,sep,b,emp) end, t0 = function (tos, T, a,sep,b,emp) local tableisempty = (next(T) == nil) if tableisempty and emp then return emp end local body = tos:kvs(tos:getsortedkvs(T), sep) return (a or "{")..body..(b or "}") end, -- kvs = function (tos, ps, sep) local tos_p = function (p) return tos:kv(p) end return mapconcat(tos_p, ps, sep or ", ") end, kv = function (tos, p) return tos:k(p.key).."="..tos:o(p.val) end, k = function (tos, k) return tos:o(k) end, -- -- t0 uses this to sort the key-value pairs of a table. getsortedkvs = function (tos, T) return sorted(tos:getkvs(T), tos.comparekvs) end, getkvs = function (tos, T) local kvs = {} for k,v in pairs(T) do table.insert(kvs, {key=k, val=v}) end return kvs end, comparekvs = function (kv1, kv2) -- not a method! local k1, k2 = kv1.key, kv2.key return rawtostring_comp(k1, k2) local t1, t2 = type(k1), type(k2) -- if t1 == t2 then -- if t1 == "number" then return k1 < k2 end -- if t1 == "string" then return k1 < k2 end -- return rawtostring(k1) < rawtostring(k2) -- fast -- else -- return t1 < t2 -- numbers before strings before tables, etc -- end end, -- -- return a tostring-like function f = function (tos, a,sep,b,emp) return function (o) return tos:o(o, a,sep,b,emp) end end, -- -- An alternative to t. -- When tos is an object of the class Tos -- and foo is an object of the class Foo we have this: -- tos:t (foo) --> "{...}" -- tos:tp(foo) --> "Foo:{...}" -- tp = function (tos, T, a,sep,b,emp) -- experimental local mt = getmetatable(T) local typename = mt and mt.type local prefix = typename and (typename..":") or "" return prefix..tos:t0(T, a,sep,b,emp) end, }, } -- «tos0-and-tosp» (to ".tos0-and-tosp") -- Two objects of the class Tos. -- "tos0" uses all the default methods, -- "tosp" overrides ":t" with ":tp" to display class names. tos0 = Tos({}) tosp = Tos({t = Tos.__index.tp}) -- «mytostring» (to ".mytostring") -- Basic tostring-ish functions. -- To override them, redefine these functions. mytostring = function (o) return tos0:o (o) end mytostringv = function (o) return tos0:ov(o) end mytostringp = function (o) return tosp:o (o) end mytostringpv = function (o) return tosp:ov(o) end mytabletostring = function (o) return tos0:ov(o) end -- old name -- «PP» (to ".PP") -- Basic pretty-printing functions. PPV = function (o) print(mytabletostring(o)); return o end PP = function (...) return PP_(mytostring, ...) end PP_ = function (tos, ...) local args = pack(...) for i=1,args.n do printf(" %s", tos(args[i])) end print() return ... end -- «HTable-and-VTable» (to ".HTable-and-VTable") -- See: (find-angg "LUA/lua50init.lua" "HTable-and-VTable") -- «tests» (to ".tests") -- (getenv "LUA_INIT") -- (setenv "LUA_INIT" nil) -- (setenv (concat "@" (ee-expand "~/LUA/lua50init.lua")) -- --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Tos.lua" Aaa = Class { type = "Aaa", __tostring = mytostring, __index = { }, } Bbb = Class { type = "Bbb", __tostring = mytostringpv, __index = { }, } A = Aaa {1, 2, 3} B = Bbb {10, 20, 30} C = {30, A, B, 40} PPV(A) PP(A, B) = A = B = C = mytostring(C) = mytostringv(C) = mytostringp(C) = mytostringpv(C) --]] -- Local Variables: -- coding: utf-8-unix -- End: