Warning: this is an htmlized version!
The original is across this link,
and the conversion rules are here.
-- This file:
--   http://angg.twu.net/dednat6/dednat6/minimalcore.lua.html
--   http://angg.twu.net/dednat6/dednat6/minimalcore.lua
--                (find-dednat6 "dednat6/minimalcore.lua")
--
-- The .tex file that tests this:
--   http://angg.twu.net/dednat6/demo-core.tex.html
--   http://angg.twu.net/dednat6/demo-core.tex
--                (find-dednat6 "demo-core.tex")
--
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
-- Version: 2020jun06

-- This is a single-file implementation of the "core" of dednat6.
-- It only implements one head: "%L".
-- It doesn't depend on edrxlib.lua (that has LOTS of cruft).
-- It desn't change "require" to work more like standard Lua - see 
-- lualoader.lua.








-- Some functions from edrxlib.lua.
-- From: (find-angg "LUA/lua50init.lua")
--
fnamedirectory    = function (fname) return fname:match"^(.*/)[^/]*$"  end
fnamenondirectory = function (fname) return fname:match     "([^/]*)$" end

readfile = function (fname)
    local f = assert(io.open(fname, "r"))
    local bigstr = f:read("*a")
    f:close()
    return bigstr
  end
ee_expand = function (path)
    path = string.gsub(path, "^~$", "$HOME/", 1)
    path = string.gsub(path, "^~/", "$HOME/", 1)
    path = string.gsub(path, "^%$(%w+)", os.getenv, 1)
    return path
  end
ee_readfile  = function (fname) return readfile(ee_expand(fname)) end

split = function (str, pat)
    local arr = {}
    string.gsub(str, pat or "([^%s]+)", function (word)
        table.insert(arr, word)
      end)
    return arr
  end
splitlines = function (bigstr)
    local arr = split(bigstr, "([^\n]*)\n?")
    if _VERSION:sub(5) < "5.3" then
      table.remove(arr)
    end
    return arr
  end

string.len8 = function (str) return str:gsub("[\128-\191]+", ""):len() end
strlen8 = string.len8
untabify_table =
  {"        ", "       ", "      ", "     ", "    ", "   ", "  ", " "}
--{"--------", "-------", "------", "-----", "----", "---", "--", "-"}
untabify8_strtab = function (strbeforetab)
    return strbeforetab ..
      untabify_table[math.fmod(strlen8(strbeforetab), 8) + 1]
  end
untabify8 = function (str)
    return (gsub(str, "([^\t\r\n]*)\t", untabify8_strtab))
  end
untabify = untabify8





-- From: (find-dn6file "eoo.lua")
Class = {
    type   = "Class",
    __call = function (class, o) return setmetatable(o, class) end,
  }
setmetatable(Class, Class)


-- From: (find-dn6file "output.lua")
deletecomments1 = function (line)
    return line:match"^([^%%]*)"
  end
deletecomments = function (bigstr)
    return (bigstr:gsub("([^\n]+)", deletecomments1))
  end
output = function (str)
    tex.print(deletecomments(str))
    print(str)
  end


-- From: (find-dn6file "heads.lua")
heads = {}
registerhead = function (headstr)
    return function (head)
        head.headstr = headstr
        heads[headstr] = head
      end
  end
registerhead "%L" {
  name   = "lua",
  action = function ()
      local i,j,luacode = tf:getblockstr()
      local chunkname = tf.name..":%L:"..i.."-"..j
      assert(loadstring(luacode, chunkname))()
    end,
}



-- From: (find-dn6file "block.lua")
--
TexLines = Class {
  type = "TexLines",
  new  = function (name, lines)
      return TexLines({name=name}):setlines(lines)
    end,
  read = function (fname)
      return TexLines.new(fnamenondirectory(fname), ee_readfile(fname))
    end,
  test = function (str)
      local tr = {["L"]="%L", ["D"]="%D", [":"]="%:", ["p"]="\\pu"}
      local tl = TexLines {name="(test)"}
      for c in str:gmatch"." do table.insert(tl, tr[c] or c) end
      return tl
    end,
  __tostring = function (tl) return tl:tostring() end,
  __index = {
    setlines = function (tl, lines)
        if type(lines) == "string" then lines = splitlines(lines) end
        for i=1,#lines do tl[i] = lines[i] end
        return tl
      end,
    nlines = function (tl) return #tl end,
    line = function (tl, i) return tl[i] end,
    --
    head = function (tl, i)
        local li = tl:line(i)
        local p = function (len)
            local s = li:sub(1, len)
            return heads[s] and s
          end
        return li and (p(3) or p(2) or p(1) or p(0))
      end,
    nohead = function (tl, i)
        return tl:line(i):sub(#tl:head(i) + 2)
      end,
    --
    tostring1 = function (tl, i) return format("%3d: %s", i, tl:line(i)) end,
    tostring  = function (tl, i, j)
        local T = {}
        for k=(i or 1),(j or tl:nlines()) do
          table.insert(T, tl:tostring1(k))
        end
        return table.concat(T, "\n")
      end,
    --
    toblock = function (tl)
        return Block {i=1, j=#tl, nline=1, name=tl.name}
      end,
  },
}

headblocks = {}   -- a "log" of all the head blocks processed so far

Block = Class {
  type    = "Block",
  __tostring = mytostring,
  __index = {
    firstheadblockin = function (bl, i0, j0)
        local i,j
        for i1=i0,j0 do
          if texlines:head(i1) then i=i1; break end 
        end
        if not i then return end
        local head = texlines:head(i)
        for j1=i+1,j0 do
          if texlines:head(j1) ~= head then
            return Block {i=i, j=j1-1, head=head}
          end 
        end
        return Block {i=i, j=bl.j, head=head}
      end,
    --
    processheadblock = function (bl)
        lastheadblock = bl                    -- for ":getblock()"s
        table.insert(headblocks, bl)
        local action = heads[bl.head].action  -- uses "tf:getblock()"
        if action then action() else print("No action for "..bl.head) end
      end,
    processarbitraryblock = function (bl)
        -- print("process arbitrary:", mytostring(bl))
        local i0 = bl.i
        while true do
          local headbl = bl:firstheadblockin(i0, bl.j)
          if not headbl then return end
          headbl:processheadblock()
          i0 = headbl.j + 1
        end
      end,
    process = function (bl)
        -- print("process:", mytostring(bl))
        if bl.head
        then bl:processheadblock(bl)
        else bl:processarbitraryblock(bl)
        end
      end,
    --
    processuntil = function (bl, puline)
        local publock = Block {i=bl.nline, j=puline-1}
        publock:process()
        bl.nline = puline+1
        return bl
      end,
    --
    getblock = function (bl)
        local i,j,head = lastheadblock.i, lastheadblock.j, lastheadblock.head
        local A = {}
        for k=i,j do
            table.insert(A, texlines:line(k):sub(#head+1))
          end
        return i,j,A
      end,
    getblockstr = function (bl)
        local i,j,A = tf:getblock()
        return i,j,table.concat(A, "\n")
      end,
    -- hyperlink = function (bl)
    --     return "Line "..lastheadblock.i
    --   end,
    hyperlink = function (bl)
        return format("In the \"%s\"-block in lines %d--%d",
                      lastheadblock.head, lastheadblock.i, lastheadblock.j)
      end,
  },
}

texfile0 = function (fname)
    texlines = TexLines.read(fname)
    tf = texlines:toblock()
  end
texfile = function (fname)
    texfile0(fname..".tex")
  end

pu = function (puline) tf:processuntil(puline or tex.inputlineno) end