Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
--   http://anggtwu.net/LUA/Indent2.lua.html
--   http://anggtwu.net/LUA/Indent2.lua
--          (find-angg "LUA/Indent2.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- This file defines the class Indent and the lowest-level methods of
-- the class Pict. The middle-level methods of the class Pict are
-- defined, and explained, here:
--
--  (find-angg "LUA/Pict3.lua" "PictBounds-methods")
--  (find-angg "LUA/Pict3.lua" "Pict-show")
--
-- This file does not implement a ":show()" method for pict objects;
-- see the link to "Pict-show" above.
--
-- (defun e  () (interactive) (find-angg "LUA/Indent2.lua"))
-- (defun e1 () (interactive) (find-angg "LUA/ELpeg1.lua"))
-- (defun i1 () (interactive) (find-angg "LUA/Indent1.lua"))
-- (defun i2 () (interactive) (find-angg "LUA/Indent2.lua"))
-- (defun p2 () (interactive) (find-angg "LUA/Pict2e2.lua"))
-- (defun p3 () (interactive) (find-angg "LUA/Pict3.lua"))

-- «.Indent»		(to "Indent")
-- «.Indent-tests»	(to "Indent-tests")
-- «.Pict»		(to "Pict")
-- «.Pict-tests»	(to "Pict-tests")

require "Stack1"  -- (find-angg "LUA/Stack1.lua")
require "ELpeg1"  -- (find-angg "LUA/ELpeg1.lua" "Gram")

spaces = function (n) return string.rep(" ", n) end

flatten = function (o)
    local out = VTable {}
    local add   -- recursive, defined in the next line
    add = function (x)
        if type(x) == "table"
        then map(add, x)
        else table.insert(out, x)
        end
      end
    add(o)
    return out
  end


--  ___           _            _   
-- |_ _|_ __   __| | ___ _ __ | |_ 
--  | || '_ \ / _` |/ _ \ '_ \| __|
--  | || | | | (_| |  __/ | | | |_ 
-- |___|_| |_|\__,_|\___|_| |_|\__|
--                                 
-- «Indent»  (to ".Indent")

Indent = Class {
  type  = "Indent",
  from  = function (bigstr) return Indent.from0(bigstr):concat() end,
  from0 = function (bigstr) return Indent.new():split(bigstr):runall() end,
  new   = function ()
      return Indent {stack=Stack.new(), prefixn=0, outs=VTable{}}
    end,
  makepat = function (open, close)
      local tocmd   = function (tbl) return HTable(tbl) end
      local toitems = function (tbl) return VTable(tbl) end
      local gr,V = Gram.new()
      V.o       = P(open)
      V.c       = P(close)
      V.hs      = S" \t"
      V.s       = S" \t\n"
      V.ss      = V.s^0
      V.l       = V.ss:C():Cg"l"
      V.r       = V.ss:C():Cg"r"
      V.cmdbody = ((-V.c*P(1))^0):C():Cg"cmdbody"
      V.cmd     = (V.l * V.o * V.cmdbody * V.c * V.r):Ct() / tocmd
      V.nl      = P"\n":Ct() / tocmd
      V.hspaces = (V.hs^1):C()
      V.other   = ((-V.s * -V.o * -V.c * P(1))^1):C()
      V.item    = V.cmd + V.hspaces + V.nl + V.other
      V.toitems = (V.item^0):Ct() / toitems
      return gr:compile("toitems")
    end,
  setopenclose = function (open, close)
      Indent.__index.o = open
      Indent.__index.c = close
      Indent.__index.pat = Indent.makepat(open, close)
    end,
  __index = {
    -- o = "<",   -- open
    -- c = ">",   -- close
    -- pat = Indent.makepat("<", ">"),
    --
    -- :ocfix(str) lets us write the delimiters as "<" and ">".
    -- For example, if o is "[." and c is ".]",
    -- then:      ind:ocfix("foo <i:pop()> bar")
    -- returns:            "foo [.i:pop().] bar"
    --
    ocfix = function (ind,str)
        return (str:gsub("([<>])", {["<"]=ind.o, [">"]=ind.c}))
      end,
    --
    split0 = function (ind,bigstr) return ind.pat:match(bigstr) end,
    split  = function (ind,bigstr) ind.ins = ind:split0(bigstr); return ind end,
    prefix = function (ind,delta) return spaces(ind.prefixn + (delta or 0)) end,
    nl     = function (ind,delta) return "\n"..ind:prefix(delta) end,
    ind    = function (ind,delta)
        ind.stack:push(ind.prefixn)
        ind.prefixn = ind.prefixn+delta
        return ind
      end,
    pop    = function (ind) ind.prefixn = ind.stack:pop(); return ind end,
    out    = function (ind,o) table.insert(ind.outs, o); return ind end,
    concat = function (ind) return table.concat(ind.outs) end,
    --
    runstr = function (ind,s) ind:out(s); return ind end,
    runnl  = function (ind)   ind:out(ind:nl()); return ind end,
    runcmd = function (ind,c)
        local l = c.l
        local r = c.r
        local o = l..r
        local cmd = format("local i,l,r,o=...; %s\nreturn o", c.cmdbody)
        local o2 = assert(loadstring(cmd))(ind, l, r, o)
        ind:out(o2)
      end,
    runo  = function (ind,o)
        if type(o) == "string" then ind:runstr(o)
        elseif not o.cmdbody then ind:runnl()
        else ind:runcmd(o)
        end
        return ind
      end,
    runall = function (ind)
        for _,o in ipairs(ind.ins) do ind:runo(o) end
        return ind
      end,
  },
}

Indent.setopenclose("<", ">")

-- «Indent-tests»  (to ".Indent-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Indent2.lua"
bigstr = "abc def <foo> \nbar\nplic"
bigstr = "abc def\nbar\nplic"
bigstr = "aaa\nbbb\nccc<i:ind(2)>ddd\neee\nfff<i:pop()>ggg\nhhh"
i = Indent.new():split(bigstr)
= i
= i.ins
= i.outs
= i:runall()
= i.outs
= i:concat()

bigstr = "foo{<i:ind(2);o=i:nl()>\nbar<i:pop()>\n}"
= Indent.from(bigstr)

Indent.setopenclose("[",     "]")
Indent.setopenclose("<<.", ".>>")
bigstr = "foo{[   i:ind(2);o=i:nl()   ]\nbar[   i:pop()   ]\n}"
bigstr = "foo{<<. i:ind(2);o=i:nl() .>>\nbar<<. i:pop() .>>\n}"
i = Indent.new():split(bigstr)
= i
= i.ins
= Indent.from(bigstr)

= Indent({}):ocfix("foo<o=i:nl()> bar")

--]]




--  ____  _      _   
-- |  _ \(_) ___| |_ 
-- | |_) | |/ __| __|
-- |  __/| | (__| |_ 
-- |_|   |_|\___|\__|
--                   
-- «Pict»  (to ".Pict")
-- Based on: (find-angg "LUA/Pict2e2.lua" "Pict")
-- See:      (find-angg "LUA/Pict3.lua" "Pict-show")
--
Pict = Class {
  type = "Pict",
  __tostring = function (o) return o:tostring() end,
  __index = {
    tostring = function (o,percent)
        local bigstr = o:indent()
        if percent then bigstr = bigstr:gsub("\n", "%%\n") end
        return bigstr
      end,
    indent = function (o) return Indent.from(o:concat()) end,
    concat = function (o) return table.concat(flatten(o), "\n") end,
    --
    output  = function (p) output(p:tostring("%")) end,
    add     = function (o,o2) table.insert(o, o2); return o end,
    print   = function (o,o2) return p:add(o) end,
    printf  = function (o,...) return p:add(format(...)) end,
    pprintf = function (o,...) return p:add(pformat(...)) end,
    --
    glue_     = "<o=''>",
    ["{+1"]   = "{<i:ind(1);o=''>",
    ["{+2"]   = "{<i:ind(2);o=i:nl()>",
    ["}"]     = "<i:pop();o=''>}",
    ["nl}"]   = "<i:pop();o=i:nl()>}",
    ["$+1"]   = "<i:ind(1);o='$'>",
    ["$$+2"]  = "<i:ind(2);o='$$'>",
    ["{$+1"]  = "<i:ind(1);o='{$'>",
    ["pop$"]  = "<i:pop();o='$'>",
    ["pop$$"] = "<i:pop();o='$$'>",
    ["pop$}"] = "<i:pop();o='$}'>",
    ["+2nl"]  = "<i:ind(2);o=i:nl()>",
    ["popnl"] = "<i:pop(); o=i:nl()>",
    --
    cmd0 = function (o,str) return Indent({}):ocfix(str) end,
    cmd  = function (o,tag) return Indent({}):ocfix(o[tag]) end,
    glue   = function (o) return Pict {o:cmd0("glue_")} end,
    --
    pre0   = function (o,prestr) return Pict({prestr, o}) end,
    preg   = function (o,prestr) return Pict({prestr, o:cmd("glue_"), o}) end,
    pre    = function (o,prestr) return prestr and o:preg(prestr) or o end,
    wrap0  = function (o,tag1,tag2) return Pict({o:cmd(tag1), o, o:cmd(tag2)}) end,
    wrapp  = function (o,tag1,tag2,prestr) return o:wrap0(tag1,tag2):pre(prestr) end,
    wrap1  = function (o, prestr) return o:wrapp("{+1",      "}", prestr) end,
    wrap2  = function (o, prestr) return o:wrapp("{+2",    "nl}", prestr) end,
    wrap1d = function (o, prestr) return o:wrapp("{$+1", "pop$}", prestr) end,
    wrapsp = function (o, prestr) return o:wrapp("+2nl", "popnl", prestr) end,
    wrapbe = function (o,b,e) return Pict {b, o:wrapsp(), e} end,
    --
    em        = function (o) return o:wrap1("\\ensuremath")  end,
    d         = function (o) return o:wrapp("$+1",   "pop$") end,
    dd        = function (o) return o:wrapp("$$+2", "pop$$") end,
    def       = function (o, name) return o:wrap2("\\def\\"..name) end,
    sa        = function (o, name) return o:wrap2("\\sa{"..name.."}") end,
    color     = function (o, color) return o:pre0("\\color{"..color.."}"):wrap1() end,
    Color     = function (o, color) return o:wrap1("\\Color"..color) end,
    precolor0 = function (o, color) return o:pre0("\\color{"..color.."}") end,
    precolor  = function (o, color) return o:pre0("\\color{"..color.."}"):wrap1() end,
    prethickness = function (o, th) return o:pre0("\\linethickness{"..th.."}") end,
    preunitlength = function (o, u) return o:pre0("\\unitlength="..u) end,
    bhbox     = function (o) return o:wrap1d("\\bhbox") end,
    myvcenter = function (o) return o:wrap1("\\myvcenter") end,
    putat     = function (o, xy) return o:wrap1(pformat("\\put%s", xy)) end,
    --
    scalebox  = function (o, scale)
        if not scale then return o end
        return o:em():wrap2("\\scalebox{"..scale.."}")
      end,
  },
}

-- «Pict-tests»  (to ".Pict-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Indent2.lua"
= Pict {"bar"} :wrapp("{+2", "nl}", "\\foo")
= Pict {"foo", "bar"} :wrap1()
= Pict {"foo", "bar"} :wrap1("\\text")
= Pict {"foo", "bar"} :wrap1("\\ensuremath")
= Pict {"foo", "bar"} :wrap2()
= Pict {"foo", "bar"} :wrap2("\\pre")
= Pict {"foo", "bar"} :wrap2("\\pre") :tostring()
= Pict {"foo", "bar"} :wrap2("\\pre") :tostring("%")
= Pict {"foo", "bar"} :wrap2("\\pre") :concat()
= Pict {"foo", "bar"} :d()
= Pict {"foo", "bar"} :dd()
= Pict {"foo", "bar"} :def("plic")
= Pict {"foo", "bar"} :sa ("plic")
= Pict {"foo", "bar"} :color("red")
= Pict {"foo", "bar"} :Color("Red")
= Pict {"foo", "bar"} :precolor("red")
= Pict {"foo", "bar"} :prethickness("2pt")
= Pict {"foo", "bar"} :preunitlength("2pt")
= Pict {"foo", "bar"} :bhbox()
= Pict {"foo", "bar"} :myvcenter()
= Pict {"foo", "bar"} :putat("(2,3)")
= Pict {"foo", "bar"} :wrapbe("aaa", "bbb")
= Pict {"foo", "bar"} :wrapbe("aaa", "bbb"):wrapbe("ccc", "ddd")

glue = "<o=''>"
nl   = "<o='\\n'>"
p    = "<o=i:prefix()>"
b    = "<i:ind(2);o=''>"
e    = "<i:pop();o=''>"

= Pict {"aaa", glue, nl, b, "foo", "bar", glue, e, "bbb"}   -- good
= Pict {"aaa",       nl, b, "foo", "bar", glue, e, "bbb"}   -- good
= Pict {"aaa", glue, nl, b, "foo", "bar", e, glue, "bbb"}
= Pict {"aaa", glue, nl, b, "foo", "bar", e, nl, "bbb"}

b = "<i:ind(2);o=i:nl()>"
e = "<i:pop();o=i:nl()>"
= Pict {"aaa", b, "foo", "bar", e, "bbb"}



Indent.setopenclose("<<.", ".>>")
= Pict {"foo", "bar"} :wrap2("\\pre")
= Pict {"foo", "bar"} :wrap2("\\pre") :concat()

--]]


-- (find-angg "LUA/Indent1.lua" "flatten")




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