<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>