|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file:
-- http://anggtwu.net/LUA/Maxima3.lua.html
-- http://anggtwu.net/LUA/Maxima3.lua
-- (find-angg "LUA/Maxima3.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- See: (find-angg "MAXIMA/2025-baf-qparts.mac")
-- (find-Maxima3-links)
--
-- (defun e () (interactive) (find-angg "LUA/Maxima3.lua"))
-- (defun o () (interactive) (find-angg "LUA/Maxima2.lua"))
-- (defun oe () (interactive) (find-2a '(o) '(e)))
--
-- «.MaximaIO» (to "MaximaIO")
-- «.MaximaIO-tests» (to "MaximaIO-tests")
-- «.MaximaParse» (to "MaximaParse")
-- «.MaximaParse-tests» (to "MaximaParse-tests")
-- «.MaximaTeX» (to "MaximaTeX")
-- «.MaximaTeX-tests» (to "MaximaTeX-tests")
-- «.MaximaHead» (to "MaximaHead")
-- «.MaximaHead-tests» (to "MaximaHead-tests")
-- «.SplitMaximaLog1» (to "SplitMaximaLog1")
-- «.SplitMaximaLog1-tests» (to "SplitMaximaLog1-tests")
-- «.SplitMaximaLog» (to "SplitMaximaLog")
-- «.SplitMaximaLog-tests» (to "SplitMaximaLog-tests")
-- «.log-to-i» (to "log-to-i")
require "Co1" -- (find-angg "LUA/Co1.lua")
require "Pict3" -- (find-angg "LUA/Pict3.lua")
-- __ __ _ ___ ___
-- | \/ | __ ___ _(_)_ __ ___ __ _|_ _/ _ \
-- | |\/| |/ _` \ \/ / | '_ ` _ \ / _` || | | | |
-- | | | | (_| |> <| | | | | | | (_| || | |_| |
-- |_| |_|\__,_/_/\_\_|_| |_| |_|\__,_|___\___/
--
-- «MaximaIO» (to ".MaximaIO")
MaximaIO = Class {
type = "MaximaIO",
__tostring = function (mio) return mio:torect():tostring() end,
__index = {
r = function (mio,name)
if not mio[name] then return Rect {} end
if #mio[name]==0 then return Rect {} end
local right = Rect(copy(mio[name]))
local left = Rect {format("%-3s ", name..":")}
return left..right
end,
torect = function (mio)
return mio:r"i" / mio:r"ip" / mio:r"o"
end,
push = function (mio,name,line)
mio[name] = mio[name] or VTable {}
table.insert(mio[name], line)
return mio
end,
},
}
-- «MaximaIO-tests» (to ".MaximaIO-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Maxima3.lua"
m = MaximaIO {i={"a","b"}, ip={"c"}, o={"d","e"}, op={}}
= m:r"i"
= m:r"i" / m:r"ip"
= m:r"i" / m:r"ip" / m:r"foo"
= m:torect()
= m
= m:push("o","f")
= m:push("op","g")
--]]
-- __ __ _ ____
-- | \/ | __ ___ _(_)_ __ ___ __ _| _ \ __ _ _ __ ___ ___
-- | |\/| |/ _` \ \/ / | '_ ` _ \ / _` | |_) / _` | '__/ __|/ _ \
-- | | | | (_| |> <| | | | | | | (_| | __/ (_| | | \__ \ __/
-- |_| |_|\__,_/_/\_\_|_| |_| |_|\__,_|_| \__,_|_| |___/\___|
--
-- «MaximaParse» (to ".MaximaParse")
MaximaParse = Class {
type = "MaximaParse",
fromlines = function (lines) return MaximaParse{}:parselines(lines) end,
__tostring = function (mp) return mp:torect():tostring() end,
__index = {
torect = function (mp)
local rect = Rect {}
local mios = mp.mios or {}
for i=1,#mios do
local mio = MaximaIO(copy(mios[i]))
local left = Rect {format("%-4s ", "("..i.."):")}
local right = mio:torect()
rect = rect / (left..right)
end
return rect
end,
addmio = function (mp)
mp.mios = mp.mios or {}
table.insert(mp.mios, MaximaIO {})
return mp
end,
lastmio = function (mp) return MaximaIO(mp.mios[#mp.mios]) end, -- set metatable
push = function (mp,name,line) mp:lastmio():push(name,line); return mp end,
--
-- The state machine
splitline = function (mp,line)
local kind,n,body = line:match("^%(%%([io])([0-9]+)%) ?(.*)")
if kind then return kind,n,body end
return nil,nil,line -- the whole line becomes the body
end,
parseline_inner = function (mp,state,kind,line)
if kind=="i" then mp:addmio():push("i",line); return "i" end
if kind=="o" then mp :push("o",line); return "o" end
if kind==nil and state=="i" then mp:push("ip",line); return "i" end
error("Bad transition: state=%s, kind=%s", state, kind)
end,
parseline = function (mp,line)
local kind,n,body = mp:splitline(line)
local state = mp.state
local newstate = mp:parseline_inner(state,kind,line)
mp.state = newstate
return mp
end,
parselines = function (mp,lines)
if type(lines)=="string" then lines = splitlines(lines) end
for _,line in ipairs(lines) do mp:parseline(line) end
return mp
end,
},
}
maximaparse_iines = Rect {
"(%i1) a,",
" b;",
"(%o1) a b",
"(%i2) c$",
}
-- «MaximaParse-tests» (to ".MaximaParse-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Maxima3.lua"
mp = MaximaParse {}
mp = MaximaParse {mios={{i={"a"}},
{i={"b"}}}}
= mp:push("i", "c")
= mp:push("i", "d"):push("o", "e"):addmio():push("i", "f")
= mp:splitline("(%i42) foo")
= mp:splitline("(%i42)foo")
= mp:splitline("(%i42)")
= mp:splitline("bla")
mp = MaximaParse.fromlines(maximaparse_iines)
= mp
--]]
-- __ __ _ _____ __ __
-- | \/ | __ ___ _(_)_ __ ___ __ |_ _|__\ \/ /
-- | |\/| |/ _` \ \/ / | '_ ` _ \ / _` || |/ _ \\ /
-- | | | | (_| |> <| | | | | | | (_| || | __// \
-- |_| |_|\__,_/_/\_\_|_| |_| |_|\__,_||_|\___/_/\_\
--
-- «MaximaTeX» (to ".MaximaTeX")
-- (find-angg "LUA/Maxima2.lua" "MaximaLine")
MaximaTeX = Class {
type = "MaximaTeX",
linestorect = function (lines)
local mp = MaximaParse{}:parselines(lines)
local mios = mp.mios
return MaximaTeX{}:miosrect(mios)
end,
linestovbox = function (lines)
return MaximaTeX{}:vbox(MaximaTeX.linestorect(lines))
end,
linestopict = function (lines)
return Pict { MaximaTeX.linestovbox(lines) }
end,
__index = {
match = function (mt,str,pat)
local result = str:match(pat)
if not result then PP("Doesn't match:", pat, str); error("") end
return result
end,
left = function (mt,line) return mt:match(line, "^(%(%%[io][0-9]+%) ?).*") end,
right = function (mt,line) return mt:match(line, "^%(%%[io][0-9]+%) ?(.*)") end,
spaces = function (mt,line) return (mt:left(line):gsub(".", " ")) end,
indent = function (mt,iline,ipline) return mt:spaces(iline)..ipline end,
--
--co = Co.new(" \\%{}$_", "^~"),
co = Co.new("\\%{}$_", " ^~"),
cot = function (mt,str) return mt.co:translate(str) end,
blue0 = function (mt,a) return format("\\maximablue{%s}", a) end,
red0 = function (mt,a,b) return format("\\maximared{%s}{%s}", a,b) end,
blue = function (mt,a) return mt:blue0(mt:cot(a)) end,
red = function (mt,a,b) return mt:red0 (mt:cot(a), b) end,
blue1 = function (mt,iline) return mt:blue(iline) end,
blue2 = function (mt,iline,ipline) return mt:blue1(mt:indent(iline,ipline)) end,
red1 = function (mt,line) return mt:red(mt:left(line),mt:right(line)) end,
redleft = function (mt,line) return mt:red(mt:left(line),"") end,
redright = function (mt,line) return mt:red("",mt:right(line)) end,
--
miorect = function (mt,mio)
local iline = mio.i[1]
local irect = Rect {mt:blue1(iline)}
local iprect = Rect {}
local orect = Rect {}
for _,ipline in ipairs(mio.ip or {}) do
table.insert(iprect, mt:blue2(iline,ipline))
end
for _,oline in ipairs(mio.o or {}) do
table.insert(orect, mt:redleft(oline))
table.insert(orect, mt:redright(oline))
table.insert(orect, mt:red0("",""))
end
return irect / iprect / orect
end,
miosrect = function (mt,mios)
local bigrect = Rect {}
for _,mio in ipairs(mios) do bigrect = bigrect / mt:miorect(mio) end
return bigrect
end,
vbox = function (mt,rect)
return format("\\vbox{%s}", table.concat(rect))
end,
},
}
-- «MaximaTeX-tests» (to ".MaximaTeX-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
* (eepitch-lua54)
* (eepitch-kill)
* (eepitch-lua54)
dofile "Maxima3.lua"
mt = MaximaTeX {}
iline = "(%i1) 42"
ipline = "33"
oline = "(%o1) 99"
PP(iline)
PP(mt:left(iline))
PP(mt:right(iline))
PP(mt:spaces(iline))
PP(mt:indent(iline, ipline))
PP(mt:blue1(iline))
PP(mt:blue2(iline, ipline))
PP(mt:red1(oline))
lines = {
"(%i1) a,",
"b;",
"(%o1) a b",
"(%i2) c$"
}
= MaximaTeX.linestorect(lines)
= MaximaTeX.linestovbox(lines)
MaximaTeX.__index.co = Co.new("", "")
= MaximaTeX.linestorect(lines)
= MaximaTeX.linestovbox(lines)
= MaximaTeX.linestopict(lines)
= MaximaTeX.linestopict(lines):sa"foo"
--]]
-- __ __ _ _ _ _
-- | \/ | __ ___ _(_)_ __ ___ __ _| | | | ___ __ _ __| |
-- | |\/| |/ _` \ \/ / | '_ ` _ \ / _` | |_| |/ _ \/ _` |/ _` |
-- | | | | (_| |> <| | | | | | | (_| | _ | __/ (_| | (_| |
-- |_| |_|\__,_/_/\_\_|_| |_| |_|\__,_|_| |_|\___|\__,_|\__,_|
--
-- «MaximaHead» (to ".MaximaHead")
-- (find-angg "LUA/Maxima2.lua" "MaximaHead")
MaximaHead = Class {
type = "MaximaHead",
__index = {
sa = function (mh, name)
MaximaTeX.linestopict(mh.lines):sa(name):output()
end,
},
}
maximahead = MaximaHead {}
registerhead = registerhead or function () return nop end
registerhead "%M" {
name = "maxima",
action = function ()
local i,j,lines = tf:getblock(3)
maximahead.lines = VTable(lines)
end,
}
-- «MaximaHead-tests» (to ".MaximaHead-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Maxima3.lua"
maximahead.lines = VTable {
"(%i1) a,",
"b;",
"(%o1) ab",
"(%i2) c$"
}
output = output or print
maximahead:sa("foo")
maximahead.lines = table.concat(maximahead.lines, "\n")
maximahead:sa("foo")
--]]
-- ____ _ _ _ __ __ _ _ _
-- / ___| _ __ | (_) |_| \/ | __ ___ _(_)_ __ ___ __ _| | ___ __ _/ |
-- \___ \| '_ \| | | __| |\/| |/ _` \ \/ / | '_ ` _ \ / _` | | / _ \ / _` | |
-- ___) | |_) | | | |_| | | | (_| |> <| | | | | | | (_| | |__| (_) | (_| | |
-- |____/| .__/|_|_|\__|_| |_|\__,_/_/\_\_|_| |_| |_|\__,_|_____\___/ \__, |_|
-- |_| |___/
--
-- «SplitMaximaLog1» (to ".SplitMaximaLog1")
SplitMaximaLog1 = Class {
type = "SplitMaximaLog1",
__tostring = function (sl) return sl:tostring() end,
__index = {
tostring = function (sl) return sl:torect():tostring() end,
torect = function (sl) return sl.name..": "..Rect(splitlines(sl.bigstr)) end,
sa = function (sl)
local addM = function (line) return format("%%M %s\n", line) end
local linesM = mapconcat(addM, splitlines(sl.bigstr))
return format("%s%%L\n%%L maximahead:sa(\"%s\", \"\")\n\\pu", linesM, sl.name)
end,
ga = function (sl)
local fmt = "\\vspace*{0cm}\n\\def\\hboxthreewidth{9cm}\n\\ga{%s}"
return format(fmt, sl.name)
end,
},
}
-- «SplitMaximaLog1-tests» (to ".SplitMaximaLog1-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Maxima3.lua"
sl = SplitMaximaLog1 {name="aaa", bigstr="(%i1) foo\n(%o1) bar"}
= sl
= sl:sa()
= sl:ga()
--]]
-- ____ _ _ _ __ __ _ _
-- / ___| _ __ | (_) |_| \/ | __ ___ _(_)_ __ ___ __ _| | ___ __ _
-- \___ \| '_ \| | | __| |\/| |/ _` \ \/ / | '_ ` _ \ / _` | | / _ \ / _` |
-- ___) | |_) | | | |_| | | | (_| |> <| | | | | | | (_| | |__| (_) | (_| |
-- |____/| .__/|_|_|\__|_| |_|\__,_/_/\_\_|_| |_| |_|\__,_|_____\___/ \__, |
-- |_| |___/
--
-- «SplitMaximaLog» (to ".SplitMaximaLog")
SplitMaximaLog = Class {
type = "SplitMaximaLog",
from = function (bigstr)
if type(bigstr) == "table" then bigstr = table.concat(bigstr, "\n") end
return SplitMaximaLog({bigstr=bigstr}):calcdivs():getlog1s()
end,
__tostring = function (sml) return sml:tostring() end,
__index = {
tostring = function (sml)
return mapconcat(tostring, sml, "\n\n")
end,
calcdivs = function (sml)
sml.divs = VTable {}
local pat = "()%(%%i[0-9]+%) ()/%* block (.-) %*/\n()"
for p0,p1,name,p2 in sml.bigstr:gmatch(pat) do
table.insert(sml.divs, {name=name, p0=p0, p1=p1, p2=p2})
end
table.insert(sml.divs, {p0=#sml.bigstr})
return sml
end,
getlog1 = function (sml,n)
local str01 = sml.bigstr:sub(sml.divs[n].p0, sml.divs[n].p1 - 1)
local str23 = sml.bigstr:sub(sml.divs[n].p2, sml.divs[n+1].p0 - 1)
local name = sml.divs[n].name
return SplitMaximaLog1 {name=name, bigstr=str01..str23}
end,
getlog1s = function (sml)
local blocks = VTable {}
sml:calcdivs()
for i=1,#sml.divs-1 do sml[i] = sml:getlog1(i) end
return sml
end,
sas = function (sml, sep)
local f = function (sml1) return sml1:sa() end
if sep then return mapconcat(f, sml, sep) else return map(s, sml) end
end,
gas = function (sml, sep)
local f = function (sml1) return sml1:ga() end
if sep then return mapconcat(f, sml, sep) else return map(s, sml) end
end,
all_gas_in_one_slide = function (sml)
local body = sml:gas("\n\n}\\def\\colwidth{7.5cm}\\anothercol{\n\n")
return "\\scalebox{0.6}{\\def\\colwidth{9cm}\\firstcol{\n\n"..body.."\n\n}}"
end,
all_in_one_slide = function (sml)
return sml:sas("\n\n").."\n\n"..sml:all_gas_in_one_slide()
end,
},
}
lines_maximalog = Rect {
"(%i42) linenum : 0$",
"(%i1) /* block aaaaa */",
"a+b;",
"(%o1) b + a",
"(%i2) /* block bbbbb */",
"foo;",
"(%o2) foo",
"(%i3) ",
}
-- «SplitMaximaLog-tests» (to ".SplitMaximaLog-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Maxima3.lua"
s = SplitMaximaLog.from(lines_maximalog)
= s
= s.bigstr
= s.divs
= s:sas("\n\n")
= s:gas("\n\n")
= s:all_gas_in_one_slide()
= s: all_in_one_slide()
--]==]
-- «log-to-i» (to ".log-to-i")
-- Converts a log of a Maxima session to some LaTeX/Dednat code
-- that can be inserted into a .tex file with `M-x i'. See:
-- (find-efunction 'find-Maxima3-links)
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Maxima3.lua"
bigstr = ee_readfile "/tmp/o"
s = SplitMaximaLog.from(bigstr)
= s
o2 = s:sas("\n\n")
= o2
o2 = s:all_in_one_slide()
= o2
ee_writefile("/tmp/o2", o2)
** (find-fline "/tmp/o2")
* (defun i () (interactive) (insert-file "/tmp/o2"))
--]]
-- Local Variables:
-- coding: utf-8-unix
-- End: