Greetings
Here is a simple REPL for use with LuaTeX. I started with work by Rob Hoelz <[email protected]> and cut out all the bells and whistles. To use it, save this to a lua file and load it. The REPL can be started by invoking repl(). I find this very handy to explore what is going on with LuaTeX. Robert P.S. I use this within Emacs. I assume it will work anywhere with a terminal type interface. ========== -- Copyright (c) 2011-2015 Rob Hoelz <[email protected]> -- -- Further hacked by others. -- -- Permission is hereby granted, free of charge, to any person -- obtaining a copy of this software and associated documentation -- files (the "Software"), to deal in the Software without -- restriction, including without limitation the rights to use, copy, -- modify, merge, publish, distribute, sublicense, and/or sell copies -- of the Software, and to permit persons to whom the Software is -- furnished to do so, subject to the following conditions: -- -- The above copyright notice and this permission notice shall be -- included in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -- SOFTWARE. -- @class repl --- This module implements the core functionality of a REPL. repl = {VERSION = 0.9 } repl_buffer = '' local error = error local function gather_results(success, ...) local n = select('#', ...) return success, { n = n, ... } end --- Uses the compilation error to determine whether or not further input --- is pending after the last line. That is, is this a fraction of a --- statement. --- Rather crude, but this seems to work. local function detectcontinue(err) return string.match(err, "'<eof>'$") or string.match(err, "<eof>$") end local function compilechunk(chunk) -- If this is an expression, rather than a statement, we should -- get a function, in f, to return the value of that expression. local f, err = load('return ' .. chunk, 'REPL') -- for statements (or fractions thereof). if not f then f, err = load(chunk, 'REPL') end return f, err end -- @param results The results to display. The results are a table, -- with the integer keys containing the results, and the 'n' key -- containing the highest integer key. local function displayresults(results) if results.n == 0 then return end print(table.unpack(results, 1, results.n)) end local function displayerror(err) print(err) end --- Evaluates a line of input, and displays return value(s). local function handleline(line) local chunk = repl_buffer .. line local f, err = compilechunk(chunk) if f then -- We have a (presumed) function. Try to call it, and display the -- results, or error. repl_buffer = '' local success, results = gather_results(xpcall(f, function(...) return debug.traceback(...) end)) if success then displayresults(results) else displayerror(results[1]) end else -- Is this a (presumed) fraction of a statement, or an error? if detectcontinue(err) then -- Presumably, a fraction of a statement. repl_buffer = chunk .. '\n' return 2 else -- An error. Clear the buffer, so this does not keep happening. repl_buffer = '' displayerror(err) end end return 1 end local function prompt(level) local prompt if level == 1 then prompt=">" else prompt=">>" end io.write(prompt) end --- Run a REPL loop in a synchronous fashion. function repl() print() prompt(1) for line in io.stdin:lines() do local level = handleline(line) prompt(level) end end
