Warning: this is an htmlized version!
The original is here, 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


--]]