|
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: