Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file: EdrxRepl.lua - a REPL for Lua. -- https://github.com/edrx/emacs-lua/ -- http://angg.twu.net/emacs-lua/EdrxRepl.lua.html -- http://angg.twu.net/emacs-lua/EdrxRepl.lua -- (find-angg "emacs-lua/EdrxRepl.lua") -- -- In the HTML version the sexp hyperlinks work. -- See: (find-eev-quick-intro "3. Elisp hyperlinks") -- (find-eepitch-intro "3. Test blocks") -- -- Author: Eduardo Ochs <eduardoochs@gmail.com> -- Version: 20210918 -- License: GPL3 at this moment. -- If you need another license, get in touch! -- -- Some eev-isms: -- (defun o () (interactive) (find-angg "emacs-lua/README.org")) -- (defun r () (interactive) (find-angg "emacs-lua/EdrxRepl.lua")) -- (defun x () (interactive) (find-angg "emacs-lua/EdrxPcall.lua")) -- This file is being rewritten. -- The class EdrxRepl uses -- the class EdrxPcall, -- that is defined here: require "EdrxPcall" -- (find-angg "emacs-lua/EdrxPcall.lua") -- «.EdrxRepl» (to "EdrxRepl") -- «.EdrxRepl-emacs» (to "EdrxRepl-emacs") -- «.EdrxRepl-tests» (to "EdrxRepl-tests") -- «.dbg-tests» (to "dbg-tests") -- ____ _ -- | _ \ ___ _ __ | | -- | |_) / _ \ '_ \| | -- | _ < __/ |_) | | -- |_| \_\___| .__/|_| -- |_| -- -- «EdrxRepl» (to ".EdrxRepl") -- Also in: (find-angg "LUA/lua50init.lua" "Repl") -- A simple REPL for Lua that handles errors well enough. -- It uses EdrxPcall to run code. -- Usage: -- -- REPL = EdrxRepl:new(); REPL:repl() -- -- To exit the REPL set REPL.stop to true. -- -- NOTE ON '='s: The EdrxRepl class implements a trick that is found in -- the REPLs of Lua5.1 and Lua5.2 but was dropped from Lua5.3 onwards. -- It is explained in the manpages for lua5.1 and lua5.2 as: -- -- If a line starts with '=', then lua displays the values of all -- the expressions in the remainder of the line. The expressions -- must be separated by commas. -- -- In Lua5.3 they changed that to this (also copied from the manpage): -- -- If the line contains an expression or list of expressions, then -- the line is evaluated and the results are printed. -- -- See for example this thread: -- http://lua-users.org/lists/lua-l/2020-10/msg00209.html EdrxRepl = Class { type = "EdrxRepl", new = function () return EdrxRepl({}) end, __index = { bigstr = function (r) return table.concat(r.lines, "\n") end, code = function (r) return r:bigstr():gsub("^=", "return ") end, -- -- incompletep = function (r) return r:incompletep0(r:code()) end, -- incompletep0 = function (r, bigstr) -- local f, err = loadstring(bigstr) -- return (f == nil) and r:incompleteerrp(err) -- end, -- read00 = function (r, prompt) io.write(prompt); return io.read() end, read0 = function (r, prompt) table.insert(r.lines, r:read00(prompt)) end, read1 = function (r) return r:read0 ">>> " end, read2 = function (r) return r:read0 "... " end, read = function (r) r.lines = {} r:read1() while r:trapincomplete() do r:read2() end return r end, -- incompleteerrp = function (r, err) return err:find(" near '?<eof>'?$") end, trapincomplete = function (r) r.f, r.err = loadstring(r:code()) return (r.err and r:incompleteerrp(r.err)) and "[incomplete]" end, trapcomperror = function (r) r.f, r.err = loadstring(r:code()) return r.err and "[comp error]" end, trapexecerror = function (r) r.xpc = EdrxPcall.new():call(r.f) if not r.xpc:success() then r.err = r.xpc.err_msg r.tb = r.xpc:tbshorter() return "[exec error]" end end, printcomperror = function (r) print(r.err) end, printexecerror = function (r) print(r.err) end, readevalprint = function (r) r:read() if r:trapcomperror() then return r:printcomperror() end if r:trapexecerror() then return r:printexecerror() end if r:bigstr():match("^=") then print(r.xpc:outsuccess()) end end, -- -- The standard interface: repl = function (r) while not r.stop do r:readevalprint() end end, -- -- «EdrxRepl-emacs» (to ".EdrxRepl-emacs") -- The emacs interface: erepltest = function (r) while not r.stop do print(r:esend(r:read00(r:eprompt()))) end end, -- e0 = function (r) r.lines = {}; return r end, -- clear .lines eprompt = function (r) r.lines = r.lines or {} if #r.lines == 0 then return ">>> " else return "... " end end, etrapexecerror = function (r) r.xpc = EdrxPcall.new():prcall(r.f) if not r.xpc:success() then r.err = r.xpc.err_msg r.tb = r.xpc:tbshorter() return "[exec error]" end end, esend = function (r, line) table.insert(r.lines, line) if r: trapincomplete() then return r:eretincomplete() end if r: trapcomperror() then return r:e0():eretcomperror() end if r:etrapexecerror() then return r:e0():eretexecerror() end if r:bigstr():match("^=") then return r:e0():eretsuccessprint() else return r:e0():eretsuccessnonprint() end end, eretincomplete = function (r) return "(incomplete)" end, eretcomperror = function (r) return "(comp error)", r.err end, eretexecerror = function (r) return "(exec error)", r.xpc:prout(nil, "\n") end, eretsuccessprint = function (r) return "(success: =)", r.xpc:prout("=", "\n") end, eretsuccessnonprint = function (r) return "(success)", r.xpc:prout() end, }, } -- «EdrxRepl-tests» (to ".EdrxRepl-tests") -- (find-elisp-intro "5. Variables" "If you execute lines 1, 3, and 4") -- (find-angg "LUA/lua50init.lua") --[[ * (eepitch-shell) * (eepitch-kill) * (eepitch-shell) export LUA_INIT="" export LUA_INIT=@$HOME/LUA/lua50init.lua lua5.1 lua5.2 lua5.3 lua5.4 PP() * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "EdrxRepl.lua" REPL = EdrxRepl.new() -- REPL:repl() REPL:repl() print( 1+2 ) = 1+2 = 1, 2, 3 = 20, 30, nil, 40, nil REPL.stop = 1 * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "EdrxRepl.lua" REPL = EdrxRepl.new() REPL:erepltest() print( 1+2 ) = 1+2 = 1, 2, 3 = 20, 30, nil, 40, nil a = 22 a = a + 33 a = a + 200 = a = a + 2 + 3 = a + 2 + nil REPL.stop = 1 REPL.stop = 1 * (eepitch-lua51) * (eepitch-kill) * (eepitch-lua51) dofile "EdrxRepl.lua" EdrxPcall.__index.tb_e = 10 EdrxPcall.__index.tb_e = 5 EdrxPcall.__index.tb_e = 6 REPL = EdrxRepl.new() REPL:erepltest() = a + 2 + nil --]]