Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: -- http://anggtwu.net/LUA/Dednat7.lua.html -- http://anggtwu.net/LUA/Dednat7.lua -- (find-angg "LUA/Dednat7.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- -- The core of dednat6, rewritten as a small number of classes with -- nice __tostring metamethods and nice test blocks. Based on: -- (find-angg "LATEX/dednat6/minimalcore.lua") -- (find-dn6file "minimalcore.lua") -- -- Typically loaded by: -- (find-angg "LUA/dednat7load.lua") -- «.Head» (to "Head") -- «.Head-tests» (to "Head-tests") -- «.Heads» (to "Heads") -- «.lua-head» (to "lua-head") -- «.Heads-tests» (to "Heads-tests") -- «.AllTeXFiles» (to "AllTeXFiles") -- «.AllTeXFiles-tests» (to "AllTeXFiles-tests") -- «.TeXFile» (to "TeXFile") -- «.TeXFile-tests» (to "TeXFile-tests") -- «.Block» (to "Block") -- «.Block-getblock» (to "Block-getblock") -- «.Block-tests» (to "Block-tests") -- «.Blocks» (to "Blocks") -- «.Blocks-tests» (to "Blocks-tests") -- «.texfile0» (to "texfile0") -- «.high-level-test» (to "high-level-test") require "Output1" -- (find-angg "LUA/Output1.lua") -- _ _ _ -- | | | | ___ __ _ __| | -- | |_| |/ _ \/ _` |/ _` | -- | _ | __/ (_| | (_| | -- |_| |_|\___|\__,_|\__,_| -- -- Typical usage: when we do something like this -- heads:registerhead "%L" {name="lua", action=function () end} -- this adds a new "Head" object to "heads". -- See: (to "Heads") -- (to "Heads-tests") -- (find-dn6 "heads6.lua" "abbrev-head") -- (find-dn6 "heads6.lua" "lua-head") -- -- «Head» (to ".Head") Head = Class { type = "Head", __tostring = function (head) return mytostringv(head) end, __index = { }, } -- «Head-tests» (to ".Head-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Dednat7.lua" = Head {name = "foo", action = function () end} --]] -- _ _ _ -- | | | | ___ __ _ __| |___ -- | |_| |/ _ \/ _` |/ _` / __| -- | _ | __/ (_| | (_| \__ \ -- |_| |_|\___|\__,_|\__,_|___/ -- -- Typical usage: -- heads = Heads {} -- heads:registerhead "%L" {name="lua", action=function () end} -- heads:registerhead "%:" {name="tree", action=function () end} -- See: (find-dn6 "heads6.lua" "registerhead") -- -- «Heads» (to ".Heads") Heads = Class { type = "Heads", __tostring = function (heads) return "Registered heads: "..mapconcat(mytostring, sortedkeys(heads), ", ") end, __index = { headstrfor = function (heads, li) local p = function (len) local s = li:sub(1, len) return heads[s] and s end return p(5) or p(4) or p(3) or p(2) or p(1) or p(0) end, headfor = function (heads, li) local headstr = heads:headstrfor(li) return headstr and heads[headstr] end, registerhead = function (heads, headstr) return function (tbl) tbl.headstr = headstr heads[headstr] = Head(tbl) return heads end end, }, } -- «lua-head» (to ".lua-head") -- Based on: (find-dn6 "heads6.lua" "lua-head") heads = Heads {} registerhead = function (...) return heads:registerhead(...) end registerhead "%L" { name = "lua", action = function () local i,j,luacode = tf:getblockstr(3) local chunkname = tf.name..":%L:"..i.."-"..j assert(loadstring(luacode, chunkname))() end, } -- «Heads-tests» (to ".Heads-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Dednat7.lua" = heads heads["%LL"] = "bar" heads["%D"] = 42 = heads = heads:headstrfor "%LL bla" = heads:headstrfor "%L bla" = heads:headstrfor "blop" = heads:headfor "%LL bla" = heads:headfor "%L bla" = heads:headfor "blop" heads:registerhead "%P" { name = "foo", action = function () end } = heads = heads["%P"] = heads:headstrfor "%P bla" = heads:headfor "%P bla" --]] -- _ _ _ _____ __ _______ _ _ -- / \ | | |_ _|__\ \/ / ___(_) | ___ ___ -- / _ \ | | | | |/ _ \\ /| |_ | | |/ _ \/ __| -- / ___ \| | | | | __// \| _| | | | __/\__ \ -- /_/ \_\_|_| |_|\___/_/\_\_| |_|_|\___||___/ -- -- «AllTeXFiles» (to ".AllTeXFiles") AllTeXFiles = Class { type = "AllTeXFiles", __tostring = function (atf) if #keys(atf) == 0 then return "(no TeXFiles objects registered)" end local f = function (k) return format("%q -> %d lines", k, #atf[k]) end local ks = sorted(keys(atf)) return mapconcat(f, ks, "\n") end, __index = { }, } alltexfiles = AllTeXFiles {} -- «AllTeXFiles-tests» (to ".AllTeXFiles-tests") --[==[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Dednat7.lua" = alltexfiles alltexfiles["a.tex"] = {"a", "b", "c", "d", "e"} alltexfiles["bb.tex"] = VTable {"a", "b", "c", name="bb.tex"} = alltexfiles = alltexfiles["a.tex"] = alltexfiles["bb.tex"] --]==] -- _____ __ _______ _ _ -- |_ _|__\ \/ / ___(_) | ___ -- | |/ _ \\ /| |_ | | |/ _ \ -- | | __// \| _| | | | __/ -- |_|\___/_/\_\_| |_|_|\___| -- -- A TeXFile object is a .tex file split into lines and with a -- "name" field. A texfile object also has a "blocks" field, -- that is initially empty. -- -- Based on: (find-dn6 "minimalcore.lua" "heads") -- «TeXFile» (to ".TeXFile") TeXFile = Class { type = "TeXFile", read = function (name) return TeXFile.from(name, ee_readfile(name)) end, from = function (name, lines) return TeXFile.from0(name):setlines(lines):register() end, from0 = function (name) return TeXFile {name=name, blocks=Blocks{}} end, __tostring = function (tf) return format("TeXFile: %q\n%s\n%s", tf.name, tf:linestostring(), tostring(tf.blocks)) end, __index = { line = function (tf,k) return tf[k] end, linetostring = function (tf,k) return format("%3d: %s", k, tf[k]) end, linestostring = function (tf,i,j) i,j = i or 1, j or #tf local f = function (k) return tf:linetostring(k) end return mapconcat(f, seq(i,j), "\n") end, register = function (tf) alltexfiles[tf.name] = tf return tf end, setlines = function (tf, lines) if type(lines) == "string" then lines = splitlines(unixnewlines(lines)) end for i=1,#lines do tf[i] = lines[i] end return tf end, -- headstr = function (tf,k) return heads:headstrfor(tf[k]) end, head = function (tf,k) return heads:headfor(tf[k]) end, getj = function (tf,i) local j,headstr = i,tf:headstr(i) while j<#tf and tf:headstr(j+1)==headstr do j = j+1 end return j end, buildblock = function (tf,i) return Block.from(i, tf:getj(i), tf.name, tf:headstr(i)) end, -- hasblocks = function (tf) return #tf.blocks > 0 end, lastblock = function (tf,k) return tf.blocks[#tf.blocks + (k or 0)] end, lastj = function (tf) return tf:lastblock().j end, anotherblock = function (tf) if #tf == 0 then return end if tf:hasblocks() and tf:lastj() == #tf then return end local i = tf:hasblocks() and tf:lastj()+1 or 1 local bl = tf:buildblock(i) table.insert(tf.blocks, bl) return bl end, -- lastj_or_0 = function (tf) return tf:hasblocks() and tf:lastj() or 0 end, processlast = function (tf) return tf:lastblock():doaction() end, processnext = function (tf) if tf:anotherblock() then -- if verbose then print(tf:lastblock())end tf:processlast() end end, processuntil = function (tf,puline,verbose) tf.puline = puline -- used by output:puinfo() if verbose then output:puinfo() end if puline > #tf then puline = #tf end -- to avoid a loop while tf:lastj_or_0() < puline do tf:processnext() end end, -- -- For compatibility with Dednat6: getblock = function (tf,...) return thisblock:getblock(...) end, getblockstr = function (tf,...) return thisblock:getblockstr(...) end, luachunkname = function (tf,...) return thisblock:luachunkname(...) end, hyperlink = function (tf,...) return thisblock:hyperlink(...) end, }, } pu = function (puline,verbose) tf:processuntil(puline or tex.inputlineno, verbose) end -- «TeXFile-tests» (to ".TeXFile-tests") --[==[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Dednat7.lua" lis = VTable {"1", "2", "%L print(3,", "%L 4)", "5", "6"} tf = TeXFile.from("a.tex", lis) = alltexfiles = alltexfiles["a.tex"] heads = Heads {} heads:registerhead "%:" {name="tree", action=function () end} heads:registerhead "%L" { name = "lua", action = function () thisbody = thisblock:untabifys(3, "", "\n") print(thisbody) -- global end, } = heads = tf:anotherblock() = tf:anotherblock() = tf:anotherblock() = tf:anotherblock() = tf = tf.blocks = tf.blocks[2] = tf.blocks[2]:untabifys() = tf.blocks[2]:untabifys(nil, nil, "\n") = tf.blocks[2]:untabifys(3, nil, "\n") = tf.blocks[2]:untabifys(3, "", "\n") = tf.blocks[2]:untabifys(3, "---", "\n") = tf.blocks[1]:head() = tf.blocks[2]:head() = tf.blocks[1]:action() = tf.blocks[2]:action() = tf.blocks[1]:doaction() = tf.blocks[2]:doaction() tf.blocks = Blocks {} -- reset = tf = tf:lastj_or_0() tf:processnext("verbose") tf:processnext("verbose") tf:processnext("verbose") tf.blocks = Blocks {} -- reset tf:processuntil(200, "verbose") --]==] -- ____ _ _ -- | __ )| | ___ ___| | __ -- | _ \| |/ _ \ / __| |/ / -- | |_) | | (_) | (__| < -- |____/|_|\___/ \___|_|\_\ -- -- «Block» (to ".Block") -- Block = Class { type = "Block", from = function (i,j,name,headstr) return Block {i=i, j=j, name=name, headstr=headstr} end, __tostring = function (bl) return bl:tostring() end, __index = { ijtostring = function (bl) return bl.i.."--"..bl.j end, luachunkname = function (bl) return bl.name..":%L:"..bl.i.."-"..bl.j end, tostring = function (bl) return format("%7s in %s: %s", bl:ijtostring(), bl.name, mytostring(bl.headstr)) end, -- texlines = function (bl) return alltexfiles[bl.name] end, line = function (bl, k) return bl:texlines()[k] end, head = function (bl) return bl.headstr and heads[bl.headstr] end, action = function (bl) return bl:head() and bl:head().action end, doaction = function (bl) thisblock = bl -- set a global lastheadblock = bl -- same, for compatibility with dednat6 local action = bl:action() if action then output:blockinfo(); return action() end end, -- untabify = function (bl, k, cut, newprefix) local line = untabify8(bl:line(k)) if cut then line = line:sub(cut+1) end if newprefix then line = newprefix..line end return line end, untabifys = function (bl, cut, newprefix, sep) local f = function (k) return bl:untabify(k, cut, newprefix) end local o = map(f, seq(bl.i, bl.j)) if sep then o = table.concat(o, sep) end return o end, -- -- «Block-getblock» (to ".Block-getblock") -- (find-dn6 "minimalcore.lua" "Block" "getblock =") getblock = function (bl, cut) local i,j = bl.i,bl.j local lines = bl:untabifys(cut or #(thisblock.headstr)+1) return i,j,lines end, getblockstr = function (bl, cut) local i,j = bl.i,bl.j local blockstr = bl:untabifys(cut, nil, "\n") return i,j,blockstr end, -- -- Old, recycle: hyperlink = function (bl) return format("In the \"%s\"-block in lines %d--%d", lastheadblock.headstr, lastheadblock.i, lastheadblock.j) end, }, } -- «Block-tests» (to ".Block-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Dednat7.lua" = Block.from(4,6, "a.tex", "%L") = Block.from(4,6, "b.tex") --]] -- ____ _ _ -- | __ )| | ___ ___| | _____ -- | _ \| |/ _ \ / __| |/ / __| -- | |_) | | (_) | (__| <\__ \ -- |____/|_|\___/ \___|_|\_\___/ -- -- «Blocks» (to ".Blocks") Blocks = Class { type = "Blocks", __tostring = function (bls) return "Blocks:\n"..mapconcat(tostring, bls, "\n") end, __index = { }, } -- «Blocks-tests» (to ".Blocks-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Dednat7.lua" bls = Blocks { Block.from(1,4, "a.tex"), Block.from(5,6, "a.tex", "%L"), Block.from(7,8, "a.tex"), } = bls --]] -- Old: -- «texfile0» (to ".texfile0") texfile0 = function (fname) -- texlines = TexLines.read(fname) -- tf = texlines:toblock() tf = TeXFile.read(fname) texlines = tf end texfile = function (fname) texfile0(fname..".tex") end -- «high-level-test» (to ".high-level-test") --[[ -- (find-angg "LUA/Dednat7.lua" "lua-head" "i,j,luacode =") -- (find-angg "LUA/Dednat7.lua" "Block" "untabifys =") * (ee-write-string "1\n2\n%L print(3,\n%L 4)\n5\n6\n" "/tmp/o.tex") ** (find-fline "/tmp/o.tex") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Dednat7.lua" tf = TeXFile.read("/tmp/o.tex") = tf pu(#tf+1, "verbose") PPV(tf) pu(#tf+2, "verbose") pu(#tf+3) = tf pu(6) = tf PP(tf) = tf.blocks = tf.blocks[2] registerhead "%L" { name = "lua", action = function () local i,j,luacode = tf:getblockstr(3) local chunkname = tf:luachunkname() -- local i,j,luacode = thisblock:getblockstr(3) -- local chunkname = thisblock:luachunkname() print(thisblock) print(i,j,luacode,chunkname) end, } --]] -- (defun e () (interactive) (find-angg "LUA/DedNat7.lua")) -- Local Variables: -- coding: utf-8-unix -- End: