|
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: