Warning: this is an htmlized version! The original is across this link, and the conversion rules are here.
```-- Draw in a rectangular grid in ascii

spaces = function (n) return (" "):rep(n) end
padto = function (str, n)
if #str >= n
then return str
else return str .. spaces(n - #str)
end
end
replace = function (orig, h, new)
if h < 1 then new = new:sub(2 - h); h = 1 end
orig = padto(orig or "", h - 1)
return orig:sub(1, h - 1) .. new .. orig:sub(h + #new)
end
newcanvas   = function () return {minv=1, maxv=1} end
printcanvas = function (f)
for v=canvas.minv,canvas.maxv do (f or print)(canvas[v] or "") end
end
plot = function (v, h, str)
canvas[v] = replace(canvas[v], h, str)
canvas.minv = min(canvas.minv, v)
canvas.maxv = max(canvas.maxv, v)
end
floor  = math.floor
round  = function (x) return math.floor(x + 0.4995) end
xtoh   = function (x) return (x + 1) * 10 end
ytov   = function (y) return (y + 1) * -10 end
xyplot = function (x, y, str)
plot(round(ytov(y)), round(xtoh(x)), str)
end

--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
ee_dofile "~/LUA/canvas.lua"
-- A demo: draw a senoid
canvas = newcanvas()
for y=-1,1,.05 do xyplot(0, y, "|") end
for x=-2,6,.05 do xyplot(x, 0, "-") end
for x=-2,6,.1 do xyplot(x, math.sin(x), "O") end
xyplot(0, 0, "a")
printcanvas(PP)

canvas = newcanvas()
plot(1, 1, "AA")
plot(2, 3, "BB")
printcanvas()

--]]

-- tnodes
-- This is a new data structure that I plan to implement in dednat4.
-- Example:
--
--   line 10:    a  b
--   line 11:    ----
--   line 12:     a,b   a,b|->c
--   line 13:     -------------
--   line 14:          c
--
tnodes = {}
tnodes["10:1"] = {left=0, right=0, above=0, text="a", tabove={}}
tnodes["10:2"] = {left=0, right=0, above=0, text="b", tabove={}, leftdx=2}
tnodes["11:1"] = {left=0, right=0, above=1, text="----", tabove={"10:1", "10:2"}}
tnodes["12:1"] = {left=1, right=0, above=2, text="a,b",  tabove={"11:1"}, abovedx=1}
tnodes["12:2"] = {left=0, right=0, above=0, text="a,b|->c", tabove={}, leftdx=3}
tnodes["13:1"] = {left=1, right=0, above=3, text="-------------", tabove={"12:1", "12:2"}}
tnodes["14:1"] = {left=6, right=7, above=4, text="c", tabove={"13:1"}, abovedx=5}

tnodeplot1 = function (tnode, x, y)
plot(y, x, tnodes[tnode].text)
end

Plot = P

gettnode = function (tagortnode)
if type(tagortnode) == "string" then return tnodes[tagortnode] end
if type(tagortnode) == "table"  then return tagortnode end
end

tnodeboxwidth = function (tn)
tn = gettnode(tn)
return tn.left + #(tn.text) + tn.right
end

tnode_get = function (tn) return type(tn) == "string" and tnodes[tn] or tn end
tnode_llldx = function (tn) tn = tnode_get(tn); return tn.llldx or 2 end
tnode_lldx = function (tn) tn = tnode_get(tn); return tn.lldx or tn.ldx or 0 end
tnode_ldx = function (tn) tn = tnode_get(tn); return tn.ldx or 0 end
tnode_rrdx = function (tn) tn = tnode_get(tn); return tn.rrdx or tn.rdx or 0 end
tnode_text = function (tn) tn = tnode_get(tn); return tn.text end
tnode_above = function (tn) tn = tnode_get(tn); return tn.above end
tnode_boxwidth = function (tn)
tn = tnode_get(tn)
return tnode_lldx(tn) + #(tn.text) + tnode_rrdx(tn)
end

tnode_plotwithrootat = function (tn, x, y)
tn = tnode_get(tn)
plot(y, x, tn.text)
local tabove = tn.tabove or {}
if #tabove > 0 then
y = y - 1
x = x - tnode_ldx(tn)
local ta = tabove[1]
tnode_plotwithrootat (ta, x, y)
x = x + #(tnode_text(ta)) + tnode_rrdx(ta)
for i=2,#tabove do
ta = tabove[i]
x = x + tnode_llldx(ta) + tnode_lldx(ta)
tnode_plotwithrootat (ta, x, y)
x = x + #(tnode_text(ta)) + tnode_rrdx(ta)
end
end
end
tnode_plot = function (tn)
tnode_plotwithrootat(tn, tnode_lldx(tn) + 1, tnode_above(tn) + 1)
end

tnodeplot = function (tn, x, y)
tn = gettnode(tn)
x = x or tn.left + 1
y = y or tn.above + 1
PP("x,y,tn:", x,y,tn)
plot(y, x, tn.text)
y = y - 1
x = x - (tn.abovedx or 0)
for i=1,#(tn.tabove) do
local tna = gettnode(tn.tabove[i])
PP("tna:", tna)
x = x + (tna.leftdx or 0)
tnodeplot(tna, x, y)
x = x + tnodeboxwidth(tna)
end
end

--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
ee_dofile "~/LUA/canvas.lua"
-- A demo: draw a senoid
canvas = newcanvas()
tnodeplot "14:1"
printcanvas(PP)
-- for y=-1,1,.05 do xyplot(0, y, "|") end

tnodes = {}
tnodes["10:1"] =       {text="a"}
tnodes["10:2"] = {llldx=2, text="b"}
tnodes["11:1"] =       {text="----",        above=1, tabove={"10:1", "10:2"}}
tnodes["12:1"] = {ldx=1, text="a,b", rdx=0, above=2, tabove={"11:1"}}
tnodes["12:2"] = {llldx=3,     text="a,b|->c"}
tnodes["13:1"] = {ldx=1, text="-------------", rdx=0, above=3, tabove={"12:1", "12:2"}}
tnodes["14:1"] = {lldx=6, ldx=5, text="c",     rdx=7, above=4, tabove={"13:1"}}

canvas = newcanvas()
tnode_plot("14:1")
printcanvas(PP)

aaaaaaaa   bbbbbbbbbbbb
=======================
ccccccc
===========================
dddddddd
<--------|
ldx or 0
|---------------->
lldx or ldx or 0
|------>
#text

tnodeboxwidth = function (tn)
tn = gettnode(tn)
return (tn.lldx or tn.ldx or 0) + #(tn.text) + (tn.rrdx or tn.rdx or 0)
end

tnodeplot = function (tn, x, y)
tn = gettnode(tn)
x = x or 1
y = y or
x = (x or tn.lldx or tn.ldx or 0) + 1
y = (y or tn.above or 0) + 1
PP("x,y,tn:", x,y,tn)
plot(y, x, tn.text)
y = y - 1
x = x - (tn.ldx or 0)
for i=1,#(tn.tabove) do
local tna = gettnode(tn.tabove[i])
PP("tna:", tna)
x = x + (tna.llldx or 0)
tnodeplot(tna, x, y)
x = x + tnodeboxwidth(tna)
end
end

--]]

```