Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: -- http://anggtwu.net/LUA/Maxima2.lua.html -- http://anggtwu.net/LUA/Maxima2.lua -- (find-angg "LUA/Maxima2.lua") -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- -- Long story short: I found emaxima.sty too limited and too hard to -- modify, and I wrote this Lpeg-based tool to convert the output of -- Maxima with "display2d:'emaxima" to LaTeX code. -- -- The "too limited" above means: emaxima.sty changes catcodes -- temporarily, and because of that it was super hard to use -- emaxima.sty to put Maxima code in "\vbox"es. -- -- An example of input (in the .tex, in the "%M" lines) and output: -- -- http://anggtwu.net/LATEX/2023-2-C2-edovs.tex.html#4-inversas-maxima -- http://anggtwu.net/LATEX/2023-2-C2-Tudo.pdf#page=221 -- 2hT221 (c2m232edovsp 13 "4-inversas-maxima") -- (c2m232edovsa "4-inversas-maxima") -- (find-es "maxima" "qdraw-4-inverses") -- -- See: (find-es "maxima" "Maxima2.lua") -- (defun o () (interactive) (find-angg "LUA/Maxima1.lua")) -- (defun e () (interactive) (find-angg "LUA/Maxima2.lua")) -- «.MaximaLine» (to "MaximaLine") -- «.MaximaLine-tests» (to "MaximaLine-tests") -- «.MaximaIO» (to "MaximaIO") -- «.MaximaIO-tests» (to "MaximaIO-tests") -- «.MaximaIOs» (to "MaximaIOs") -- «.MaximaIOs-tests» (to "MaximaIOs-tests") -- «.grammar» (to "grammar") -- «.grammar-tests» (to "grammar-tests") -- «.MaximaHead» (to "MaximaHead") -- «.MaximaHead-tests» (to "MaximaHead-tests") -- «.head» (to "head") -- «.show2» (to "show2") -- «.show2-tests» (to "show2-tests") -- «.show2-tests-head» (to "show2-tests-head") -- «.show2-tests-prep» (to "show2-tests-prep") require "ELpeg1" -- (find-angg "LUA/ELpeg1.lua") require "Show2" -- (find-angg "LUA/Show2.lua") require "Co1" -- (find-angg "LUA/Co1.lua") require "DeleteComments2" -- (find-angg "LUA/DeleteComments2.lua") deletecomments = deletecomments_2023 -- __ __ _ _ _ -- | \/ | __ ___ _(_)_ __ ___ __ _| | (_)_ __ ___ -- | |\/| |/ _` \ \/ / | '_ ` _ \ / _` | | | | '_ \ / _ \ -- | | | | (_| |> <| | | | | | | (_| | |___| | | | | __/ -- |_| |_|\__,_/_/\_\_|_| |_| |_|\__,_|_____|_|_| |_|\___| -- -- «MaximaLine» (to ".MaximaLine") -- See: (find-LATEX "edrx21.sty" "maximablue-red") MaximaLine = Class { type = "MaximaLine", ify = function (tbl) return MaximaLine(tbl) end, __tostring = function (ml) return mytostring(ml) end, __index = { co = Co.new(" \\%{}$_", "^~"), cot = function (ml, str) return ml.co:translate(str) end, blue0 = function (ml, a) return format("\\maximablue{%s}", a) end, red0 = function (ml, a,b) return format("\\maximared{%s}{%s}", a,b) end, type1tex = function (ml) return ml:blue0(ml:cot(ml.c .. ml.d)) end, type2tex = function (ml, c) local spaces = c:gsub(".", " ") return ml:blue0(ml:cot(spaces .. ml.d)) end, type3tex = function (ml) --local fmt = "$\displaystyle %s$" local fmt = "%s" return ml:red0(ml:cot(ml.c), ""), ml:red0("", format(fmt, ml.d)), ml:red0("", "") end, }, } -- «MaximaLine-tests» (to ".MaximaLine-tests") --[[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Maxima2.lua" ml1 = MaximaLine.ify {a="i", b="42", c="(%i42) ", d="2+"} ml2 = MaximaLine.ify { d="3;"} ml3 = MaximaLine.ify {a="o", b="42", c="(%o42) ", d="5"} = ml1 = ml2 = ml3 = ml1:type1tex() = ml2:type2tex("(%i42) ") = ml3:type3tex() --]] -- __ __ _ ___ ___ -- | \/ | __ ___ _(_)_ __ ___ __ _|_ _/ _ \ -- | |\/| |/ _` \ \/ / | '_ ` _ \ / _` || | | | | -- | | | | (_| |> <| | | | | | | (_| || | |_| | -- |_| |_|\__,_/_/\_\_|_| |_| |_|\__,_|___\___/ -- -- In the first version of this program an object of the class -- MaximaIO (a "mio") was always a list made of an "(%i<n>)" line and -- an "(%o<n>)" line associated to it. A mio could represent something -- like this: -- -- (%i42) 2+3; -- (%o42) 5 -- -- Then I realized the in my logs of Maxima sessions I could have mios -- like this one: -- -- (%i1) a+ -- b+ -- 42; c+d; e+f; -- (%o1) b + a + 42 -- (%o2) d + c -- (%o3) f + e -- -- each "(%i<n>)" line can be followed by some continuation lines, and -- this can be followed by zero or more "(%o<n>)" lines. See the test -- block for the details. -- -- «MaximaIO» (to ".MaximaIO") MaximaIO = Class { type = "MaximaIO", ify = function (tbl) return MaximaIO(tbl) end, __tostring = function (mio) return mio:totyped() end, __index = { tovtable = function (mio) local vt = VTable {mio[1]} for _,ml in ipairs(mio[2]) do table.insert(vt, ml) end for _,ml in ipairs(mio[3]) do table.insert(vt, ml) end return vt end, totyped = function (mio) local prefix = (mio[1].c):gsub(".", " ") local vt = VTable {} local add = function (str) table.insert(vt, str) end local addtype1 = function (ml) add("type 1: "..ml.c ..ml.d) end local addtype2 = function (ml) add("type 2: "..prefix..ml.d) end local addtype3 = function (ml) add("type 3: "..ml.c ..ml.d) end addtype1(mio[1]) for _,ml in ipairs(mio[2]) do addtype2(ml) end for _,ml in ipairs(mio[3]) do addtype3(ml) end return table.concat(vt, "\n") end, toboxes = function (mio) local prefix = (mio[1].c):gsub(".", " ") local vt = VTable {} local add = function (str) table.insert(vt, str) end local adds = function (...) for _,o in ipairs({...}) do add(o) end end local addtype1 = function (ml) add(ml:type1tex()) end local addtype2 = function (ml) add(ml:type2tex(prefix)) end local addtype3 = function (ml) adds(ml:type3tex()) end addtype1(mio[1]) for _,ml in ipairs(mio[2]) do addtype2(ml) end for _,ml in ipairs(mio[3]) do addtype3(ml) end return vt end, toboxesconcat = function (mio, sep) return table.concat(mio:toboxes(), sep or "\n") end, a = function (mio) return mio:totyped() end, b = function (mio,sep) return mio:toboxesconcat(sep) end, ab = function (mio,sep) return mio:a().."\n"..mio:b(sep) end, }, } -- «MaximaIO-tests» (to ".MaximaIO-tests") --[==[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Maxima2.lua" mio = MaximaIO.ify {"a", {"b", "c"}, {"d", "e"}} = mio:tovtable() mio = MaximaIO.ify { MaximaLine_parse "(%i1) a+", -- type 1: (%i<n>) { MaximaLine_parse "b+", -- type 2: continuation MaximaLine_parse "42; c+d; e+f;", -- type 2: continuation }, { MaximaLine_parse "(%o1) b + a + 42", -- type 3: (%o<n>) MaximaLine_parse "(%o2) d + c", -- type 3: (%o<n>) MaximaLine_parse "(%o3) f + e", -- type 3: (%o<n>) } } = mio:tovtable() = mio:totyped() = mio:toboxes() = mio:toboxesconcat() = mio:toboxesconcat(" \\\\\n") = mio:a () = mio: b() = mio: b(" \\\\\n") = mio:ab() = mio:ab(" \\\\\n") bigstr = [[ (%i1) a+ b+ 42; c+d; e+f; (%o1) b + a + 42 (%o2) d + c (%o3) f + e (%i4) ]] mios = MaximaIOs_parse(bigstr) = mios[1] = mios[2] = otype(mios[1]) * (eepitch-maxima) * (eepitch-kill) * (eepitch-maxima) a+ b+ 42; c+d; e+f; --]==] -- __ __ _ ___ ___ -- | \/ | __ ___ _(_)_ __ ___ __ _|_ _/ _ \ ___ -- | |\/| |/ _` \ \/ / | '_ ` _ \ / _` || | | | / __| -- | | | | (_| |> <| | | | | | | (_| || | |_| \__ \ -- |_| |_|\__,_/_/\_\_|_| |_| |_|\__,_|___\___/|___/ -- -- An object of the class MaximaIOs (a "mios") is essentially just a -- list of objects of the class MaximaIO (a list of "mio"s). -- -- «MaximaIOs» (to ".MaximaIOs") MaximaIOs = Class { type = "MaximaIOs", __tostring = function (mios) return mios:ias() end, __index = { a = function (mios,i) return mios[i]:a() end, b = function (mios,i,sep) return mios[i]:b(sep) end, ab = function (mios,i,sep) return mios[i]:a().."\n"..mios[i]:b(sep) end, ias = function (mios) local f = function (i) return i..":\n"..mios:a(i) end return mapconcat(f, seq(1, #mios), "\n") end, iabs = function (mios,sep) local f = function (i) return i..":\n"..mios:ab(i,sep) end return mapconcat(f, seq(1, #mios), "\n") end, bs = function (mios, sep) local f = function (i) return mios:b(i,sep) end return mapconcat(f, seq(1, #mios), sep or "\n") end, debug = function (mios,sep) return mios:iabs(sep) end, totex = function (mios,sep) return mios:bs(sep) end, show = function (mios, opts) opts = opts or {} scale = opts.scale or 1 texbody = "\\vbox{\n"..mios:totex().."}" return Show.try(tostring(outertexbody)) end, -- show00 = function (mios,...) local texbody0 = "\\vbox{\n"..mios:totex().."}" return texbody0:show00(...) end, show0 = function (mios,...) return mios:show00(...):show0(...) end, show = function (mios,...) return mios:show00(...):show (...) end, }, } -- «MaximaIOs-tests» (to ".MaximaIOs-tests") --[==[ * (show2-use "$SHOW2LATEXDIR/") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Maxima2.lua" bigstr = [[ (%i1) a+ b+ 42; c+d; e+f; (%o1) b + a + 42 (%o2) d + c (%o2) f + e (%i3) ]] mios = MaximaIOs_parse(bigstr) = mios = mios[1] = mios[2] = mios:debug() = mios:debug(" \\\\\n") = mios:totex() = mios:totex(" \\\\\n") = mios:show00({scale=0.8}) = mios:show0 ({scale=0.8}) = mios:show ({scale=0.8}) = Show.log = Show.bigstr * (etv) --]==] -- __ _ _ __ __ _ _ __ ___ _ __ ___ __ _ _ __ -- / _` | '__/ _` | '_ ` _ \| '_ ` _ \ / _` | '__| -- | (_| | | | (_| | | | | | | | | | | | (_| | | -- \__, |_| \__,_|_| |_| |_|_| |_| |_|\__,_|_| -- |___/ -- -- «grammar» (to ".grammar") -- See: (find-es "lpeg" "lpeg.Cfromthere") -- (find-es "lpeg" "lpeg.Cobeying") -- gr,V,VAST,VEXPECT,PEXPECT = Gram.new() local gr,V,VAST,VEXPECT,PEXPECT = Gram.new() V.a = S"io":Cg"a" V.b = (R"09"^1):Cg"b" V.c0 = Cp():Cg"c" -- store the initial position in "c" V.c1 = Cb"c":Cfromthere():Cg"c" -- replace "c" by its :Cfromthere() V.abc = V.c0 * P"(%" * V.a * V.b * P")" * P" "^-1 * V.c1 V.d = ((1-S"\n")^0):C():Cg"d" V.abcd = V.abc^-1 * V.d V.abct = V.abc:Ct() V.abcdt = V.abcd:Ct() V.mline = V.abcd:Ct() / MaximaLine.ify V.mline1 = V.mline:Cobeying(function (ml) return ml.a == "i" end) V.mline2 = V.mline:Cobeying(function (ml) return ml.a == nil end) V.mline3 = V.mline:Cobeying(function (ml) return ml.a == "o" end) V.mio = (V.mline1 * ((P"\n" * V.mline2)^0):Ct() * ((P"\n" * V.mline3)^0):Ct() ):Ct() / MaximaIO.ify V.mios = (V.mio * (P"\n" * V.mio)^0) :Ct() Maxima_gr = gr MaximaLine_pat = gr:compile("mline") MaximaLine_parse = function (str) return MaximaLine_pat:match(str) end MaximaIOs_pat = gr:compile("mios") MaximaIOs_parse = function (str) local mios = MaximaIOs_pat:match(str) if type(mios) ~= "table" then print("MaximaIOs_pat:match failed! Input:") print(str) end return MaximaIOs(mios) end -- «grammar-tests» (to ".grammar-tests") --[==[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Maxima2.lua" = Maxima_gr:cm ("abc", "(%i42)") = Maxima_gr:cm ("abct", "(%i42)") = Maxima_gr:cm ("abcd", "(%i42)") = Maxima_gr:cmp("abcd", "(%i42)") PP(Maxima_gr:cm0("abct", "(%i42) foo")) PP(Maxima_gr:cm0("abcdt", "(%i42) foo")) Maxima_gr:cmp("abcdt", "(%i42) foo") PP(Maxima_gr:cm0("abcdt", "blarpy foo")) = Maxima_gr:cm0("mline", "(%i3) foo") = Maxima_gr:cm0("mline", "(%o42) foo") = Maxima_gr:cm0("mline", "blarpy foo") = Maxima_gr:cm0("mline1", "(%i3) foo") = Maxima_gr:cm0("mline1", "(%o42) foo") = Maxima_gr:cm0("mline1", "blarpy foo") = Maxima_gr:cm0("mline2", "(%i3) foo") = Maxima_gr:cm0("mline2", "(%o42) foo") = Maxima_gr:cm0("mline2", "blarpy foo") bigstr = [[ (%i1) a+ b+ 42; c+d; e+f; (%o1) b + a + 42 (%o2) d + c (%o3) f + e (%i4) ]] * (eepitch-maxima) * (eepitch-kill) * (eepitch-maxima) a+ b+ 42; c+d; e+f; --]==] -- __ __ _ _ _ _ -- | \/ | __ ___ _(_)_ __ ___ __ _| | | | ___ __ _ __| | -- | |\/| |/ _` \ \/ / | '_ ` _ \ / _` | |_| |/ _ \/ _` |/ _` | -- | | | | (_| |> <| | | | | | | (_| | _ | __/ (_| | (_| | -- |_| |_|\__,_/_/\_\_|_| |_| |_|\__,_|_| |_|\___|\__,_|\__,_| -- -- The code below tells Dednat6 how to handle blocks of comments -- in which each line starts with "%M". -- -- «MaximaHead» (to ".MaximaHead") MaximaHead = Class { type = "MaximaHead", __index = { set_maxima_lines = function (mh, origlines, delchars) local mtrim = function (li) if not delchars then return (li:gsub("^%%M ?", "")) end return li:sub(delchars+1) end if type(origlines) == "string" then origlines = splitlines(origlines) end maxima_lines00 = VTable(copy(origlines)) maxima_lines0 = VTable(map(mtrim, maxima_lines00)) maxima_lines = bitrim(table.concat(maxima_lines0, "\n")) return maxima_lines end, mios = function (mh) return MaximaIOs_parse(maxima_lines) end, sa000 = function (mh, sep) return maximahead:mios():totex(sep) end, sa00 = function (mh, sep) return "\\vbox{"..mh:sa000(sep).."}" end, sa0 = function (mh, name, sep) return format("\\sa{%s}{%%\n%s%%\n}", name, mh:sa00(sep)) end, sa = function (mh, name, sep) output(mh:sa0(name, sep)) end, -- M0 = function (mh) local addM = function (li) return "%M "..li end return VTable(map(addM, maxima_lines0)) end, M1 = function (mh) return bitrim(table.concat(mh:M0(), "\n")) end, M2 = function (mh,name) return '%L maximahead:sa("'..name..'", "")' end, M12 = function (mh,name) return mh:M1().."\n"..mh:M2(name).."\n\\pu" end, M3 = function (mh,name) return "\\ga{"..name.."}" end, show00 = function (mh,...) return mh:M12("foo").."\n\n"..mh:M3("foo"):show00(...) end, show0 = function (mh,...) return mh:show00(...):show0() end, show = function (mh,...) return mh:show00(...):show () end, }, } maximahead = MaximaHead {} -- «MaximaHead-tests» (to ".MaximaHead-tests") --[==[ * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Maxima2.lua" bigstr = [[ %M (%i1) a+ %M b+ %M 42; c+d; e+f; %M (%o1) b + a + 42 %M (%o2) d + c %M (%o3) f + e %M (%i4) %M ]] = maximahead:set_maxima_lines(bigstr, 0) -- delete 0 chars = maximahead:set_maxima_lines(bigstr, 3) -- delete 3 chars = maximahead:set_maxima_lines(bigstr) -- delete the "%M "s = maxima_lines00 = maxima_lines0 = maxima_lines = maximahead:sa000() = maximahead:sa00 () = maximahead:sa0 ("foo") = maximahead:M0() = maximahead:M1() = maximahead:M2 ("bar") = maximahead:M12("bar") = maximahead:M3 ("bar") = maximahead:show00 {scale=0.9} = maximahead:show0 {scale=0.9} = maximahead:show {scale=0.9} * (etv) = Show.log = Show.bigstr = maximahead:mios() = maximahead:mios():totex() = maximahead:mios():totex("%\n") = maximahead:mios():totex(" \\\\\n") = maximahead:sa00() = maximahead:sa00( " \\\\\n") = maximahead:sa0("foo") = maximahead:sa0("foo", " \\\\\n") output = print maximahead:sa ("foo") maximahead:sa ("foo", " \\\\\n") --]==] -- _ _ -- | |__ ___ __ _ __| | -- | '_ \ / _ \/ _` |/ _` | -- | | | | __/ (_| | (_| | -- |_| |_|\___|\__,_|\__,_| -- -- See: http://angg.twu.net/dednat6/tug-slides.pdf#page=17 -- http://angg.twu.net/dednat6/tugboat-rev2.pdf#page=4 -- https://tug.org/TUGboat/tb39-3/tb123ochs-dednat.pdf#page=4 -- -- «head» (to ".head") -- (find-angg "LUA/Verbatim1.lua" "vbt-head") registerhead = registerhead or function () return nop end registerhead "%M" { name = "maxima", action = function () local i,j,origlines = tf:getblock(0) maximahead:set_maxima_lines(origlines) end, } -- «show2» (to ".show2") -- (find-angg "LUA/Show2.lua" "dednat6" "dednat6_Maxima2") -- (find-LATEX "edrx21.sty" "maximablue-red") dednat6_Maxima2 = [==[ % (find-Deps1-cps "Maxima2") %L dofile "Maxima2.lua" -- (find-angg "LUA/Maxima2.lua") \pu ]==] usepackages.edrx21 = true dednat6["0"] = true dednat6.Maxima2 = true -- «show2-tests» (to ".show2-tests") --[==[ ** (find-Deps1-cps "Maxima2") * (show2-use "$SHOW2LATEXDIR/") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Maxima2.lua" = outertexbody = ([=[ % A low-level test without Dednat6. % See: (find-LATEX "edrx21.sty" "maximablue-red") \def\hboxthreewidth{4cm} \vbox{% \maximablue{(\%i1)\ 2*3;}% \maximared{(\%o1)\ }{}% \maximared{}{5}% } ]=]) :show {scale=1.5} = Show.log = Show.bigstr * (etv) --]==] -- «show2-tests-head» (to ".show2-tests-head") --[==[ ** (find-Deps1-cps "Maxima2") * (show2-use "$SHOW2LATEXDIR/") * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "Maxima2.lua" = outertexbody dednat6.Maxima2_test = [=[ % A test with Dednat6. % %M (%i1) 2*3; %M (%o1) 5 %L maximahead:sa("2 + 3", "") \pu \def\hboxthreewidth {6cm} ]=] = ([=[ \vbox{\ga{2 + 3}} ]=]) :show {scale=1.5} = Show.log = Show.bigstr * (etv) --]==] -- «show2-tests-prep» (to ".show2-tests-prep") --[[ ** (find-Maxima2-links "maxima-subst1") * (eepitch-maxima) * (eepitch-kill) * (eepitch-maxima) load("/usr/share/emacs/site-lisp/maxima/emaxima.lisp")$ load("~/MAXIMA/barematrix1.lisp")$ display2d:'emaxima$ linenum:0; /* PR: power rule * PRW: power rule, wrong version */ PR : 'diff(x^n,x) = n*x^(n-1); PRW : 'diff(x^n,x) = n*x^(n-1) + 10*n; subst([n=4], PR); subst([n=4], PRW); --]] -- Local Variables: -- coding: utf-8-unix -- End: