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